[GISel]: Add helpers for easy building G_FCONSTANT along with matchers
authorAditya Nandakumar <aditya_nandakumar@apple.com>
Fri, 9 Mar 2018 17:31:51 +0000 (17:31 +0000)
committerAditya Nandakumar <aditya_nandakumar@apple.com>
Fri, 9 Mar 2018 17:31:51 +0000 (17:31 +0000)
Added helpers to build G_FCONSTANT, along with matching ConstantFP and
unit tests for the same.

Sample usage.

auto MIB = Builder.buildFConstant(s32, 0.5); // Build IEEESingle
For Matching the above

const ConstantFP* Tmp;
mi_match(DstReg, MRI, m_GFCst(Tmp));

https://reviews.llvm.org/D44128
reviewed by: volkan

llvm-svn: 327152

llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h
llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
llvm/include/llvm/CodeGen/GlobalISel/Utils.h
llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
llvm/lib/CodeGen/GlobalISel/Utils.cpp
llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp

index 2f31cab..336eba7 100644 (file)
@@ -142,6 +142,16 @@ template <> struct bind_helper<LLT> {
   }
 };
 
+template <> struct bind_helper<const ConstantFP *> {
+  static bool bind(const MachineRegisterInfo &MRI, const ConstantFP *&F,
+                   unsigned Reg) {
+    F = getConstantFPVRegVal(Reg, MRI);
+    if (F)
+      return true;
+    return false;
+  }
+};
+
 template <typename Class> struct bind_ty {
   Class &VR;
 
@@ -156,6 +166,9 @@ inline bind_ty<unsigned> m_Reg(unsigned &R) { return R; }
 inline bind_ty<MachineInstr *> m_MInstr(MachineInstr *&MI) { return MI; }
 inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; }
 
+// Helper for matching G_FCONSTANT
+inline bind_ty<const ConstantFP *> m_GFCst(const ConstantFP *&C) { return C; }
+
 // General helper for all the binary generic MI such as G_ADD/G_SUB etc
 template <typename LHS_P, typename RHS_P, unsigned Opcode,
           bool Commutable = false>
index 8a5d027..47d072c 100644 (file)
@@ -572,6 +572,12 @@ public:
   }
   MachineInstrBuilder buildFConstant(unsigned Res, const ConstantFP &Val);
 
+  template <typename DstType>
+  MachineInstrBuilder buildFConstant(DstType &&Res, double Val) {
+    return buildFConstant(getDestFromArg(Res), Val);
+  }
+  MachineInstrBuilder buildFConstant(unsigned Res, double Val);
+
   /// Build and insert \p Res = COPY Op
   ///
   /// Register-to-register COPY sets \p Res to \p Op.
index 36cf652..837035f 100644 (file)
@@ -33,6 +33,7 @@ class TargetRegisterInfo;
 class TargetRegisterClass;
 class Twine;
 class ConstantFP;
+class APFloat;
 
 /// Try to constrain Reg to the specified register class. If this fails,
 /// create a new virtual register in the correct class and insert a COPY before
@@ -99,5 +100,7 @@ const ConstantFP* getConstantFPVRegVal(unsigned VReg,
 MachineInstr *getOpcodeDef(unsigned Opcode, unsigned Reg,
                            const MachineRegisterInfo &MRI);
 
+/// Returns an APFloat from Val converted to the appropriate size.
+APFloat getAPFloatFromSize(double Val, unsigned Size);
 } // End namespace llvm.
 #endif
index 475bb82..a6c285a 100644 (file)
@@ -284,6 +284,14 @@ MachineInstrBuilder MachineIRBuilder::buildFConstant(unsigned Res,
   return buildInstr(TargetOpcode::G_FCONSTANT).addDef(Res).addFPImm(&Val);
 }
 
+MachineInstrBuilder MachineIRBuilder::buildFConstant(unsigned Res, double Val) {
+  LLT DstTy = MRI->getType(Res);
+  auto &Ctx = MF->getFunction().getContext();
+  auto *CFP =
+      ConstantFP::get(Ctx, getAPFloatFromSize(Val, DstTy.getSizeInBits()));
+  return buildFConstant(Res, *CFP);
+}
+
 MachineInstrBuilder MachineIRBuilder::buildBrCond(unsigned Tst,
                                                   MachineBasicBlock &Dest) {
   assert(MRI->getType(Tst).isScalar() && "invalid operand type");
index b34414b..f39b387 100644 (file)
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/GlobalISel/Utils.h"
+#include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
 #include "llvm/CodeGen/MachineInstr.h"
@@ -212,3 +213,16 @@ llvm::MachineInstr *llvm::getOpcodeDef(unsigned Opcode, unsigned Reg,
   }
   return DefMI->getOpcode() == Opcode ? DefMI : nullptr;
 }
+
+APFloat llvm::getAPFloatFromSize(double Val, unsigned Size) {
+  if (Size == 32)
+    return APFloat(float(Val));
+  if (Size == 64)
+    return APFloat(Val);
+  if (Size != 16)
+    llvm_unreachable("Unsupported FPConstant size");
+  bool Ignored;
+  APFloat APF(Val);
+  APF.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &Ignored);
+  return APF;
+}
index 0816084..d402d0b 100644 (file)
@@ -257,6 +257,42 @@ TEST(PatternMatchInstr, MatchFPUnaryOp) {
   match = mi_match(MIBFabs->getOperand(0).getReg(), MRI, m_GFabs(m_Reg(Src)));
   ASSERT_TRUE(match);
   ASSERT_EQ(Src, Copy0s32->getOperand(0).getReg());
+
+  // Build and match FConstant.
+  auto MIBFCst = B.buildFConstant(s32, .5);
+  const ConstantFP *TmpFP{};
+  match = mi_match(MIBFCst->getOperand(0).getReg(), MRI, m_GFCst(TmpFP));
+  ASSERT_TRUE(match);
+  ASSERT_TRUE(TmpFP);
+  APFloat APF((float).5);
+  auto *CFP = ConstantFP::get(Context, APF);
+  ASSERT_EQ(CFP, TmpFP);
+
+  // Build double float.
+  LLT s64 = LLT::scalar(64);
+  auto MIBFCst64 = B.buildFConstant(s64, .5);
+  const ConstantFP *TmpFP64{};
+  match = mi_match(MIBFCst64->getOperand(0).getReg(), MRI, m_GFCst(TmpFP64));
+  ASSERT_TRUE(match);
+  ASSERT_TRUE(TmpFP64);
+  APFloat APF64(.5);
+  auto CFP64 = ConstantFP::get(Context, APF64);
+  ASSERT_EQ(CFP64, TmpFP64);
+  ASSERT_NE(TmpFP64, TmpFP);
+
+  // Build half float.
+  LLT s16 = LLT::scalar(16);
+  auto MIBFCst16 = B.buildFConstant(s16, .5);
+  const ConstantFP *TmpFP16{};
+  match = mi_match(MIBFCst16->getOperand(0).getReg(), MRI, m_GFCst(TmpFP16));
+  ASSERT_TRUE(match);
+  ASSERT_TRUE(TmpFP16);
+  bool Ignored;
+  APFloat APF16(.5);
+  APF16.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &Ignored);
+  auto CFP16 = ConstantFP::get(Context, APF16);
+  ASSERT_EQ(TmpFP16, CFP16);
+  ASSERT_NE(TmpFP16, TmpFP);
 }
 
 TEST(PatternMatchInstr, MatchExtendsTrunc) {