[llvm] [X86] Reimplement bundle alignment mode (PR #175830)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 14 19:21:49 PDT 2026
================
@@ -852,7 +916,144 @@ bool X86AsmBackend::padInstructionEncoding(MCFragment &RF,
return Changed;
}
+bool X86AsmBackend::padInstsBackward(SmallVectorImpl<MCFragment *> &Relaxable,
+ unsigned &RemainingSize) const {
+ bool Changed = false;
+ while (!Relaxable.empty() && RemainingSize != 0) {
+ auto &RF = *Relaxable.pop_back_val();
+ // Give the backend a chance to play any tricks it wishes to increase
+ // the encoding size of the given instruction. Target independent code
+ // will try further relaxation, but target's may play further tricks.
+ Changed |= padInstructionEncoding(RF, Asm->getEmitter(), RemainingSize);
+
+ // If we have an instruction which hasn't been fully relaxed, we can't
+ // skip past it and insert bytes before it. Changing its starting
+ // offset might require a larger negative offset than it can encode.
+ // We don't need to worry about larger positive offsets as none of the
+ // possible offsets between this and our align are visible, and the
+ // ones afterwards aren't changing.
+ if (mayNeedRelaxation(RF.getOpcode(), RF.getOperands(),
+ *RF.getSubtargetInfo()))
+ break;
+ }
+ Relaxable.clear();
+ return Changed;
+}
+
+// Peephole is a list of Fragments that ends with non-zero-sized
+// BoundaryAlignFragment. Most of the time it will be every instruction within a
+// bundle, but there can be a partial bundle if it has nops in the middle(e.g.,
+// align_to_end).
+bool X86AsmBackend::dividePadInBundle(const MCAssembler &Asm,
+ ArrayRef<MCFragment *> Peephole) const {
+ bool Changed = false;
+
+ // Last Fragment is either FT_Align or FT_BoundaryAlign
+ auto *LastF = Peephole.back();
+ unsigned RemainingSize =
+ Asm.computeFragmentSize(*LastF) - LastF->getFixedSize();
+
+ unsigned StartOffset = Asm.getFragmentOffset(*LastF);
+ unsigned EndOffset = StartOffset + RemainingSize;
+ auto BoundaryAlignment = Align(Asm.getBundleAlignSize());
+ bool CrossBoundary = (StartOffset >> Log2(BoundaryAlignment)) !=
+ ((EndOffset - 1) >> Log2(BoundaryAlignment));
+
+ if (CrossBoundary) {
+ // i.e., this pad is a mix of suffix fragment of one bundle + prefix of the
+ // very next bundle. It prevents overflow of the first bundle when Peephole
+ // contains more than one bundle.
+ //
+ // This design limits the possibly further-optimized code, which might be
+ // achieved by migrating some instructions to the next bundle, but doing
+ // such may cause fixup errors because instructions can shift by more than
+ // a bundle-size and labels may become unreachable. Until we come up with a
+ // better logic, we limits the optimization scope to a single bundle.
+ RemainingSize -= EndOffset % Asm.getBundleAlignSize();
+ }
+ assert(RemainingSize > 0);
+
+ SmallVector<MCFragment *, 4> Relaxable;
+ for (auto *FIB : Peephole) {
+ if (FIB->getKind() == MCFragment::FT_Data) // Skip and ignore
+ continue;
+
+ if (FIB->getKind() == MCFragment::FT_Align) {
+ // p2align within a bundle
+ Relaxable.clear();
+ continue;
+ }
+
+ if (FIB->getKind() == MCFragment::FT_Relaxable) {
+ auto &RF = cast<MCFragment>(*FIB);
+ Relaxable.push_back(&RF);
+ continue;
+ }
+ }
+
+ // First, try padding previous instructions.
+ Changed |= padInstsBackward(Relaxable, RemainingSize);
+
+ // Second, try padding following instructions.
+ auto padInstsForward = [&](unsigned &Size) {
+ auto *BF = cast<MCBoundaryAlignFragment>(LastF);
+ for (auto *F = BF->getNext();; F = F->getNext()) {
+ if (F->getKind() == MCFragment::FT_Relaxable)
+ Changed |= padInstructionEncoding(*F, Asm.getEmitter(), Size);
+ if (F == BF->getLastFragment() || Size == 0)
+ break;
+ }
+ };
+
+ unsigned TailSize = EndOffset % Asm.getBundleAlignSize();
+ if (!CrossBoundary && RemainingSize > 0 && TailSize != 0) {
+ padInstsForward(RemainingSize);
+ } else if (CrossBoundary && TailSize > 0) {
+ unsigned NextRemainingSize = TailSize;
+ padInstsForward(NextRemainingSize);
+ RemainingSize += NextRemainingSize;
+ }
+
+ // FT_Align sizes will be recalculated by layoutSection(),
+ // FT_BoundaryAlign sizes are adjusted here.
+ if (auto *BF = dyn_cast<MCBoundaryAlignFragment>(LastF))
+ BF->setSize(RemainingSize);
+
+ return Changed;
+}
+
+bool X86AsmBackend::optimizeBundleNops(const MCAssembler &Asm) const {
+ bool Changed = false;
+ for (MCSection &Sec : Asm) {
+ if (!Sec.isText())
+ continue;
+
+ SmallVector<MCFragment *, 4> Bundle;
+ for (MCSection::iterator I = Sec.begin(), IE = Sec.end(); I != IE; ++I) {
----------------
MaskRay wrote:
for each loop?
https://github.com/llvm/llvm-project/pull/175830
More information about the llvm-commits
mailing list