GlobalISel: translate floating-point comparisons

llvm-svn: 279319
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
index 3fc09fe..8d83538 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
@@ -134,8 +134,19 @@
   /// Translate a phi instruction.
   bool translatePHI(const User &U);
 
+  /// Translate a comparison (icmp or fcmp) instruction or constant.
+  bool translateCompare(const User &U);
+
   /// Translate an integer compare instruction (or constant).
-  bool translateICmp(const User &U);
+  bool translateICmp(const User &U) {
+    return translateCompare(U);
+  }
+
+  /// Translate a floating-point compare instruction (or constant).
+  bool translateFCmp(const User &U) {
+    return translateCompare(U);
+  }
+
 
   /// Add remaining operands onto phis we've translated. Executed after all
   /// MachineBasicBlocks for the function have been created.
@@ -273,7 +284,6 @@
   bool translateAddrSpaceCast(const User &U) { return false; }
   bool translateCleanupPad(const User &U) { return false; }
   bool translateCatchPad(const User &U) { return false; }
-  bool translateFCmp(const User &U) { return false; }
   bool translateUserOp1(const User &U) { return false; }
   bool translateUserOp2(const User &U) { return false; }
   bool translateVAArg(const User &U) { return false; }
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index c8531e2..daaf511 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -320,6 +320,14 @@
   MachineInstrBuilder buildICmp(ArrayRef<LLT> Tys, CmpInst::Predicate Pred,
                                 unsigned Res, unsigned Op0, unsigned Op1);
 
+  /// Build and insert a G_FCMP
+  ///
+  /// \pre setBasicBlock or setMI must have been called.
+  ///
+  /// \return a MachineInstrBuilder for the newly created instruction.
+  MachineInstrBuilder buildFCmp(ArrayRef<LLT> Tys, CmpInst::Predicate Pred,
+                                unsigned Res, unsigned Op0, unsigned Op1);
+
   /// Build and insert a \p Res = G_SELECT { \p Ty, s1 } \p Tst, \p Op0, \p Op1
   ///
   /// \pre setBasicBlock or setMI must have been called.
diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td
index 9a4fde0..f234525 100644
--- a/llvm/include/llvm/Target/GenericOpcodes.td
+++ b/llvm/include/llvm/Target/GenericOpcodes.td
@@ -190,13 +190,20 @@
   let hasSideEffects = 0;
 }
 
-// Generic bitwise or.
+// Generic integer comparison.
 def G_ICMP : Instruction {
   let OutOperandList = (outs unknown:$dst);
   let InOperandList = (ins unknown:$tst, unknown:$src1, unknown:$src2);
   let hasSideEffects = 0;
 }
 
+// Generic floating-point comparison.
+def G_FCMP : Instruction {
+  let OutOperandList = (outs unknown:$dst);
+  let InOperandList = (ins unknown:$tst, unknown:$src1, unknown:$src2);
+  let hasSideEffects = 0;
+}
+
 // Generic select
 def G_SELECT : Instruction {
   let OutOperandList = (outs unknown:$dst);
diff --git a/llvm/include/llvm/Target/TargetOpcodes.def b/llvm/include/llvm/Target/TargetOpcodes.def
index ad87497..ff06ace 100644
--- a/llvm/include/llvm/Target/TargetOpcodes.def
+++ b/llvm/include/llvm/Target/TargetOpcodes.def
@@ -265,6 +265,9 @@
 /// Generic integer-base comparison, also applicable to vectors of integers.
 HANDLE_TARGET_OPCODE(G_ICMP)
 
+/// Generic floating-point comparison, also applicable to vectors.
+HANDLE_TARGET_OPCODE(G_FCMP)
+
 /// Generic select.
 HANDLE_TARGET_OPCODE(G_SELECT)
 
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 1a243c5..36150c6 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -100,17 +100,24 @@
   return true;
 }
 
-bool IRTranslator::translateICmp(const User &U) {
-  const CmpInst &CI = cast<CmpInst>(U);
-  unsigned Op0 = getOrCreateVReg(*CI.getOperand(0));
-  unsigned Op1 = getOrCreateVReg(*CI.getOperand(1));
-  unsigned Res = getOrCreateVReg(CI);
-  CmpInst::Predicate Pred = CI.getPredicate();
+bool IRTranslator::translateCompare(const User &U) {
+  const CmpInst *CI = dyn_cast<CmpInst>(&U);
+  unsigned Op0 = getOrCreateVReg(*U.getOperand(0));
+  unsigned Op1 = getOrCreateVReg(*U.getOperand(1));
+  unsigned Res = getOrCreateVReg(U);
+  CmpInst::Predicate Pred =
+      CI ? CI->getPredicate() : static_cast<CmpInst::Predicate>(
+                                    cast<ConstantExpr>(U).getPredicate());
 
-  assert(isa<ICmpInst>(CI) && "only integer comparisons supported now");
-  assert(CmpInst::isIntPredicate(Pred) && "only int comparisons supported now");
-  MIRBuilder.buildICmp({LLT{*CI.getType()}, LLT{*CI.getOperand(0)->getType()}},
-                       Pred, Res, Op0, Op1);
+  if (CmpInst::isIntPredicate(Pred))
+    MIRBuilder.buildICmp(
+        {LLT{*U.getType()}, LLT{*U.getOperand(0)->getType()}}, Pred, Res, Op0,
+        Op1);
+  else
+    MIRBuilder.buildFCmp(
+        {LLT{*U.getType()}, LLT{*U.getOperand(0)->getType()}}, Pred, Res, Op0,
+        Op1);
+
   return true;
 }
 
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 2fe6eab..aa64be5 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -222,6 +222,17 @@
       .addUse(Op1);
 }
 
+MachineInstrBuilder MachineIRBuilder::buildFCmp(ArrayRef<LLT> Tys,
+                                                CmpInst::Predicate Pred,
+                                                unsigned Res, unsigned Op0,
+                                                unsigned Op1) {
+  return buildInstr(TargetOpcode::G_FCMP, Tys)
+      .addDef(Res)
+      .addPredicate(Pred)
+      .addUse(Op0)
+      .addUse(Op1);
+}
+
 MachineInstrBuilder MachineIRBuilder::buildSelect(LLT Ty, unsigned Res,
                                                   unsigned Tst,
                                                   unsigned Op0, unsigned Op1) {
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll
index fd823f9..d8742e4 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll
@@ -793,3 +793,19 @@
   store float 1.5, float* %addr
   ret void
 }
+
+; CHECK-LABEL: name: float_comparison
+; CHECK: [[LHSADDR:%[0-9]+]](64) = COPY %x0
+; CHECK: [[RHSADDR:%[0-9]+]](64) = COPY %x1
+; CHECK: [[BOOLADDR:%[0-9]+]](64) = COPY %x2
+; CHECK: [[LHS:%[0-9]+]](32) = G_LOAD { s32, p0 } [[LHSADDR]]
+; CHECK: [[RHS:%[0-9]+]](32) = G_LOAD { s32, p0 } [[RHSADDR]]
+; CHECK: [[TST:%[0-9]+]](1) = G_FCMP { s1, s32 } floatpred(oge), [[LHS]], [[RHS]]
+; CHECK: G_STORE { s1, p0 } [[TST]], [[BOOLADDR]]
+define void @float_comparison(float* %a.addr, float* %b.addr, i1* %bool.addr) {
+  %a = load float, float* %a.addr
+  %b = load float, float* %b.addr
+  %res = fcmp oge float %a, %b
+  store i1 %res, i1* %bool.addr
+  ret void
+}