[llvm] [X86] Resolve FIXME: Copy kill flag for eflags (PR #82411)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 21 16:48:48 PST 2024
https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/82411
>From bae0d5190372395937001c6eb8d4fe172cc172e0 Mon Sep 17 00:00:00 2001
From: Rose <83477269+AtariDreams at users.noreply.github.com>
Date: Tue, 20 Feb 2024 14:29:42 -0500
Subject: [PATCH] [X86] Resolve FIXME: Copy kill flag for eflags
We now mark the last eflags usage as kill if the def was also kill.
---
llvm/lib/Target/X86/X86FlagsCopyLowering.cpp | 47 ++++++++++++++++----
llvm/lib/Target/X86/X86InstrInfo.cpp | 32 ++++++++-----
2 files changed, 60 insertions(+), 19 deletions(-)
diff --git a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
index af25b34fbab995..a4780ebae074cd 100644
--- a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
+++ b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
@@ -347,6 +347,31 @@ static X86::CondCode getCondFromFCMOV(unsigned Opcode) {
}
}
+static bool checkEFLAGSLive(MachineInstr *MI) {
+ if (MI->killsRegister(X86::EFLAGS))
+ return false;
+
+ // The EFLAGS operand of MI might be missing a kill marker.
+ // Figure out whether EFLAGS operand should LIVE after MI instruction.
+ MachineBasicBlock *BB = MI->getParent();
+ MachineBasicBlock::iterator ItrMI = MI;
+
+ // Scan forward through BB for a use/def of EFLAGS.
+ for (auto I = std::next(ItrMI), E = BB->end(); I != E; ++I) {
+ if (I->readsRegister(X86::EFLAGS))
+ return true;
+ if (I->definesRegister(X86::EFLAGS))
+ return false;
+ }
+
+ // We hit the end of the block, check whether EFLAGS is live into a successor.
+ for (MachineBasicBlock *Succ : BB->successors())
+ if (Succ->isLiveIn(X86::EFLAGS))
+ return true;
+
+ return false;
+}
+
bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) {
LLVM_DEBUG(dbgs() << "********** " << getPassName() << " : " << MF.getName()
<< " **********\n");
@@ -442,7 +467,8 @@ bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) {
llvm::reverse(llvm::make_range(Begin, End)), [&](MachineInstr &MI) {
// Flag any instruction (other than the copy we are
// currently rewriting) that defs EFLAGS.
- return &MI != CopyI && MI.findRegisterDefOperand(X86::EFLAGS);
+ return &MI != CopyI &&
+ MI.findRegisterDefOperand(X86::EFLAGS, false, false, TRI);
});
};
auto HasEFLAGSClobberPath = [&](MachineBasicBlock *BeginMBB,
@@ -562,9 +588,10 @@ bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) {
break;
}
- MachineOperand *FlagUse = MI.findRegisterUseOperand(X86::EFLAGS);
+ MachineOperand *FlagUse =
+ MI.findRegisterUseOperand(X86::EFLAGS, false, TRI);
if (!FlagUse) {
- if (MI.findRegisterDefOperand(X86::EFLAGS)) {
+ if (MI.findRegisterDefOperand(X86::EFLAGS, false, false, TRI)) {
// If EFLAGS are defined, it's as-if they were killed. We can stop
// scanning here.
//
@@ -614,7 +641,7 @@ bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) {
rewriteCopy(MI, *FlagUse, CopyDefI);
} else {
// We assume all other instructions that use flags also def them.
- assert(MI.findRegisterDefOperand(X86::EFLAGS) &&
+ assert(MI.findRegisterDefOperand(X86::EFLAGS, false, false, TRI) &&
"Expected a def of EFLAGS for this instruction!");
// NB!!! Several arithmetic instructions only *partially* update
@@ -683,6 +710,8 @@ bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) {
// Now rewrite the jumps that use the flags. These we handle specially
// because if there are multiple jumps in a single basic block we'll have
// to do surgery on the CFG.
+ bool CopyDefIsKill = !checkEFLAGSLive(&CopyDefI);
+ MachineOperand *LastEflagsUse = nullptr;
MachineBasicBlock *LastJmpMBB = nullptr;
for (MachineInstr *JmpI : JmpIs) {
// Past the first jump within a basic block we need to split the blocks
@@ -693,10 +722,12 @@ bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) {
LastJmpMBB = JmpI->getParent();
rewriteCondJmp(*TestMBB, TestPos, TestLoc, *JmpI, CondRegs);
+ if (CopyDefIsKill && JmpI->readsRegister(X86::EFLAGS))
+ LastEflagsUse = JmpI->findRegisterUseOperand(X86::EFLAGS, false, TRI);
}
- // FIXME: Mark the last use of EFLAGS before the copy's def as a kill if
- // the copy's def operand is itself a kill.
+ if (LastEflagsUse && CopyDefIsKill)
+ LastEflagsUse->setIsKill(true);
}
#ifndef NDEBUG
@@ -733,7 +764,7 @@ CondRegArray X86FlagsCopyLoweringPass::collectCondsInRegs(
// Stop scanning when we see the first definition of the EFLAGS as prior to
// this we would potentially capture the wrong flag state.
- if (MI.findRegisterDefOperand(X86::EFLAGS))
+ if (MI.findRegisterDefOperand(X86::EFLAGS, false, false, TRI))
break;
}
return CondRegs;
@@ -911,7 +942,7 @@ void X86FlagsCopyLoweringPass::rewriteCondJmp(
// Rewrite the jump to use the !ZF flag from the test, and kill its use of
// flags afterward.
JmpI.getOperand(1).setImm(Inverted ? X86::COND_E : X86::COND_NE);
- JmpI.findRegisterUseOperand(X86::EFLAGS)->setIsKill(true);
+ JmpI.findRegisterUseOperand(X86::EFLAGS, false, TRI)->setIsKill(true);
LLVM_DEBUG(dbgs() << " fixed jCC: "; JmpI.dump());
}
diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp
index 0f21880f6df90c..7b882aa892cfe1 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.cpp
+++ b/llvm/lib/Target/X86/X86InstrInfo.cpp
@@ -3711,7 +3711,7 @@ bool X86InstrInfo::analyzeBranchImpl(
// In practice we should never have an undef eflags operand, if we do
// abort here as we are not prepared to preserve the flag.
- if (I->findRegisterUseOperand(X86::EFLAGS)->isUndef())
+ if (I->findRegisterUseOperand(X86::EFLAGS)->isUndef(), false, false, TRI)
return true;
// Working from the bottom, handle the first conditional branch.
@@ -5455,7 +5455,8 @@ bool X86InstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,
}
// Make sure Sub instruction defines EFLAGS and mark the def live.
- MachineOperand *FlagDef = Sub->findRegisterDefOperand(X86::EFLAGS);
+ MachineOperand *FlagDef =
+ Sub->findRegisterDefOperand(X86::EFLAGS, false, false, TRI);
assert(FlagDef && "Unable to locate a def EFLAGS operand");
FlagDef->setIsDead(false);
@@ -5677,17 +5678,20 @@ bool X86InstrInfo::foldImmediateImpl(MachineInstr &UseMI, MachineInstr *DefMI,
NewOpc == X86::SBB64ri32 || NewOpc == X86::SBB32ri ||
NewOpc == X86::SUB64ri32_ND || NewOpc == X86::SUB32ri_ND ||
NewOpc == X86::SBB64ri32_ND || NewOpc == X86::SBB32ri_ND) &&
- UseMI.findRegisterUseOperandIdx(Reg) != 2)
+ UseMI.findRegisterUseOperandIdx(Reg, false,
+ MRI->getTargetRegisterInfo()) != 2)
return false;
// For CMP instructions the immediate can only be at index 1.
if ((NewOpc == X86::CMP64ri32 || NewOpc == X86::CMP32ri) &&
- UseMI.findRegisterUseOperandIdx(Reg) != 1)
+ UseMI.findRegisterUseOperandIdx(Reg, false,
+ MRI->getTargetRegisterInfo()) != 1)
return false;
using namespace X86;
if (isSHL(Opc) || isSHR(Opc) || isSAR(Opc) || isROL(Opc) || isROR(Opc) ||
isRCL(Opc) || isRCR(Opc)) {
- unsigned RegIdx = UseMI.findRegisterUseOperandIdx(Reg);
+ unsigned RegIdx = UseMI.findRegisterUseOperandIdx(
+ Reg, false, MRI->getTargetRegisterInfo());
if (RegIdx < 2)
return false;
if (!isInt<8>(ImmVal))
@@ -5716,8 +5720,10 @@ bool X86InstrInfo::foldImmediateImpl(MachineInstr &UseMI, MachineInstr *DefMI,
// ==>
// %100 = COPY %101
UseMI.setDesc(get(TargetOpcode::COPY));
- UseMI.removeOperand(UseMI.findRegisterUseOperandIdx(Reg));
- UseMI.removeOperand(UseMI.findRegisterDefOperandIdx(X86::EFLAGS));
+ UseMI.removeOperand(UseMI.findRegisterUseOperandIdx(
+ Reg, false, MRI->getTargetRegisterInfo()));
+ UseMI.removeOperand(UseMI.findRegisterDefOperandIdx(
+ X86::EFLAGS, false, false, MRI->getTargetRegisterInfo()));
UseMI.untieRegOperand(0);
UseMI.clearFlag(MachineInstr::MIFlag::NoSWrap);
UseMI.clearFlag(MachineInstr::MIFlag::NoUWrap);
@@ -10038,8 +10044,10 @@ void X86InstrInfo::setSpecialOperandAttr(MachineInstr &OldMI1,
MachineInstr &NewMI1,
MachineInstr &NewMI2) const {
// Integer instructions may define an implicit EFLAGS dest register operand.
- MachineOperand *OldFlagDef1 = OldMI1.findRegisterDefOperand(X86::EFLAGS);
- MachineOperand *OldFlagDef2 = OldMI2.findRegisterDefOperand(X86::EFLAGS);
+ MachineOperand *OldFlagDef1 = OldMI1.findRegisterDefOperand(
+ X86::EFLAGS, false, false, &getRegisterInfo());
+ MachineOperand *OldFlagDef2 = OldMI2.findRegisterDefOperand(
+ X86::EFLAGS, false, false, &getRegisterInfo());
assert(!OldFlagDef1 == !OldFlagDef2 &&
"Unexpected instruction type for reassociation");
@@ -10050,8 +10058,10 @@ void X86InstrInfo::setSpecialOperandAttr(MachineInstr &OldMI1,
assert(OldFlagDef1->isDead() && OldFlagDef2->isDead() &&
"Must have dead EFLAGS operand in reassociable instruction");
- MachineOperand *NewFlagDef1 = NewMI1.findRegisterDefOperand(X86::EFLAGS);
- MachineOperand *NewFlagDef2 = NewMI2.findRegisterDefOperand(X86::EFLAGS);
+ MachineOperand *NewFlagDef1 = NewMI1.findRegisterDefOperand(
+ X86::EFLAGS, false, false, &getRegisterInfo());
+ MachineOperand *NewFlagDef2 = NewMI2.findRegisterDefOperand(
+ X86::EFLAGS, false, false, &getRegisterInfo());
assert(NewFlagDef1 && NewFlagDef2 &&
"Unexpected operand in reassociable instruction");
More information about the llvm-commits
mailing list