[llvm] r353077 - GlobalISel: Fix CSE handling of buildConstant

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 4 11:15:50 PST 2019


Author: arsenm
Date: Mon Feb  4 11:15:50 2019
New Revision: 353077

URL: http://llvm.org/viewvc/llvm-project?rev=353077&view=rev
Log:
GlobalISel: Fix CSE handling of buildConstant

This fixes two problems with CSE done in buildConstant. First, this
would hit an assert when used with a vector result type. Solve this by
allowing CSE on the vector elements, but not on the result vector for
now.

Second, this was also performing the CSE based on the input
ConstantInt pointer. The underlying buildConstant could potentially
convert the constant depending on the result type, giving in a
different ConstantInt*. Stop allowing the APInt and ConstantInt forms
from automatically casting to the result type to avoid any similar
problems in the future.

Modified:
    llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
    llvm/trunk/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp
    llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
    llvm/trunk/unittests/CodeGen/GlobalISel/CSETest.cpp
    llvm/trunk/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp

Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h?rev=353077&r1=353076&r2=353077&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h Mon Feb  4 11:15:50 2019
@@ -585,6 +585,7 @@ public:
   ///
   /// \return The newly created instruction.
   MachineInstrBuilder buildConstant(const DstOp &Res, int64_t Val);
+  MachineInstrBuilder buildConstant(const DstOp &Res, const APInt &Val);
 
   /// Build and insert \p Res = G_FCONSTANT \p Val
   ///
@@ -710,6 +711,11 @@ public:
   MachineInstrBuilder buildBuildVector(const DstOp &Res,
                                        ArrayRef<unsigned> Ops);
 
+  /// Build and insert \p Res = G_BUILD_VECTOR with \p Src0 replicated to fill
+  /// the number of elements
+  MachineInstrBuilder buildSplatVector(const DstOp &Res,
+                                       const SrcOp &Src);
+
   /// Build and insert \p Res = G_BUILD_VECTOR_TRUNC \p Op0, ...
   ///
   /// G_BUILD_VECTOR_TRUNC creates a vector value from multiple scalar registers

Modified: llvm/trunk/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp?rev=353077&r1=353076&r2=353077&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp Mon Feb  4 11:15:50 2019
@@ -194,6 +194,12 @@ MachineInstrBuilder CSEMIRBuilder::build
   constexpr unsigned Opc = TargetOpcode::G_CONSTANT;
   if (!canPerformCSEForOpc(Opc))
     return MachineIRBuilder::buildConstant(Res, Val);
+
+  // For vectors, CSE the element only for now.
+  LLT Ty = Res.getLLTTy(*getMRI());
+  if (Ty.isVector())
+    return buildSplatVector(Res, buildConstant(Ty.getElementType(), Val));
+
   FoldingSetNodeID ID;
   GISelInstProfileBuilder ProfBuilder(ID, *getMRI());
   void *InsertPos = nullptr;
@@ -205,6 +211,7 @@ MachineInstrBuilder CSEMIRBuilder::build
     // Handle generating copies here.
     return generateCopiesIfRequired({Res}, MIB);
   }
+
   MachineInstrBuilder NewMIB = MachineIRBuilder::buildConstant(Res, Val);
   return memoizeMI(NewMIB, InsertPos);
 }
@@ -214,6 +221,12 @@ MachineInstrBuilder CSEMIRBuilder::build
   constexpr unsigned Opc = TargetOpcode::G_FCONSTANT;
   if (!canPerformCSEForOpc(Opc))
     return MachineIRBuilder::buildFConstant(Res, Val);
+
+  // For vectors, CSE the element only for now.
+  LLT Ty = Res.getLLTTy(*getMRI());
+  if (Ty.isVector())
+    return buildSplatVector(Res, buildFConstant(Ty.getElementType(), Val));
+
   FoldingSetNodeID ID;
   GISelInstProfileBuilder ProfBuilder(ID, *getMRI());
   void *InsertPos = nullptr;

Modified: llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp?rev=353077&r1=353076&r2=353077&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp Mon Feb  4 11:15:50 2019
@@ -244,38 +244,26 @@ MachineInstrBuilder MachineIRBuilder::bu
                                                     const ConstantInt &Val) {
   LLT Ty = Res.getLLTTy(*getMRI());
   LLT EltTy = Ty.getScalarType();
-
-  const ConstantInt *NewVal = &Val;
-  if (EltTy.getSizeInBits() != Val.getBitWidth()) {
-    NewVal = ConstantInt::get(
-      getMF().getFunction().getContext(),
-      Val.getValue().sextOrTrunc(EltTy.getSizeInBits()));
-  }
+  assert(EltTy.getScalarSizeInBits() == Val.getBitWidth() &&
+         "creating constant with the wrong size");
 
   if (Ty.isVector()) {
-    unsigned EltReg = getMRI()->createGenericVirtualRegister(EltTy);
-    buildInstr(TargetOpcode::G_CONSTANT)
-      .addDef(EltReg)
-      .addCImm(NewVal);
-
-    auto MIB = buildInstr(TargetOpcode::G_BUILD_VECTOR);
-    Res.addDefToMIB(*getMRI(), MIB);
-
-    for (unsigned I = 0, E = Ty.getNumElements(); I != E; ++I)
-      MIB.addUse(EltReg);
-    return MIB;
+    auto Const = buildInstr(TargetOpcode::G_CONSTANT)
+    .addDef(getMRI()->createGenericVirtualRegister(EltTy))
+    .addCImm(&Val);
+    return buildSplatVector(Res, Const);
   }
 
-  auto MIB = buildInstr(TargetOpcode::G_CONSTANT);
-  Res.addDefToMIB(*getMRI(), MIB);
-  MIB.addCImm(NewVal);
-  return MIB;
+  auto Const = buildInstr(TargetOpcode::G_CONSTANT);
+  Res.addDefToMIB(*getMRI(), Const);
+  Const.addCImm(&Val);
+  return Const;
 }
 
 MachineInstrBuilder MachineIRBuilder::buildConstant(const DstOp &Res,
                                                     int64_t Val) {
   auto IntN = IntegerType::get(getMF().getFunction().getContext(),
-                               Res.getLLTTy(*getMRI()).getSizeInBits());
+                               Res.getLLTTy(*getMRI()).getScalarSizeInBits());
   ConstantInt *CI = ConstantInt::get(IntN, Val, true);
   return buildConstant(Res, *CI);
 }
@@ -283,28 +271,32 @@ MachineInstrBuilder MachineIRBuilder::bu
 MachineInstrBuilder MachineIRBuilder::buildFConstant(const DstOp &Res,
                                                      const ConstantFP &Val) {
   LLT Ty = Res.getLLTTy(*getMRI());
+  LLT EltTy = Ty.getScalarType();
+
+  assert(APFloat::getSizeInBits(Val.getValueAPF().getSemantics())
+         == EltTy.getSizeInBits() &&
+         "creating fconstant with the wrong size");
 
   assert(!Ty.isPointer() && "invalid operand type");
 
   if (Ty.isVector()) {
-    unsigned EltReg
-      = getMRI()->createGenericVirtualRegister(Ty.getElementType());
-    buildInstr(TargetOpcode::G_FCONSTANT)
-      .addDef(EltReg)
-      .addFPImm(&Val);
-
-    auto MIB = buildInstr(TargetOpcode::G_BUILD_VECTOR);
-    Res.addDefToMIB(*getMRI(), MIB);
-
-    for (unsigned I = 0, E = Ty.getNumElements(); I != E; ++I)
-      MIB.addUse(EltReg);
-    return MIB;
+    auto Const = buildInstr(TargetOpcode::G_FCONSTANT)
+    .addDef(getMRI()->createGenericVirtualRegister(EltTy))
+    .addFPImm(&Val);
+
+    return buildSplatVector(Res, Const);
   }
 
-  auto MIB = buildInstr(TargetOpcode::G_FCONSTANT);
-  Res.addDefToMIB(*getMRI(), MIB);
-  MIB.addFPImm(&Val);
-  return MIB;
+  auto Const = buildInstr(TargetOpcode::G_FCONSTANT);
+  Res.addDefToMIB(*getMRI(), Const);
+  Const.addFPImm(&Val);
+  return Const;
+}
+
+MachineInstrBuilder MachineIRBuilder::buildConstant(const DstOp &Res,
+                                                    const APInt &Val) {
+  ConstantInt *CI = ConstantInt::get(getMF().getFunction().getContext(), Val);
+  return buildConstant(Res, *CI);
 }
 
 MachineInstrBuilder MachineIRBuilder::buildFConstant(const DstOp &Res,
@@ -312,7 +304,7 @@ MachineInstrBuilder MachineIRBuilder::bu
   LLT DstTy = Res.getLLTTy(*getMRI());
   auto &Ctx = getMF().getFunction().getContext();
   auto *CFP =
-      ConstantFP::get(Ctx, getAPFloatFromSize(Val, DstTy.getSizeInBits()));
+      ConstantFP::get(Ctx, getAPFloatFromSize(Val, DstTy.getScalarSizeInBits()));
   return buildFConstant(Res, *CFP);
 }
 
@@ -557,6 +549,12 @@ MachineInstrBuilder MachineIRBuilder::bu
   return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
 }
 
+MachineInstrBuilder MachineIRBuilder::buildSplatVector(const DstOp &Res,
+                                                       const SrcOp &Src) {
+  SmallVector<SrcOp, 8> TmpVec(Res.getLLTTy(*getMRI()).getNumElements(), Src);
+  return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
+}
+
 MachineInstrBuilder
 MachineIRBuilder::buildBuildVectorTrunc(const DstOp &Res,
                                         ArrayRef<unsigned> Ops) {

Modified: llvm/trunk/unittests/CodeGen/GlobalISel/CSETest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CodeGen/GlobalISel/CSETest.cpp?rev=353077&r1=353076&r2=353077&view=diff
==============================================================================
--- llvm/trunk/unittests/CodeGen/GlobalISel/CSETest.cpp (original)
+++ llvm/trunk/unittests/CodeGen/GlobalISel/CSETest.cpp Mon Feb  4 11:15:50 2019
@@ -25,6 +25,7 @@ TEST_F(GISelMITest, TestCSE) {
   CSEInfo.analyze(*MF);
   B.setCSEInfo(&CSEInfo);
   CSEMIRBuilder CSEB(B.getState());
+
   CSEB.setInsertPt(*EntryMBB, EntryMBB->begin());
   unsigned AddReg = MRI->createGenericVirtualRegister(s16);
   auto MIBAddCopy =
@@ -54,6 +55,18 @@ TEST_F(GISelMITest, TestCSE) {
   EXPECT_TRUE(&*MIBFP0 == &*MIBFP0_1);
   CSEInfo.print();
 
+  // Make sure buildConstant with a vector type doesn't crash, and the elements
+  // CSE.
+  auto Splat0 = CSEB.buildConstant(LLT::vector(2, s32), 0);
+  EXPECT_EQ(TargetOpcode::G_BUILD_VECTOR, Splat0->getOpcode());
+  EXPECT_EQ(Splat0->getOperand(1).getReg(), Splat0->getOperand(2).getReg());
+  EXPECT_EQ(&*MIBCst, MRI->getVRegDef(Splat0->getOperand(1).getReg()));
+
+  auto FSplat = CSEB.buildFConstant(LLT::vector(2, s32), 1.0);
+  EXPECT_EQ(TargetOpcode::G_BUILD_VECTOR, FSplat->getOpcode());
+  EXPECT_EQ(FSplat->getOperand(1).getReg(), FSplat->getOperand(2).getReg());
+  EXPECT_EQ(&*MIBFP0, MRI->getVRegDef(FSplat->getOperand(1).getReg()));
+
   // Check G_UNMERGE_VALUES
   auto MIBUnmerge = CSEB.buildUnmerge({s32, s32}, Copies[0]);
   auto MIBUnmerge2 = CSEB.buildUnmerge({s32, s32}, Copies[0]);

Modified: llvm/trunk/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp?rev=353077&r1=353076&r2=353077&view=diff
==============================================================================
--- llvm/trunk/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp (original)
+++ llvm/trunk/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp Mon Feb  4 11:15:50 2019
@@ -13,9 +13,6 @@ TEST_F(GISelMITest, TestBuildConstantFCo
   if (!TM)
     return;
 
-  MachineIRBuilder B(*MF);
-  B.setInsertPt(*EntryMBB, EntryMBB->begin());
-
   B.buildConstant(LLT::scalar(32), 42);
   B.buildFConstant(LLT::scalar(32), 1.0);
 
@@ -27,9 +24,44 @@ TEST_F(GISelMITest, TestBuildConstantFCo
   CHECK: [[FCONST0:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.000000e+00
   CHECK: [[CONST1:%[0-9]+]]:_(s32) = G_CONSTANT i32 99
   CHECK: [[VEC0:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[CONST1]]:_(s32), [[CONST1]]:_(s32)
-  CHECK: [[FCONST1:%[0-9]+]]:_(s32) = G_FCONSTANT double 2.000000e+00
+  CHECK: [[FCONST1:%[0-9]+]]:_(s32) = G_FCONSTANT float 2.000000e+00
   CHECK: [[VEC1:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[FCONST1]]:_(s32), [[FCONST1]]:_(s32)
   )";
 
   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
 }
+
+
+#ifdef GTEST_HAS_DEATH_TEST
+#ifndef NDEBUG
+
+TEST_F(GISelMITest, TestBuildConstantFConstantDeath) {
+  if (!TM)
+    return;
+
+  LLVMContext &Ctx = MF->getFunction().getContext();
+  APInt APV32(32, 12345);
+
+  // Test APInt version breaks
+  EXPECT_DEATH(B.buildConstant(LLT::scalar(16), APV32),
+               "creating constant with the wrong size");
+  EXPECT_DEATH(B.buildConstant(LLT::vector(2, 16), APV32),
+               "creating constant with the wrong size");
+
+  // Test ConstantInt version breaks
+  ConstantInt *CI = ConstantInt::get(Ctx, APV32);
+  EXPECT_DEATH(B.buildConstant(LLT::scalar(16), *CI),
+               "creating constant with the wrong size");
+  EXPECT_DEATH(B.buildConstant(LLT::vector(2, 16), *CI),
+               "creating constant with the wrong size");
+
+  APFloat DoubleVal(APFloat::IEEEdouble());
+  ConstantFP *CF = ConstantFP::get(Ctx, DoubleVal);
+  EXPECT_DEATH(B.buildFConstant(LLT::scalar(16), *CF),
+               "creating fconstant with the wrong size");
+  EXPECT_DEATH(B.buildFConstant(LLT::vector(2, 16), *CF),
+               "creating fconstant with the wrong size");
+}
+
+#endif
+#endif




More information about the llvm-commits mailing list