summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/X86/X86FlagsCopyLowering.cpp')
-rw-r--r--llvm/lib/Target/X86/X86FlagsCopyLowering.cpp92
1 files changed, 84 insertions, 8 deletions
diff --git a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
index cfba06fb6533..b1d2de29c896 100644
--- a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
+++ b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
@@ -87,12 +87,12 @@ public:
static char ID;
private:
- MachineRegisterInfo *MRI;
- const X86Subtarget *Subtarget;
- const X86InstrInfo *TII;
- const TargetRegisterInfo *TRI;
- const TargetRegisterClass *PromoteRC;
- MachineDominatorTree *MDT;
+ MachineRegisterInfo *MRI = nullptr;
+ const X86Subtarget *Subtarget = nullptr;
+ const X86InstrInfo *TII = nullptr;
+ const TargetRegisterInfo *TRI = nullptr;
+ const TargetRegisterClass *PromoteRC = nullptr;
+ MachineDominatorTree *MDT = nullptr;
CondRegArray collectCondsInRegs(MachineBasicBlock &MBB,
MachineBasicBlock::iterator CopyDefI);
@@ -115,6 +115,10 @@ private:
MachineBasicBlock::iterator TestPos, DebugLoc TestLoc,
MachineInstr &CMovI, MachineOperand &FlagUse,
CondRegArray &CondRegs);
+ void rewriteFCMov(MachineBasicBlock &TestMBB,
+ MachineBasicBlock::iterator TestPos, DebugLoc TestLoc,
+ MachineInstr &CMovI, MachineOperand &FlagUse,
+ CondRegArray &CondRegs);
void rewriteCondJmp(MachineBasicBlock &TestMBB,
MachineBasicBlock::iterator TestPos, DebugLoc TestLoc,
MachineInstr &JmpI, CondRegArray &CondRegs);
@@ -334,6 +338,28 @@ static MachineBasicBlock &splitBlock(MachineBasicBlock &MBB,
return NewMBB;
}
+static X86::CondCode getCondFromFCMOV(unsigned Opcode) {
+ switch (Opcode) {
+ default: return X86::COND_INVALID;
+ case X86::CMOVBE_Fp32: case X86::CMOVBE_Fp64: case X86::CMOVBE_Fp80:
+ return X86::COND_BE;
+ case X86::CMOVB_Fp32: case X86::CMOVB_Fp64: case X86::CMOVB_Fp80:
+ return X86::COND_B;
+ case X86::CMOVE_Fp32: case X86::CMOVE_Fp64: case X86::CMOVE_Fp80:
+ return X86::COND_E;
+ case X86::CMOVNBE_Fp32: case X86::CMOVNBE_Fp64: case X86::CMOVNBE_Fp80:
+ return X86::COND_A;
+ case X86::CMOVNB_Fp32: case X86::CMOVNB_Fp64: case X86::CMOVNB_Fp80:
+ return X86::COND_AE;
+ case X86::CMOVNE_Fp32: case X86::CMOVNE_Fp64: case X86::CMOVNE_Fp80:
+ return X86::COND_NE;
+ case X86::CMOVNP_Fp32: case X86::CMOVNP_Fp64: case X86::CMOVNP_Fp80:
+ return X86::COND_NP;
+ case X86::CMOVP_Fp32: case X86::CMOVP_Fp64: case X86::CMOVP_Fp80:
+ return X86::COND_P;
+ }
+}
+
bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) {
LLVM_DEBUG(dbgs() << "********** " << getPassName() << " : " << MF.getName()
<< " **********\n");
@@ -593,6 +619,8 @@ bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) {
// Otherwise we can just rewrite in-place.
if (X86::getCondFromCMov(MI) != X86::COND_INVALID) {
rewriteCMov(*TestMBB, TestPos, TestLoc, MI, *FlagUse, CondRegs);
+ } else if (getCondFromFCMOV(MI.getOpcode()) != X86::COND_INVALID) {
+ rewriteFCMov(*TestMBB, TestPos, TestLoc, MI, *FlagUse, CondRegs);
} else if (X86::getCondFromSETCC(MI) != X86::COND_INVALID) {
rewriteSetCC(*TestMBB, TestPos, TestLoc, MI, *FlagUse, CondRegs);
} else if (MI.getOpcode() == TargetOpcode::COPY) {
@@ -674,6 +702,9 @@ bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) {
}
Blocks.push_back(SuccMBB);
+
+ // After this, EFLAGS will be recreated before each use.
+ SuccMBB->removeLiveIn(X86::EFLAGS);
}
} while (!Blocks.empty());
@@ -779,10 +810,10 @@ void X86FlagsCopyLoweringPass::rewriteArithmetic(
CondRegArray &CondRegs) {
// Arithmetic is either reading CF or OF. Figure out which condition we need
// to preserve in a register.
- X86::CondCode Cond;
+ X86::CondCode Cond = X86::COND_INVALID;
// The addend to use to reset CF or OF when added to the flag value.
- int Addend;
+ int Addend = 0;
switch (getMnemonicFromOpcode(MI.getOpcode())) {
case FlagArithMnemonic::ADC:
@@ -852,6 +883,51 @@ void X86FlagsCopyLoweringPass::rewriteCMov(MachineBasicBlock &TestMBB,
LLVM_DEBUG(dbgs() << " fixed cmov: "; CMovI.dump());
}
+void X86FlagsCopyLoweringPass::rewriteFCMov(MachineBasicBlock &TestMBB,
+ MachineBasicBlock::iterator TestPos,
+ DebugLoc TestLoc,
+ MachineInstr &CMovI,
+ MachineOperand &FlagUse,
+ CondRegArray &CondRegs) {
+ // First get the register containing this specific condition.
+ X86::CondCode Cond = getCondFromFCMOV(CMovI.getOpcode());
+ unsigned CondReg;
+ bool Inverted;
+ std::tie(CondReg, Inverted) =
+ getCondOrInverseInReg(TestMBB, TestPos, TestLoc, Cond, CondRegs);
+
+ MachineBasicBlock &MBB = *CMovI.getParent();
+
+ // Insert a direct test of the saved register.
+ insertTest(MBB, CMovI.getIterator(), CMovI.getDebugLoc(), CondReg);
+
+ auto getFCMOVOpcode = [](unsigned Opcode, bool Inverted) {
+ switch (Opcode) {
+ default: llvm_unreachable("Unexpected opcode!");
+ case X86::CMOVBE_Fp32: case X86::CMOVNBE_Fp32:
+ case X86::CMOVB_Fp32: case X86::CMOVNB_Fp32:
+ case X86::CMOVE_Fp32: case X86::CMOVNE_Fp32:
+ case X86::CMOVP_Fp32: case X86::CMOVNP_Fp32:
+ return Inverted ? X86::CMOVE_Fp32 : X86::CMOVNE_Fp32;
+ case X86::CMOVBE_Fp64: case X86::CMOVNBE_Fp64:
+ case X86::CMOVB_Fp64: case X86::CMOVNB_Fp64:
+ case X86::CMOVE_Fp64: case X86::CMOVNE_Fp64:
+ case X86::CMOVP_Fp64: case X86::CMOVNP_Fp64:
+ return Inverted ? X86::CMOVE_Fp64 : X86::CMOVNE_Fp64;
+ case X86::CMOVBE_Fp80: case X86::CMOVNBE_Fp80:
+ case X86::CMOVB_Fp80: case X86::CMOVNB_Fp80:
+ case X86::CMOVE_Fp80: case X86::CMOVNE_Fp80:
+ case X86::CMOVP_Fp80: case X86::CMOVNP_Fp80:
+ return Inverted ? X86::CMOVE_Fp80 : X86::CMOVNE_Fp80;
+ }
+ };
+
+ // Rewrite the CMov to use the !ZF flag from the test.
+ CMovI.setDesc(TII->get(getFCMOVOpcode(CMovI.getOpcode(), Inverted)));
+ FlagUse.setIsKill(true);
+ LLVM_DEBUG(dbgs() << " fixed fcmov: "; CMovI.dump());
+}
+
void X86FlagsCopyLoweringPass::rewriteCondJmp(
MachineBasicBlock &TestMBB, MachineBasicBlock::iterator TestPos,
DebugLoc TestLoc, MachineInstr &JmpI, CondRegArray &CondRegs) {