[llvm] [X86][APX] Reuse EFLAGS across multi-predecessor blocks via NF in optimizeCompareInstr (PR #208184)
Phoebe Wang via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 13 23:01:23 PDT 2026
================
@@ -5285,6 +5297,88 @@ static std::pair<X86::CondCode, unsigned> isUseDefConvertible(const MachineInstr
}
}
+MachineInstr *X86InstrInfo::findDominatingRedundantFlagInstr(
+ MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask,
+ int64_t CmpValue, MachineBasicBlock *MultiPredMBB, bool &IsSwapped,
+ int64_t &ImmDelta,
+ SmallVectorImpl<std::pair<MachineInstr *, unsigned>> &InstsToUpdate) const {
+ assert(Subtarget.hasNF() && "NF feature required");
+ const TargetRegisterInfo *TRI = &getRegisterInfo();
+
+ // The caller already scanned MultiPredMBB without finding the producer, so it
+ // must live in a block that strictly dominates MultiPredMBB. Walk
+ // predecessors backward to find it and prove dominance, avoiding a
+ // whole-function MachineDominatorTree that would be rebuilt in O(function
+ // size) per compare.
+ //
+ // The producer's block dominates MultiPredMBB iff every backward path funnels
+ // through it before a function-entry block, so expand predecessors but stop
+ // at a block holding the producer. Bail if a predecessor-less block is
+ // reached without the producer (a path bypasses it) or the producer is found
+ // in two blocks (neither dominates alone). Within a block, scan backward,
+ // collecting the NF-convertible EFLAGS clobbers above the producer and
+ // bailing on any other clobber (it would shadow the producer's flags from
+ // CmpInstr).
+ //
+ // Clobbers are staged in Pending and committed only on success. Visited
+ // (seeded with MultiPredMBB) stops the walk from revisiting a block or
+ // re-entering the single-predecessor chain, so none is collected twice.
+ MachineInstr *Sub = nullptr;
+ MachineBasicBlock *SubMBB = nullptr;
+ SmallVector<std::pair<MachineInstr *, unsigned>, 4> Pending;
+ SmallPtrSet<MachineBasicBlock *, 8> Visited;
+ SmallVector<MachineBasicBlock *, 8> Worklist;
+ Visited.insert(MultiPredMBB);
+ for (MachineBasicBlock *Pred : MultiPredMBB->predecessors())
+ if (Visited.insert(Pred).second)
+ Worklist.push_back(Pred);
+ while (!Worklist.empty()) {
+ MachineBasicBlock *MBB = Worklist.pop_back_val();
+ MachineInstr *Producer = nullptr;
+ for (MachineInstr &Inst : reverse(*MBB)) {
+ if (!Inst.modifiesRegister(X86::EFLAGS, TRI))
+ continue;
+ if (isRedundantFlagInstr(CmpInstr, SrcReg, SrcReg2, CmpMask, CmpValue,
+ Inst, &IsSwapped, &ImmDelta)) {
+ Producer = &Inst;
+ break;
+ }
+ unsigned NewOpc = X86::getNFVariantIfClobberRemovable(Inst, TRI);
+ if (!NewOpc)
+ return nullptr;
+ Pending.push_back(std::make_pair(&Inst, NewOpc));
----------------
phoebewang wrote:
Maybe exit when there are too many (e.g., 6) opcs need to update?
https://github.com/llvm/llvm-project/pull/208184
More information about the llvm-commits
mailing list