Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 23 additions & 8 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <paramattrs>`), optional :ref:`function attributes <fnattrs>`,
an optional address space, an optional section, an optional partition,
an optional alignment, an optional :ref:`comdat <langref_comdats>`,
an optional minimum alignment,
an optional preferred alignment,
an optional :ref:`comdat <langref_comdats>`,
an optional :ref:`garbage collector name <gc>`, an optional :ref:`prefix <prefixdata>`,
an optional :ref:`prologue <prologuedata>`,
an optional :ref:`personality <personalityfn>`,
Expand All @@ -891,8 +893,8 @@ Syntax::
<ResultType> @<FunctionName> ([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:
Expand Down Expand Up @@ -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.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems overly specific: if you read it literally, it means that we have to precisely compute the size of the function, which is probably not feasible in general, and that optimizations aren't allowed to modify prefalign. I think I'd prefer to say it's a hint, which can be overriden by PGO/CFI jump tables/etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted this to describe the lower bound on the alignment (because e.g. non-ELF or -fno-function-sections can result in a higher alignment), but yeah, it's probably best just to say that it's a hint; the actual rules are too complex to specify here. Done.


If the ``unnamed_addr`` attribute is given, the address is known to not
be significant and two identical functions can be merged.
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/AsmParser/LLParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/AsmParser/LLToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ enum Kind {
kw_prefix,
kw_prologue,
kw_c,
kw_prefalign,

kw_cc,
kw_ccc,
Expand Down
9 changes: 8 additions & 1 deletion llvm/include/llvm/IR/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
unsigned BlockNumEpoch = 0;

mutable Argument *Arguments = nullptr; ///< The formal arguments
size_t NumArgs;
uint32_t NumArgs;
MaybeAlign PreferredAlign;
std::unique_ptr<ValueSymbolTable>
SymTab; ///< Symbol table of args/instructions
AttributeList AttributeSets; ///< Parameter attributes
Expand Down Expand Up @@ -1043,6 +1044,12 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
/// 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;
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/AsmParser/LLLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(gc);
KEYWORD(prefix);
KEYWORD(prologue);
KEYWORD(prefalign);

KEYWORD(no_sanitize_address);
KEYWORD(no_sanitize_hwaddress);
Expand Down
23 changes: 13 additions & 10 deletions llvm/lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand All @@ -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)) ||
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Bitcode/Reader/BitcodeReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4385,6 +4385,13 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef<uint64_t> 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)
Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
Expand All @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/IR/AsmWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down
14 changes: 14 additions & 0 deletions llvm/test/Bitcode/compatibility.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Loading