Index: llvm/include/llvm/MC/MCFragment.h =================================================================== --- llvm/include/llvm/MC/MCFragment.h +++ llvm/include/llvm/MC/MCFragment.h @@ -335,18 +335,18 @@ }; class MCNeverAlignFragment : public MCFragment { - /// Alignment - The alignment the end of the next fragment should avoid + /// The alignment the end of the next fragment should avoid. unsigned Alignment; - /// EmitNops - Flag to indicate that (optimal) NOPs should be emitted instead + /// Flag to indicate that (optimal) NOPs should be emitted instead /// of using the provided value. The exact interpretation of this flag is /// target dependent. bool EmitNops : 1; - /// Value - Value to use for filling padding bytes. + /// Value to use for filling padding bytes. int64_t Value; - /// ValueSize - The size of the integer (in bytes) of \p Value. + /// The size of the integer (in bytes) of \p Value. unsigned ValueSize; public: Index: llvm/lib/MC/MCAssembler.cpp =================================================================== --- llvm/lib/MC/MCAssembler.cpp +++ llvm/lib/MC/MCAssembler.cpp @@ -348,30 +348,24 @@ case MCFragment::FT_NeverAlign: { const MCNeverAlignFragment &NAF = cast(F); + const MCFragment *NF = F.getNextNode(); uint64_t Offset = Layout.getFragmentOffset(&NAF); - unsigned Size = 0; - uint64_t OffsetToAvoid = 0; - // Calculate offset to avoid in order to avoid aligning the end of the - // next fragment - if (const auto *NextFrag = dyn_cast(F.getNextNode())) { - OffsetToAvoid = NAF.getAlignment() - - (NextFrag->getContents().size() % NAF.getAlignment()); - } else if (const auto *NextFrag = - dyn_cast(F.getNextNode())) { - OffsetToAvoid = NAF.getAlignment() - - (NextFrag->getContents().size() % NAF.getAlignment()); + size_t NextFragSize = 0; + if (const auto *NextFrag = dyn_cast(NF)) { + NextFragSize = NextFrag->getContents().size(); + } else if (const auto *NextFrag = dyn_cast(NF)) { + NextFragSize = NextFrag->getContents().size(); + } else { + // Didn't find the expected fragment after the current one. + return 0; } - // Check if the current offset matches the alignment plus offset we want to - // avoid - if (Offset % NAF.getAlignment() == OffsetToAvoid) { - // Avoid this alignment by introducing one extra byte - Size = 1; - if (Size > 0 && NAF.hasEmitNops()) { - while (Size % getBackend().getMinimumNopSize()) - Size += 1; - } + // Check if the next fragment ends at the alignment we want to avoid. + if ((Offset + NextFragSize) % NAF.getAlignment() == 0) { + // Avoid this alignment by introducing minimum nop. + assert(getBackend().getMinimumNopSize() != NAF.getAlignment()); + return getBackend().getMinimumNopSize(); } - return Size; + return 0; } case MCFragment::FT_Org: { Index: llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp =================================================================== --- llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -1128,6 +1128,7 @@ bool parseDirectiveArch(); bool parseDirectiveNops(SMLoc L); bool parseDirectiveEven(SMLoc L); + bool parseDirectiveAvoidEndAlign(SMLoc L); bool ParseDirectiveCode(StringRef IDVal, SMLoc L); /// CodeView FPO data directives. @@ -4631,6 +4632,8 @@ return false; } else if (IDVal == ".nops") return parseDirectiveNops(DirectiveID.getLoc()); + else if (IDVal == ".avoid_end_align") + return parseDirectiveAvoidEndAlign(DirectiveID.getLoc()); else if (IDVal == ".even") return parseDirectiveEven(DirectiveID.getLoc()); else if (IDVal == ".cv_fpo_proc") @@ -4726,6 +4729,32 @@ return false; } +/// parseDirectiveAvoidEndAlign +/// ::= .avoid_end_align alignment +bool X86AsmParser::parseDirectiveAvoidEndAlign(SMLoc L) { + int64_t Alignment = 0; + SMLoc AlignmentLoc; + const MCSubtargetInfo STI = getSTI(); + AlignmentLoc = getTok().getLoc(); + if (getParser().checkForValidSection() || + getParser().parseAbsoluteExpression(Alignment)) + return true; + + if (getParser().parseToken(AsmToken::EndOfStatement, + "unexpected token in '.avoid_end_align' directive")) + return true; + + if (Alignment <= 0) { + Error(AlignmentLoc, "'.avoid_end_align' directive with non-positive size"); + return false; + } + + /// Emit NeverAlign + getParser().getStreamer().emitNeverAlignCodeAtEnd(Alignment); + + return false; +} + /// ParseDirectiveCode /// ::= .code16 | .code32 | .code64 bool X86AsmParser::ParseDirectiveCode(StringRef IDVal, SMLoc L) { Index: llvm/test/MC/X86/x86_64-directive-avoid_end_align.s =================================================================== --- /dev/null +++ llvm/test/MC/X86/x86_64-directive-avoid_end_align.s @@ -0,0 +1,16 @@ +# RUN: llvm-mc -triple=x86_64 %s -filetype=obj | llvm-objdump -d - | FileCheck %s + +# %bb.0: # %entry +.nops 59 + pushq %rbx + movl %edi, %ebx +.avoid_end_align 64 +# CHECK: 3e: 90 nop + testl %eax, %eax +# CHECK-NEXT: 3f: 85 c0 testl %eax, %eax + je .LBB0_2 +# %bb.1: # %taken + nop +.LBB0_2: # %untaken + popq %rbx + retq