[llvm] 468a0cb - [X86] Add X87 FCMOV support to X86FlagsCopyLowering.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 31 20:49:27 PST 2019


Author: Craig Topper
Date: 2019-12-31T20:35:21-08:00
New Revision: 468a0cb5f39454a26c99f1d80fa7e24936f47bf7

URL: https://github.com/llvm/llvm-project/commit/468a0cb5f39454a26c99f1d80fa7e24936f47bf7
DIFF: https://github.com/llvm/llvm-project/commit/468a0cb5f39454a26c99f1d80fa7e24936f47bf7.diff

LOG: [X86] Add X87 FCMOV support to X86FlagsCopyLowering.

Fixes PR44396

Added: 
    llvm/test/CodeGen/X86/pr44396.ll

Modified: 
    llvm/lib/Target/X86/X86FlagsCopyLowering.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
index 46fe5b54fade..0915a1532df9 100644
--- a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
+++ b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
@@ -115,6 +115,10 @@ class X86FlagsCopyLoweringPass : public MachineFunctionPass {
                    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) {
@@ -852,6 +880,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) {

diff  --git a/llvm/test/CodeGen/X86/pr44396.ll b/llvm/test/CodeGen/X86/pr44396.ll
new file mode 100644
index 000000000000..98e31192522e
--- /dev/null
+++ b/llvm/test/CodeGen/X86/pr44396.ll
@@ -0,0 +1,47 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=i386-apple-macosx10.15.0 -mattr=+cmov | FileCheck %s
+
+ at b = global i32 0, align 4
+ at a = global i64 0, align 8
+
+define double @c() nounwind {
+; CHECK-LABEL: c:
+; CHECK:       ## %bb.0: ## %entry
+; CHECK-NEXT:    pushl %esi
+; CHECK-NEXT:    subl $16, %esp
+; CHECK-NEXT:    movl _b, %eax
+; CHECK-NEXT:    movl %eax, %ecx
+; CHECK-NEXT:    sarl $31, %ecx
+; CHECK-NEXT:    movl _a+4, %edx
+; CHECK-NEXT:    movl _a, %esi
+; CHECK-NEXT:    subl %eax, %esi
+; CHECK-NEXT:    sbbl %ecx, %edx
+; CHECK-NEXT:    setb %al
+; CHECK-NEXT:    xorl %ecx, %ecx
+; CHECK-NEXT:    testl %edx, %edx
+; CHECK-NEXT:    setns %cl
+; CHECK-NEXT:    movl %esi, (%esp)
+; CHECK-NEXT:    movl %edx, {{[0-9]+}}(%esp)
+; CHECK-NEXT:    fildll (%esp)
+; CHECK-NEXT:    fadds LCPI0_0(,%ecx,4)
+; CHECK-NEXT:    fstpl {{[0-9]+}}(%esp)
+; CHECK-NEXT:    fldl {{[0-9]+}}(%esp)
+; CHECK-NEXT:    fldz
+; CHECK-NEXT:    testb %al, %al
+; CHECK-NEXT:    fxch %st(1)
+; CHECK-NEXT:    fcmovne %st(1), %st
+; CHECK-NEXT:    fstp %st(1)
+; CHECK-NEXT:    addl $16, %esp
+; CHECK-NEXT:    popl %esi
+; CHECK-NEXT:    retl
+entry:
+  %0 = load i32, i32* @b, align 4
+  %conv = sext i32 %0 to i64
+  %1 = load i64, i64* @a, align 8
+  %cmp = icmp ult i64 %1, %conv
+  %sub = sub i64 %1, %conv
+  %conv3 = uitofp i64 %sub to double
+  %cond = select i1 %cmp, double 0.000000e+00, double %conv3
+  ret double %cond
+}
+


        


More information about the llvm-commits mailing list