From 9d14b9c6b51f47dab04a3742e36ec1956a63d7a4 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Tue, 26 Aug 2025 19:19:40 -0700 Subject: [PATCH 1/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?= =?UTF-8?q?anges=20to=20main=20this=20commit=20is=20based=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.6-beta.1 [skip ci] --- clang/include/clang/Basic/LangOptions.def | 1 + clang/include/clang/Driver/Options.td | 5 + clang/lib/CodeGen/CodeGenModule.cpp | 20 ++-- clang/lib/Driver/ToolChains/Clang.cpp | 13 +++ clang/test/CodeGen/prefalign.c | 4 + clang/test/CodeGenCXX/member-alignment.cpp | 6 +- clang/test/Driver/prefalign.c | 5 + lld/test/ELF/lto/linker-script-symbols-ipo.ll | 2 +- llvm/docs/Extensions.rst | 15 +++ llvm/docs/LangRef.rst | 31 ++++-- llvm/include/llvm/AsmParser/LLParser.h | 2 +- llvm/include/llvm/AsmParser/LLToken.h | 1 + llvm/include/llvm/CodeGen/MachineFunction.h | 2 + llvm/include/llvm/IR/Function.h | 9 +- llvm/include/llvm/MC/MCAsmInfo.h | 4 + llvm/include/llvm/MC/MCObjectStreamer.h | 1 + llvm/include/llvm/MC/MCSection.h | 14 +++ llvm/include/llvm/MC/MCStreamer.h | 2 + llvm/lib/AsmParser/LLLexer.cpp | 1 + llvm/lib/AsmParser/LLParser.cpp | 23 ++-- llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 7 ++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 4 +- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 16 ++- llvm/lib/CodeGen/AsmPrinter/WinException.cpp | 4 +- llvm/lib/CodeGen/MachineFunction.cpp | 17 ++- llvm/lib/IR/AsmWriter.cpp | 2 + llvm/lib/MC/ELFObjectWriter.cpp | 8 +- llvm/lib/MC/MCAsmInfoELF.cpp | 1 + llvm/lib/MC/MCAsmStreamer.cpp | 6 + llvm/lib/MC/MCObjectStreamer.cpp | 4 + llvm/lib/MC/MCParser/AsmParser.cpp | 20 ++++ llvm/lib/MC/MCSection.cpp | 10 ++ llvm/lib/MC/MCStreamer.cpp | 1 + llvm/lib/Target/X86/X86AsmPrinter.cpp | 2 +- llvm/test/Bitcode/compatibility.ll | 14 +++ llvm/test/CodeGen/PowerPC/alloca-crspill.ll | 2 +- llvm/test/CodeGen/X86/prefalign.ll | 27 +++++ llvm/test/MC/ELF/prefalign-errors.s | 5 + llvm/test/MC/ELF/prefalign.s | 104 ++++++++++++++++++ .../SampleProfile/pseudo-probe-emit.ll | 4 +- 40 files changed, 370 insertions(+), 49 deletions(-) create mode 100644 clang/test/CodeGen/prefalign.c create mode 100644 clang/test/Driver/prefalign.c create mode 100644 llvm/test/CodeGen/X86/prefalign.ll create mode 100644 llvm/test/MC/ELF/prefalign-errors.s create mode 100644 llvm/test/MC/ELF/prefalign.s diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index f094ba112988f..19bdc43abaac0 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -418,6 +418,7 @@ ENUM_LANGOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest, NotCompatible, "with") VALUE_LANGOPT(FunctionAlignment, 5, 0, Compatible, "Default alignment for functions") +VALUE_LANGOPT(PreferredFunctionAlignment, 5, 0, Compatible, "Preferred alignment for functions") VALUE_LANGOPT(LoopAlignment, 32, 0, Compatible, "Default alignment for loops") LANGOPT(FixedPoint, 1, 0, NotCompatible, "fixed point types") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 82e8212bee12d..2dfc0872bac1f 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1550,6 +1550,8 @@ defm access_control : BoolFOption<"access-control", PosFlag>; def falign_functions : Flag<["-"], "falign-functions">, Group; def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group; +def fpreferred_function_alignment_EQ : + Joined<["-"], "fpreferred-function-alignment=">, Group; def falign_loops_EQ : Joined<["-"], "falign-loops=">, Group, Visibility<[ClangOption, CC1Option]>, MetaVarName<"">, HelpText<"N must be a power of two. Align loops to the boundary">, @@ -8446,6 +8448,9 @@ def fencode_extended_block_signature : Flag<["-"], "fencode-extended-block-signa def function_alignment : Separate<["-"], "function-alignment">, HelpText<"default alignment for functions">, MarshallingInfoInt>; +def preferred_function_alignment : Separate<["-"], "preferred-function-alignment">, + HelpText<"preferred alignment for functions">, + MarshallingInfoInt>; def fhalf_no_semantic_interposition : Flag<["-"], "fhalf-no-semantic-interposition">, HelpText<"Like -fno-semantic-interposition but don't use local aliases">, MarshallingInfoFlag>; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 7064421fe0613..e7d94ed878e10 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2794,13 +2794,19 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, F->addFnAttrs(B); - unsigned alignment = D->getMaxAlignment() / Context.getCharWidth(); - if (alignment) - F->setAlignment(llvm::Align(alignment)); - - if (!D->hasAttr()) - if (LangOpts.FunctionAlignment) - F->setAlignment(llvm::Align(1ull << LangOpts.FunctionAlignment)); + llvm::MaybeAlign ExplicitAlignment; + if (unsigned alignment = D->getMaxAlignment() / Context.getCharWidth()) + ExplicitAlignment = llvm::Align(alignment); + else if (LangOpts.FunctionAlignment) + ExplicitAlignment = llvm::Align(1ull << LangOpts.FunctionAlignment); + + if (ExplicitAlignment) { + F->setAlignment(ExplicitAlignment); + F->setPreferredAlignment(ExplicitAlignment); + } else if (LangOpts.PreferredFunctionAlignment) { + F->setPreferredAlignment( + llvm::Align(1ull << LangOpts.PreferredFunctionAlignment)); + } // Some C++ ABIs require 2-byte alignment for member functions, in order to // reserve a bit for differentiating between virtual and non-virtual member diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 1b44090534e82..c2ab8d9318a33 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -46,6 +46,7 @@ #include "llvm/Support/Compression.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/YAMLParser.h" @@ -5503,6 +5504,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(std::to_string(FunctionAlignment))); } + if (const Arg *A = Args.getLastArg(options::OPT_fpreferred_function_alignment_EQ)) { + unsigned Value = 0; + if (StringRef(A->getValue()).getAsInteger(10, Value) || Value > 65536 || + !llvm::isPowerOf2_32(Value)) + TC.getDriver().Diag(diag::err_drv_invalid_int_value) + << A->getAsString(Args) << A->getValue(); + + CmdArgs.push_back("-preferred-function-alignment"); + CmdArgs.push_back(Args.MakeArgString( + std::to_string(llvm::Log2_32_Ceil(std::min(Value, 65536u))))); + } + // We support -falign-loops=N where N is a power of 2. GCC supports more // forms. if (const Arg *A = Args.getLastArg(options::OPT_falign_loops_EQ)) { diff --git a/clang/test/CodeGen/prefalign.c b/clang/test/CodeGen/prefalign.c new file mode 100644 index 0000000000000..2370585a8e457 --- /dev/null +++ b/clang/test/CodeGen/prefalign.c @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-linux -preferred-function-alignment 4 %s -o - | FileCheck %s + +// CHECK: define {{.*}} void @f() {{.*}} prefalign 16 +void f() {} diff --git a/clang/test/CodeGenCXX/member-alignment.cpp b/clang/test/CodeGenCXX/member-alignment.cpp index d5c9a5a02b160..37ee733e18ff5 100644 --- a/clang/test/CodeGenCXX/member-alignment.cpp +++ b/clang/test/CodeGenCXX/member-alignment.cpp @@ -31,9 +31,9 @@ class t { [[gnu::aligned(16)]] void t::baz(void) { -// CHECK-NOEXTRAALIGN: @_ZN1t3bazEv({{.*}}) #0 align 16 { -// CHECK-EXTRAALIGN: @_ZN1t3bazEv({{.*}}) #0 align 16 { -// CHECK-MSVC: @"?baz@t@@QEAAXXZ"({{.*}}) #0 align 16 { +// CHECK-NOEXTRAALIGN: @_ZN1t3bazEv({{.*}}) #0 align 16 prefalign 16 { +// CHECK-EXTRAALIGN: @_ZN1t3bazEv({{.*}}) #0 align 16 prefalign 16 { +// CHECK-MSVC: @"?baz@t@@QEAAXXZ"({{.*}}) #0 align 16 prefalign 16 { } void diff --git a/clang/test/Driver/prefalign.c b/clang/test/Driver/prefalign.c new file mode 100644 index 0000000000000..de52f2dcf28bc --- /dev/null +++ b/clang/test/Driver/prefalign.c @@ -0,0 +1,5 @@ +// RUN: %clang -### -fpreferred-function-alignment=16 %s 2>&1 | FileCheck %s -check-prefix CHECK-16 +// RUN: not %clang -### -fpreferred-function-alignment=3 %s 2>&1 | FileCheck %s -check-prefix CHECK-INVALID + +// CHECK-16: "-preferred-function-alignment" "4" +// CHECK-INVALID: invalid integral value '3' in '-fpreferred-function-alignment=3' diff --git a/lld/test/ELF/lto/linker-script-symbols-ipo.ll b/lld/test/ELF/lto/linker-script-symbols-ipo.ll index 414ee4080bee0..39996cbfa28db 100644 --- a/lld/test/ELF/lto/linker-script-symbols-ipo.ll +++ b/lld/test/ELF/lto/linker-script-symbols-ipo.ll @@ -18,7 +18,7 @@ ; NOIPO: : ; NOIPO-NEXT: movl $2, %eax ; NOIPO: <_start>: -; NOIPO-NEXT: jmp 0x201160 +; NOIPO-NEXT: jmp 0x201158 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/docs/Extensions.rst b/llvm/docs/Extensions.rst index 6b1d9fe08e911..64216981d5a1f 100644 --- a/llvm/docs/Extensions.rst +++ b/llvm/docs/Extensions.rst @@ -28,6 +28,21 @@ hexadecimal format instead of decimal if desired. .section .data .float 0x1c2.2ap3 +``.prefalign`` directive +------------------------ + +The ``.prefalign`` directive sets the preferred alignment for a section, +and enables the section's final alignment to be set in a way that is +dependent on the section size (currently only supported with ELF). + +If the section size is less than the section's minimum alignment as +determined using ``.align`` family directives, the section's alignment +will be equal to its minimum alignment. Otherwise, if the section size is +between the minimum alignment and the preferred alignment, the section's +alignment will be equal to the power of 2 greater than or equal to the +section size. Otherwise, the section's alignment will be equal to the +preferred alignment. + Machine-specific Assembly Syntax ================================ diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index b122fd352eaf5..80f9b7c150b67 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -877,7 +877,9 @@ an optional ``unnamed_addr`` attribute, a return type, an optional name, a (possibly empty) argument list (each with optional :ref:`parameter attributes `), optional :ref:`function attributes `, an optional address space, an optional section, an optional partition, -an optional alignment, an optional :ref:`comdat `, +an optional minimum alignment, +an optional preferred alignment, +an optional :ref:`comdat `, an optional :ref:`garbage collector name `, an optional :ref:`prefix `, an optional :ref:`prologue `, an optional :ref:`personality `, @@ -891,8 +893,8 @@ Syntax:: @ ([argument list]) [(unnamed_addr|local_unnamed_addr)] [AddrSpace] [fn Attrs] [section "name"] [partition "name"] [comdat [($name)]] [align N] - [gc] [prefix Constant] [prologue Constant] [personality Constant] - (!name !N)* { ... } + [prefalign N] [gc] [prefix Constant] [prologue Constant] + [personality Constant] (!name !N)* { ... } The argument list is a comma-separated sequence of arguments where each argument is of the following form: @@ -942,11 +944,24 @@ LLVM allows an explicit section to be specified for functions. If the target supports it, it will emit functions to the section specified. Additionally, the function can be placed in a COMDAT. -An explicit alignment may be specified for a function. If not present, -or if the alignment is set to zero, the alignment of the function is set -by the target to whatever it feels convenient. If an explicit alignment -is specified, the function is forced to have at least that much -alignment. All alignments must be a power of 2. +An explicit minimum alignment (``align``) may be specified for a +function. If not present, or if the alignment is set to zero, the +alignment of the function is set according to the preferred alignment +rules described below. If an explicit minimum alignment is specified, the +function is forced to have at least that much alignment. All alignments +must be a power of 2. + +An explicit preferred alignment (``prefalign``) may also be specified +for a function (definitions only, and must be a power of 2). If a +function does not have a preferred alignment attribute, the preferred +alignment is determined in a target-specific way. The final alignment +of the function is determined in the following way: if the function +size is less than the minimum alignment, the function's alignment will +be at least the minimum alignment. Otherwise, if the function size is +between the minimum alignment and the preferred alignment, the function's +alignment will be at least the power of 2 greater than or equal to the +function size. Otherwise, the function's alignment will be at least the +preferred alignment. If the ``unnamed_addr`` attribute is given, the address is known to not be significant and two identical functions can be merged. diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h index c01de4a289a69..5970b388b6bcd 100644 --- a/llvm/include/llvm/AsmParser/LLParser.h +++ b/llvm/include/llvm/AsmParser/LLParser.h @@ -311,7 +311,7 @@ namespace llvm { GlobalValueSummary::ImportKind &Res); void parseOptionalDLLStorageClass(unsigned &Res); bool parseOptionalCallingConv(unsigned &CC); - bool parseOptionalAlignment(MaybeAlign &Alignment, + bool parseOptionalAlignment(lltok::Kind KW, MaybeAlign &Alignment, bool AllowParens = false); bool parseOptionalCodeModel(CodeModel::Model &model); bool parseOptionalDerefAttrBytes(lltok::Kind AttrKind, uint64_t &Bytes); diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h index e6a0eae9da30c..65d52747abc62 100644 --- a/llvm/include/llvm/AsmParser/LLToken.h +++ b/llvm/include/llvm/AsmParser/LLToken.h @@ -130,6 +130,7 @@ enum Kind { kw_prefix, kw_prologue, kw_c, + kw_prefalign, kw_cc, kw_ccc, diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h index ef783f276b7d4..a454ad02df23d 100644 --- a/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/llvm/include/llvm/CodeGen/MachineFunction.h @@ -818,6 +818,8 @@ class LLVM_ABI MachineFunction { Alignment = A; } + Align getPreferredAlignment() const; + /// exposesReturnsTwice - Returns true if the function calls setjmp or /// any other similar functions with attribute "returns twice" without /// having the attribute itself. diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h index d3497716ca844..0f9f526556847 100644 --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -85,7 +85,8 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node { unsigned BlockNumEpoch = 0; mutable Argument *Arguments = nullptr; ///< The formal arguments - size_t NumArgs; + uint32_t NumArgs; + MaybeAlign PreferredAlign; std::unique_ptr SymTab; ///< Symbol table of args/instructions AttributeList AttributeSets; ///< Parameter attributes @@ -1043,6 +1044,12 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node { /// defined. void setAlignment(MaybeAlign Align) { GlobalObject::setAlignment(Align); } + /// Returns the prefalign of the given function. + MaybeAlign getPreferredAlignment() const { return PreferredAlign; } + + /// Sets the prefalign attribute of the Function. + void setPreferredAlignment(MaybeAlign Align) { PreferredAlign = Align; } + /// Return the value for vscale based on the vscale_range attribute or 0 when /// unknown. unsigned getVScaleValue() const; diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h index 6c12cd347901a..af52e302fe3d1 100644 --- a/llvm/include/llvm/MC/MCAsmInfo.h +++ b/llvm/include/llvm/MC/MCAsmInfo.h @@ -301,6 +301,9 @@ class LLVM_ABI MCAsmInfo { // most targets, so defaults to true. bool HasFunctionAlignment = true; + // True if the target respects .prefalign directives. + bool HasPreferredAlignment = false; + /// True if the target has .type and .size directives, this is true for most /// ELF targets. Defaults to true. bool HasDotTypeDotSizeDirective = true; @@ -603,6 +606,7 @@ class LLVM_ABI MCAsmInfo { } bool hasFunctionAlignment() const { return HasFunctionAlignment; } + bool hasPreferredAlignment() const { return HasPreferredAlignment; } bool hasDotTypeDotSizeDirective() const { return HasDotTypeDotSizeDirective; } bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } bool hasIdentDirective() const { return HasIdentDirective; } diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index b9e813b9b0d28..5f5c5049e4eff 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -137,6 +137,7 @@ class MCObjectStreamer : public MCStreamer { unsigned MaxBytesToEmit = 0) override; void emitCodeAlignment(Align ByteAlignment, const MCSubtargetInfo *STI, unsigned MaxBytesToEmit = 0) override; + void emitPrefAlign(Align Alignment) override; void emitValueToOffset(const MCExpr *Offset, unsigned char Value, SMLoc Loc) override; void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, diff --git a/llvm/include/llvm/MC/MCSection.h b/llvm/include/llvm/MC/MCSection.h index 12389d623e588..f8b9c388f4942 100644 --- a/llvm/include/llvm/MC/MCSection.h +++ b/llvm/include/llvm/MC/MCSection.h @@ -525,6 +525,7 @@ class LLVM_ABI MCSection { MCSymbol *End = nullptr; /// The alignment requirement of this section. Align Alignment; + MaybeAlign PreferredAlignment; /// The section index in the assemblers section list. unsigned Ordinal = 0; // If not -1u, the first linker-relaxable fragment's order within the @@ -585,6 +586,19 @@ class LLVM_ABI MCSection { Alignment = MinAlignment; } + Align getPreferredAlignment() const { + if (!PreferredAlignment || Alignment > *PreferredAlignment) + return Alignment; + return *PreferredAlignment; + } + + void ensurePreferredAlignment(Align PrefAlign) { + if (!PreferredAlignment || PrefAlign > *PreferredAlignment) + PreferredAlignment = PrefAlign; + } + + Align getAlignmentForObjectFile(uint64_t Size) const; + unsigned getOrdinal() const { return Ordinal; } void setOrdinal(unsigned Value) { Ordinal = Value; } diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 79c715e3820a6..0cc42f0995e5b 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -839,6 +839,8 @@ class LLVM_ABI MCStreamer { virtual void emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI, unsigned MaxBytesToEmit = 0); + virtual void emitPrefAlign(Align A); + /// Emit some number of copies of \p Value until the byte offset \p /// Offset is reached. /// diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 3d5bd6155536e..e51ab2c584770 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -625,6 +625,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(gc); KEYWORD(prefix); KEYWORD(prologue); + KEYWORD(prefalign); KEYWORD(no_sanitize_address); KEYWORD(no_sanitize_hwaddress); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 1bc2906f63b07..415a7b99a3c80 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -1449,7 +1449,7 @@ bool LLParser::parseGlobal(const std::string &Name, unsigned NameID, return true; } else if (Lex.getKind() == lltok::kw_align) { MaybeAlign Alignment; - if (parseOptionalAlignment(Alignment)) + if (parseOptionalAlignment(lltok::kw_align, Alignment)) return true; if (Alignment) GV->setAlignment(*Alignment); @@ -1548,7 +1548,7 @@ bool LLParser::parseEnumAttribute(Attribute::AttrKind Attr, AttrBuilder &B, return true; Alignment = Align(Value); } else { - if (parseOptionalAlignment(Alignment, true)) + if (parseOptionalAlignment(lltok::kw_align, Alignment, true)) return true; } B.addAlignmentAttr(Alignment); @@ -2382,10 +2382,11 @@ bool LLParser::parseOptionalFunctionMetadata(Function &F) { /// parseOptionalAlignment /// ::= /* empty */ -/// ::= 'align' 4 -bool LLParser::parseOptionalAlignment(MaybeAlign &Alignment, bool AllowParens) { +/// ::= KW 4 +bool LLParser::parseOptionalAlignment(lltok::Kind KW, MaybeAlign &Alignment, + bool AllowParens) { Alignment = std::nullopt; - if (!EatIfPresent(lltok::kw_align)) + if (!EatIfPresent(KW)) return false; LocTy AlignLoc = Lex.getLoc(); uint64_t Value = 0; @@ -2695,7 +2696,7 @@ bool LLParser::parseOptionalCommaAlign(MaybeAlign &Alignment, if (Lex.getKind() != lltok::kw_align) return error(Lex.getLoc(), "expected metadata or 'align'"); - if (parseOptionalAlignment(Alignment)) + if (parseOptionalAlignment(lltok::kw_align, Alignment)) return true; } @@ -6705,7 +6706,7 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine, LocTy BuiltinLoc; std::string Section; std::string Partition; - MaybeAlign Alignment; + MaybeAlign Alignment, PrefAlignment; std::string GC; GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::None; unsigned AddrSpace = 0; @@ -6722,7 +6723,8 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine, (EatIfPresent(lltok::kw_section) && parseStringConstant(Section)) || (EatIfPresent(lltok::kw_partition) && parseStringConstant(Partition)) || parseOptionalComdat(FunctionName, C) || - parseOptionalAlignment(Alignment) || + parseOptionalAlignment(lltok::kw_align, Alignment) || + parseOptionalAlignment(lltok::kw_prefalign, PrefAlignment) || (EatIfPresent(lltok::kw_gc) && parseStringConstant(GC)) || (EatIfPresent(lltok::kw_prefix) && parseGlobalTypeAndValue(Prefix)) || (EatIfPresent(lltok::kw_prologue) && parseGlobalTypeAndValue(Prologue)) || @@ -6824,6 +6826,7 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine, Fn->setUnnamedAddr(UnnamedAddr); if (Alignment) Fn->setAlignment(*Alignment); + Fn->setPreferredAlignment(PrefAlignment); Fn->setSection(Section); Fn->setPartition(Partition); Fn->setComdat(C); @@ -8446,7 +8449,7 @@ int LLParser::parseAlloc(Instruction *&Inst, PerFunctionState &PFS) { bool AteExtraComma = false; if (EatIfPresent(lltok::comma)) { if (Lex.getKind() == lltok::kw_align) { - if (parseOptionalAlignment(Alignment)) + if (parseOptionalAlignment(lltok::kw_align, Alignment)) return true; if (parseOptionalCommaAddrSpace(AddrSpace, ASLoc, AteExtraComma)) return true; @@ -8461,7 +8464,7 @@ int LLParser::parseAlloc(Instruction *&Inst, PerFunctionState &PFS) { return true; if (EatIfPresent(lltok::comma)) { if (Lex.getKind() == lltok::kw_align) { - if (parseOptionalAlignment(Alignment)) + if (parseOptionalAlignment(lltok::kw_align, Alignment)) return true; if (parseOptionalCommaAddrSpace(AddrSpace, ASLoc, AteExtraComma)) return true; diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 22a0d0ffdbaab..abdd58eeed612 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -4385,6 +4385,13 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef Record) { Func->setPartition(StringRef(Strtab.data() + Record[17], Record[18])); } + if (Record.size() > 19) { + MaybeAlign PrefAlignment; + if (Error Err = parseAlignmentValue(Record[19], PrefAlignment)) + return Err; + Func->setPreferredAlignment(PrefAlignment); + } + ValueList.push_back(Func, getVirtualTypeID(Func->getType(), FTyID)); if (OperandInfo.PersonalityFn || OperandInfo.Prefix || OperandInfo.Prologue) diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index a1d5b36bde64d..edb125a214405 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1644,7 +1644,8 @@ void ModuleBitcodeWriter::writeModuleInfo() { // FUNCTION: [strtab offset, strtab size, type, callingconv, isproto, // linkage, paramattrs, alignment, section, visibility, gc, // unnamed_addr, prologuedata, dllstorageclass, comdat, - // prefixdata, personalityfn, DSO_Local, addrspace] + // prefixdata, personalityfn, DSO_Local, addrspace, + // partition_strtab, partition_size, prefalign] Vals.push_back(addToStrtab(F.getName())); Vals.push_back(F.getName().size()); Vals.push_back(VE.getTypeID(F.getFunctionType())); @@ -1671,6 +1672,7 @@ void ModuleBitcodeWriter::writeModuleInfo() { Vals.push_back(F.getAddressSpace()); Vals.push_back(addToStrtab(F.getPartition())); Vals.push_back(F.getPartition().size()); + Vals.push_back(getEncodedAlign(F.getPreferredAlignment())); unsigned AbbrevToUse = 0; Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index cd14a4f57f760..25037651b92ea 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -977,8 +977,20 @@ void AsmPrinter::emitFunctionHeader() { emitVisibility(CurrentFnSym, F.getVisibility()); emitLinkage(&F, CurrentFnSym); - if (MAI->hasFunctionAlignment()) - emitAlignment(MF->getAlignment(), &F); + if (MAI->hasFunctionAlignment()) { + // The preferred alignment directive will not have the intended effect + // unless function sections are enabled. + if (MAI->useIntegratedAssembler() && MAI->hasPreferredAlignment() && + TM.getFunctionSections()) { + Align Alignment = MF->getAlignment(); + Align PrefAlignment = MF->getPreferredAlignment(); + emitAlignment(Alignment, &F); + if (Alignment != PrefAlignment) + OutStreamer->emitPrefAlign(PrefAlignment); + } else { + emitAlignment(MF->getPreferredAlignment(), &F); + } + } if (MAI->hasDotTypeDotSizeDirective()) OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction); diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp index 13fd270ec7410..90d8196ffb82a 100644 --- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp @@ -204,8 +204,8 @@ void WinException::beginFunclet(const MachineBasicBlock &MBB, // We want our funclet's entry point to be aligned such that no nops will be // present after the label. - Asm->emitAlignment(std::max(Asm->MF->getAlignment(), MBB.getAlignment()), - &F); + Asm->emitAlignment( + std::max(Asm->MF->getPreferredAlignment(), MBB.getAlignment()), &F); // Now that we've emitted the alignment directive, point at our funclet. Asm->OutStreamer->emitLabel(Sym); diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp index 224231cb90fe2..eabe1a510d92d 100644 --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -211,11 +211,6 @@ void MachineFunction::init() { ConstantPool = new (Allocator) MachineConstantPool(getDataLayout()); Alignment = STI.getTargetLowering()->getMinFunctionAlignment(); - // FIXME: Shouldn't use pref alignment if explicit alignment is set on F. - if (!F.hasOptSize()) - Alignment = std::max(Alignment, - STI.getTargetLowering()->getPrefFunctionAlignment()); - // -fsanitize=function and -fsanitize=kcfi instrument indirect function calls // to load a type hash before the function label. Ensure functions are aligned // by a least 4 to avoid unaligned access, which is especially important for @@ -330,6 +325,18 @@ bool MachineFunction::shouldSplitStack() const { return getFunction().hasFnAttribute("split-stack"); } +Align MachineFunction::getPreferredAlignment() const { + Align PrefAlignment = Align(1); + + if (!F.hasOptSize()) + PrefAlignment = STI.getTargetLowering()->getPrefFunctionAlignment(); + + if (MaybeAlign A = F.getPreferredAlignment()) + PrefAlignment = *A; + + return std::max(PrefAlignment, getAlignment()); +} + [[nodiscard]] unsigned MachineFunction::addFrameInst(const MCCFIInstruction &Inst) { FrameInstructions.push_back(Inst); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index dc6d599fa9585..3d3d3ba2eee33 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -4229,6 +4229,8 @@ void AssemblyWriter::printFunction(const Function *F) { maybePrintComdat(Out, *F); if (MaybeAlign A = F->getAlign()) Out << " align " << A->value(); + if (MaybeAlign A = F->getPreferredAlignment()) + Out << " prefalign " << A->value(); if (F->hasGC()) Out << " gc \"" << F->getGC() << '"'; if (F->hasPrefixData()) { diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index 759d3e0e14291..3d7f503bf08b0 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -912,10 +912,10 @@ void ELFWriter::writeSectionHeader(uint32_t GroupSymbolIndex, uint64_t Offset, sh_link = Sym->getSection().getOrdinal(); } - writeSectionHeaderEntry(StrTabBuilder.getOffset(Section.getName()), - Section.getType(), Section.getFlags(), 0, Offset, - Size, sh_link, sh_info, Section.getAlign(), - Section.getEntrySize()); + writeSectionHeaderEntry( + StrTabBuilder.getOffset(Section.getName()), Section.getType(), + Section.getFlags(), 0, Offset, Size, sh_link, sh_info, + Section.getAlignmentForObjectFile(Size), Section.getEntrySize()); } void ELFWriter::writeSectionHeaders() { diff --git a/llvm/lib/MC/MCAsmInfoELF.cpp b/llvm/lib/MC/MCAsmInfoELF.cpp index cdae9d7860f33..cb5244fc4649e 100644 --- a/llvm/lib/MC/MCAsmInfoELF.cpp +++ b/llvm/lib/MC/MCAsmInfoELF.cpp @@ -41,6 +41,7 @@ bool MCAsmInfoELF::useCodeAlign(const MCSection &Sec) const { MCAsmInfoELF::MCAsmInfoELF() { HasIdentDirective = true; + HasPreferredAlignment = true; WeakRefDirective = "\t.weak\t"; PrivateGlobalPrefix = ".L"; PrivateLabelPrefix = ".L"; diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index be8c022f39ad1..47002dbcd1728 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -274,6 +274,7 @@ class MCAsmStreamer final : public MCStreamer { void emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI, unsigned MaxBytesToEmit = 0) override; + void emitPrefAlign(Align Alignment) override; void emitValueToOffset(const MCExpr *Offset, unsigned char Value, @@ -1540,6 +1541,11 @@ void MCAsmStreamer::emitCodeAlignment(Align Alignment, emitAlignmentDirective(Alignment.value(), std::nullopt, 1, MaxBytesToEmit); } +void MCAsmStreamer::emitPrefAlign(Align Alignment) { + OS << "\t.prefalign\t" << Alignment.value(); + EmitEOL(); +} + void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value, SMLoc Loc) { diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 59265bc8595ba..f638783c56bdb 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -664,6 +664,10 @@ void MCObjectStreamer::emitCodeAlignment(Align Alignment, F->STI = STI; } +void MCObjectStreamer::emitPrefAlign(Align Alignment) { + getCurrentSectionOnly()->ensurePreferredAlignment(Alignment); +} + void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value, SMLoc Loc) { diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index fb183a10b3d37..ad3a1dc91fbd3 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -418,6 +418,7 @@ class AsmParser : public MCAsmParser { DK_P2ALIGN, DK_P2ALIGNW, DK_P2ALIGNL, + DK_PREFALIGN, DK_ORG, DK_FILL, DK_ENDR, @@ -565,6 +566,7 @@ class AsmParser : public MCAsmParser { bool parseDirectiveOrg(); // ".org" // ".align{,32}", ".p2align{,w,l}" bool parseDirectiveAlign(bool IsPow2, uint8_t ValueSize); + bool parseDirectivePrefAlign(); // ".file", ".line", ".loc", ".loc_label", ".stabs" bool parseDirectiveFile(SMLoc DirectiveLoc); @@ -2002,6 +2004,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2); case DK_P2ALIGNL: return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4); + case DK_PREFALIGN: + return parseDirectivePrefAlign(); case DK_ORG: return parseDirectiveOrg(); case DK_FILL: @@ -3427,6 +3431,21 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, uint8_t ValueSize) { return ReturnVal; } +bool AsmParser::parseDirectivePrefAlign() { + SMLoc AlignmentLoc = getLexer().getLoc(); + int64_t Alignment; + if (checkForValidSection() || parseAbsoluteExpression(Alignment)) + return true; + if (parseEOL()) + return true; + + if (!isPowerOf2_64(Alignment)) + return Error(AlignmentLoc, "alignment must be a power of 2"); + getStreamer().emitPrefAlign(Align(Alignment)); + + return false; +} + /// parseDirectiveFile /// ::= .file filename /// ::= .file number [directory] filename [md5 checksum] [source source-text] @@ -5381,6 +5400,7 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".p2align"] = DK_P2ALIGN; DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW; DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL; + DirectiveKindMap[".prefalign"] = DK_PREFALIGN; DirectiveKindMap[".org"] = DK_ORG; DirectiveKindMap[".fill"] = DK_FILL; DirectiveKindMap[".zero"] = DK_ZERO; diff --git a/llvm/lib/MC/MCSection.cpp b/llvm/lib/MC/MCSection.cpp index a668e7919b7b9..8285379eeaf81 100644 --- a/llvm/lib/MC/MCSection.cpp +++ b/llvm/lib/MC/MCSection.cpp @@ -30,6 +30,16 @@ MCSymbol *MCSection::getEndSymbol(MCContext &Ctx) { return End; } +Align MCSection::getAlignmentForObjectFile(uint64_t Size) const { + if (Size < getAlign().value()) + return getAlign(); + + if (Size < getPreferredAlignment().value()) + return Align(NextPowerOf2(Size - 1)); + + return getPreferredAlignment(); +} + bool MCSection::hasEnded() const { return End && End->isInSection(); } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index bc7398120096e..f33e4348dc9ad 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -1339,6 +1339,7 @@ void MCStreamer::emitFill(const MCExpr &NumBytes, uint64_t Value, SMLoc Loc) {} void MCStreamer::emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr, SMLoc Loc) {} void MCStreamer::emitValueToAlignment(Align, int64_t, uint8_t, unsigned) {} +void MCStreamer::emitPrefAlign(Align A) {} void MCStreamer::emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI, unsigned MaxBytesToEmit) {} void MCStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value, diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp index d406277e440bb..0912afa098b75 100644 --- a/llvm/lib/Target/X86/X86AsmPrinter.cpp +++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp @@ -155,7 +155,7 @@ void X86AsmPrinter::EmitKCFITypePadding(const MachineFunction &MF, if (HasType) PrefixBytes += 5; - emitNops(offsetToAlignment(PrefixBytes, MF.getAlignment())); + emitNops(offsetToAlignment(PrefixBytes, MF.getPreferredAlignment())); } /// emitKCFITypeId - Emit the KCFI type information in architecture specific diff --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll index 0b5ce08c00a23..b02cf1feed04e 100644 --- a/llvm/test/Bitcode/compatibility.ll +++ b/llvm/test/Bitcode/compatibility.ll @@ -759,6 +759,20 @@ declare void @f.align4() align 4 declare void @f.align8() align 8 ; CHECK: declare void @f.align8() align 8 +; Functions -- prefalign +define void @f.prefalign2() prefalign 2 { + ret void +} +; CHECK: define void @f.prefalign2() prefalign 2 +define void @f.prefalign4() prefalign 4 { + ret void +} +; CHECK: define void @f.prefalign4() prefalign 4 +define void @f.prefalign8() prefalign 8 { + ret void +} +; CHECK: define void @f.prefalign8() prefalign 8 + ; Functions -- GC declare void @f.gcshadow() gc "shadow-stack" ; CHECK: declare void @f.gcshadow() gc "shadow-stack" diff --git a/llvm/test/CodeGen/PowerPC/alloca-crspill.ll b/llvm/test/CodeGen/PowerPC/alloca-crspill.ll index cbcfd9a6a0dab..bd88b5d89202d 100644 --- a/llvm/test/CodeGen/PowerPC/alloca-crspill.ll +++ b/llvm/test/CodeGen/PowerPC/alloca-crspill.ll @@ -26,7 +26,7 @@ entry: declare signext i32 @do_something(ptr) ; CHECK: name: test -; CHECK: alignment: 16 +; CHECK: alignment: 4 ; CHECK: liveins: ; CHECK64: - { reg: '$x3', virtual-reg: '' } ; CHECK32: - { reg: '$r3', virtual-reg: '' } diff --git a/llvm/test/CodeGen/X86/prefalign.ll b/llvm/test/CodeGen/X86/prefalign.ll new file mode 100644 index 0000000000000..9a775bc328c60 --- /dev/null +++ b/llvm/test/CodeGen/X86/prefalign.ll @@ -0,0 +1,27 @@ +; RUN: llc < %s | FileCheck --check-prefixes=CHECK,NOFS %s +; RUN: llc -function-sections < %s | FileCheck --check-prefixes=CHECK,FS %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; CHECK: .globl f1 +; NOFS-NEXT: .p2align 4 +; FS-NEXT: .prefalign 16 +define void @f1() { + ret void +} + +; CHECK: .globl f2 +; CHECK-NOT: .prefalign +; CHECK-NOT: .p2align +define void @f2() prefalign 1 { + ret void +} + +; CHECK: .globl f3 +; NOFS-NEXT: .p2align 2 +; FS-NEXT: .p2align 1 +; FS-NEXT: .prefalign 4 +define void @f3() align 2 prefalign 4 { + ret void +} diff --git a/llvm/test/MC/ELF/prefalign-errors.s b/llvm/test/MC/ELF/prefalign-errors.s new file mode 100644 index 0000000000000..363638f9bcb1e --- /dev/null +++ b/llvm/test/MC/ELF/prefalign-errors.s @@ -0,0 +1,5 @@ +// RUN: not llvm-mc -filetype=asm -triple x86_64-pc-linux-gnu %s -o - 2>&1 | FileCheck %s + +.section .text.f1,"ax",@progbits +// CHECK: error: alignment must be a power of 2 +.prefalign 3 diff --git a/llvm/test/MC/ELF/prefalign.s b/llvm/test/MC/ELF/prefalign.s new file mode 100644 index 0000000000000..0732b64292ab2 --- /dev/null +++ b/llvm/test/MC/ELF/prefalign.s @@ -0,0 +1,104 @@ +// RUN: llvm-mc -filetype=asm -triple x86_64-pc-linux-gnu %s -o - | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | llvm-readelf -SW - | FileCheck --check-prefix=OBJ %s + +// Minimum alignment >= preferred alignment, no effect on sh_addralign. +// ASM: .section .text.f1lt +// ASM: .p2align 2 +// ASM: .prefalign 2 +// OBJ: .text.f1lt PROGBITS 0000000000000000 000040 000003 00 AX 0 0 4 +.section .text.f1lt,"ax",@progbits +.p2align 2 +.prefalign 2 +.rept 3 +nop +.endr + +// ASM: .section .text.f1eq +// ASM: .p2align 2 +// ASM: .prefalign 2 +// OBJ: .text.f1eq PROGBITS 0000000000000000 000044 000004 00 AX 0 0 4 +.section .text.f1eq,"ax",@progbits +.p2align 2 +.prefalign 2 +.rept 4 +nop +.endr + +// ASM: .section .text.f1gt +// ASM: .p2align 2 +// ASM: .prefalign 2 +// OBJ: .text.f1gt PROGBITS 0000000000000000 000048 000005 00 AX 0 0 4 +.section .text.f1gt,"ax",@progbits +.p2align 2 +.prefalign 2 +.rept 5 +nop +.endr + +// Minimum alignment < preferred alignment, sh_addralign influenced by section size. +// Use maximum of all .prefalign directives. +// ASM: .section .text.f2lt +// ASM: .p2align 2 +// ASM: .prefalign 8 +// ASM: .prefalign 16 +// ASM: .prefalign 8 +// OBJ: .text.f2lt PROGBITS 0000000000000000 000050 000003 00 AX 0 0 4 +.section .text.f2lt,"ax",@progbits +.p2align 2 +.prefalign 8 +.prefalign 16 +.prefalign 8 +.rept 3 +nop +.endr + +// ASM: .section .text.f2between1 +// OBJ: .text.f2between1 PROGBITS 0000000000000000 000054 000008 00 AX 0 0 8 +.section .text.f2between1,"ax",@progbits +.p2align 2 +.prefalign 8 +.prefalign 16 +.prefalign 8 +.rept 8 +nop +.endr + +// OBJ: .text.f2between2 PROGBITS 0000000000000000 00005c 000009 00 AX 0 0 16 +.section .text.f2between2,"ax",@progbits +.p2align 2 +.prefalign 8 +.prefalign 16 +.prefalign 8 +.rept 9 +nop +.endr + +// OBJ: .text.f2between3 PROGBITS 0000000000000000 000068 000010 00 AX 0 0 16 +.section .text.f2between3,"ax",@progbits +.p2align 2 +.prefalign 8 +.prefalign 16 +.prefalign 8 +.rept 16 +nop +.endr + +// OBJ: .text.f2gt1 PROGBITS 0000000000000000 000078 000011 00 AX 0 0 16 +.section .text.f2gt1,"ax",@progbits +.p2align 2 +.prefalign 8 +.prefalign 16 +.prefalign 8 +.rept 17 +nop +.endr + +// OBJ: .text.f2gt2 PROGBITS 0000000000000000 00008c 000021 00 AX 0 0 16 +.section .text.f2gt2,"ax",@progbits +.p2align 2 +.prefalign 8 +.prefalign 16 +.prefalign 8 +.rept 33 +nop +.endr diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll index 62d3d8255a175..4143b0ef580ba 100644 --- a/llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll +++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-emit.ll @@ -107,7 +107,7 @@ entry: ; CHECK-SEC: [Nr] Name Type {{.*}} ES Flg Lk Inf Al ; CHECK-SEC: [ 3] .text.foo PROGBITS {{.*}} 00 AX 0 0 16 ; CHECK-SEC: [ 5] .text.foo2 PROGBITS {{.*}} 00 AX 0 0 16 -; CHECK-SEC: [ 8] .text.foo3 PROGBITS {{.*}} 00 AXG 0 0 16 +; CHECK-SEC: [ 8] .text.foo3 PROGBITS {{.*}} 00 AXG 0 0 1 ; CHECK-SEC-COUNT-3: .pseudo_probe_desc PROGBITS ; CHECK-SEC: .pseudo_probe PROGBITS {{.*}} 00 L 3 0 1 ; CHECK-SEC-NEXT: .pseudo_probe PROGBITS {{.*}} 00 L 5 0 1 @@ -135,7 +135,7 @@ entry: ; CHECK-SEC2: [Nr] Name Type {{.*}} ES Flg Lk Inf Al ; CHECK-SEC2: [ 3] .text PROGBITS {{.*}} 00 AX 0 0 16 ; CHECK-SEC2: [ 5] .text PROGBITS {{.*}} 00 AX 0 0 16 -; CHECK-SEC2: [ 8] .text PROGBITS {{.*}} 00 AXG 0 0 16 +; CHECK-SEC2: [ 8] .text PROGBITS {{.*}} 00 AXG 0 0 1 ; CHECK-SEC2-COUNT-3: .pseudo_probe_desc PROGBITS ; CHECK-SEC2: .pseudo_probe PROGBITS {{.*}} 00 L 3 0 1 ; CHECK-SEC2-NEXT: .pseudo_probe PROGBITS {{.*}} 00 L 5 0 1 From b0cd4fa8dcbdf6cbf441b5d705150cb0f57a260f Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Wed, 27 Aug 2025 16:16:54 -0700 Subject: [PATCH 2/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?= =?UTF-8?q?anges=20introduced=20through=20rebase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.6-beta.1 [skip ci] --- llvm/docs/LangRef.rst | 18 +++++++----------- llvm/lib/CodeGen/MachineFunction.cpp | 9 +++++---- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 80f9b7c150b67..12337beb7e579 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -951,17 +951,13 @@ rules described below. If an explicit minimum alignment is specified, the function is forced to have at least that much alignment. All alignments must be a power of 2. -An explicit preferred alignment (``prefalign``) may also be specified -for a function (definitions only, and must be a power of 2). If a -function does not have a preferred alignment attribute, the preferred -alignment is determined in a target-specific way. The final alignment -of the function is determined in the following way: if the function -size is less than the minimum alignment, the function's alignment will -be at least the minimum alignment. Otherwise, if the function size is -between the minimum alignment and the preferred alignment, the function's -alignment will be at least the power of 2 greater than or equal to the -function size. Otherwise, the function's alignment will be at least the -preferred alignment. +An explicit preferred alignment (``prefalign``) may also be specified for +a function (definitions only, and must be a power of 2). If a function +does not have a preferred alignment attribute, the preferred alignment +is determined in a target-specific way. The preferred alignment, if +provided, is treated as a hint; the final alignment of the function will +generally be set to a value somewhere between the minimum alignment and +the preferred alignment. If the ``unnamed_addr`` attribute is given, the address is known to not be significant and two identical functions can be merged. diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp index eabe1a510d92d..478a7ccbdfe41 100644 --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -326,13 +326,14 @@ bool MachineFunction::shouldSplitStack() const { } Align MachineFunction::getPreferredAlignment() const { - Align PrefAlignment = Align(1); - - if (!F.hasOptSize()) - PrefAlignment = STI.getTargetLowering()->getPrefFunctionAlignment(); + Align PrefAlignment; if (MaybeAlign A = F.getPreferredAlignment()) PrefAlignment = *A; + else if (!F.hasOptSize()) + PrefAlignment = STI.getTargetLowering()->getPrefFunctionAlignment(); + else + PrefAlignment = Align(1); return std::max(PrefAlignment, getAlignment()); }