[llvm] [X86][CodeGen] Support using NF instructions for flag copy lowering (PR #93508)
Phoebe Wang via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 2 20:38:25 PDT 2024
================
@@ -254,14 +268,102 @@ bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) {
// turn copied again we visit the first one first. This ensures we can find
// viable locations for testing the original EFLAGS that dominate all the
// uses across complex CFGs.
- SmallVector<MachineInstr *, 4> Copies;
+ SmallSetVector<MachineInstr *, 4> Copies;
ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
for (MachineBasicBlock *MBB : RPOT)
for (MachineInstr &MI : *MBB)
if (MI.getOpcode() == TargetOpcode::COPY &&
MI.getOperand(0).getReg() == X86::EFLAGS)
- Copies.push_back(&MI);
+ Copies.insert(&MI);
+
+ // Try to elminate the copys by transform the instructions between copy and
+ // copydef to the NF (no flags update) variants, e.g.
+ //
+ // %1:gr64 = COPY $eflags
+ // OP1 implicit-def dead $eflags
+ // $eflags = COPY %1
+ // OP2 cc, implicit $eflags
+ //
+ // ->
+ //
+ // OP1_NF
+ // OP2 implicit $eflags
+ if (Subtarget->hasNF()) {
+ SmallSetVector<MachineInstr *, 4> RemovedCopies;
+ // CopyIIt may be invalidated by removing copies.
+ auto CopyIIt = Copies.begin(), CopyIEnd = Copies.end();
+ while (CopyIIt != CopyIEnd) {
+ auto NCopyIIt = std::next(CopyIIt);
+ SmallSetVector<MachineInstr *, 4> EvitableClobbers;
+ MachineInstr *CopyI = *CopyIIt;
+ MachineOperand &VOp = CopyI->getOperand(1);
+ MachineInstr *CopyDefI = MRI->getVRegDef(VOp.getReg());
+ MachineBasicBlock *CopyIMBB = CopyI->getParent();
+ MachineBasicBlock *CopyDefIMBB = CopyDefI->getParent();
+ // Walk all basic blocks reachable in depth-first iteration on the inverse
+ // CFG from CopyIMBB to CopyDefIMBB. These blocks are all the blocks that
+ // may be executed between the execution of CopyDefIMBB and CopyIMBB. On
+ // all execution paths, instructions from CopyDefI to CopyI (exclusive)
+ // has to be NF-convertible if it clobbers flags.
+ for (auto BI = idf_begin(CopyIMBB), BE = idf_end(CopyDefIMBB); BI != BE;
+ ++BI) {
+ MachineBasicBlock *MBB = *BI;
+ for (auto I = (MBB != CopyDefIMBB)
+ ? MBB->begin()
+ : std::next(MachineBasicBlock::iterator(CopyDefI)),
+ E = (MBB != CopyIMBB) ? MBB->end()
+ : MachineBasicBlock::iterator(CopyI);
+ I != E; ++I) {
+ MachineInstr &MI = *I;
+ EFLAGSClobber ClobberType = getClobberType(MI);
+ if (ClobberType == NoClobber)
+ continue;
+
+ if (ClobberType == InevitableClobber)
+ goto ProcessNextCopyI;
+
+ assert(ClobberType == EvitableClobber && "unexpected workflow");
----------------
phoebewang wrote:
Can't this be failed? I think we cannot transform another `$eflags = COPY %x` in `MBB` at least, right?
https://github.com/llvm/llvm-project/pull/93508
More information about the llvm-commits
mailing list