Skip to content

Commit 8121ec2

Browse files
committed
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. llvm-svn: 353077
1 parent a1cc4ea commit 8121ec2

File tree

5 files changed

+106
-44
lines changed

5 files changed

+106
-44
lines changed

llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,7 @@ class MachineIRBuilder {
585585
///
586586
/// \return The newly created instruction.
587587
MachineInstrBuilder buildConstant(const DstOp &Res, int64_t Val);
588+
MachineInstrBuilder buildConstant(const DstOp &Res, const APInt &Val);
588589

589590
/// Build and insert \p Res = G_FCONSTANT \p Val
590591
///
@@ -710,6 +711,11 @@ class MachineIRBuilder {
710711
MachineInstrBuilder buildBuildVector(const DstOp &Res,
711712
ArrayRef<unsigned> Ops);
712713

714+
/// Build and insert \p Res = G_BUILD_VECTOR with \p Src0 replicated to fill
715+
/// the number of elements
716+
MachineInstrBuilder buildSplatVector(const DstOp &Res,
717+
const SrcOp &Src);
718+
713719
/// Build and insert \p Res = G_BUILD_VECTOR_TRUNC \p Op0, ...
714720
///
715721
/// G_BUILD_VECTOR_TRUNC creates a vector value from multiple scalar registers

llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,12 @@ MachineInstrBuilder CSEMIRBuilder::buildConstant(const DstOp &Res,
194194
constexpr unsigned Opc = TargetOpcode::G_CONSTANT;
195195
if (!canPerformCSEForOpc(Opc))
196196
return MachineIRBuilder::buildConstant(Res, Val);
197+
198+
// For vectors, CSE the element only for now.
199+
LLT Ty = Res.getLLTTy(*getMRI());
200+
if (Ty.isVector())
201+
return buildSplatVector(Res, buildConstant(Ty.getElementType(), Val));
202+
197203
FoldingSetNodeID ID;
198204
GISelInstProfileBuilder ProfBuilder(ID, *getMRI());
199205
void *InsertPos = nullptr;
@@ -205,6 +211,7 @@ MachineInstrBuilder CSEMIRBuilder::buildConstant(const DstOp &Res,
205211
// Handle generating copies here.
206212
return generateCopiesIfRequired({Res}, MIB);
207213
}
214+
208215
MachineInstrBuilder NewMIB = MachineIRBuilder::buildConstant(Res, Val);
209216
return memoizeMI(NewMIB, InsertPos);
210217
}
@@ -214,6 +221,12 @@ MachineInstrBuilder CSEMIRBuilder::buildFConstant(const DstOp &Res,
214221
constexpr unsigned Opc = TargetOpcode::G_FCONSTANT;
215222
if (!canPerformCSEForOpc(Opc))
216223
return MachineIRBuilder::buildFConstant(Res, Val);
224+
225+
// For vectors, CSE the element only for now.
226+
LLT Ty = Res.getLLTTy(*getMRI());
227+
if (Ty.isVector())
228+
return buildSplatVector(Res, buildFConstant(Ty.getElementType(), Val));
229+
217230
FoldingSetNodeID ID;
218231
GISelInstProfileBuilder ProfBuilder(ID, *getMRI());
219232
void *InsertPos = nullptr;

llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -244,75 +244,67 @@ MachineInstrBuilder MachineIRBuilder::buildConstant(const DstOp &Res,
244244
const ConstantInt &Val) {
245245
LLT Ty = Res.getLLTTy(*getMRI());
246246
LLT EltTy = Ty.getScalarType();
247-
248-
const ConstantInt *NewVal = &Val;
249-
if (EltTy.getSizeInBits() != Val.getBitWidth()) {
250-
NewVal = ConstantInt::get(
251-
getMF().getFunction().getContext(),
252-
Val.getValue().sextOrTrunc(EltTy.getSizeInBits()));
253-
}
247+
assert(EltTy.getScalarSizeInBits() == Val.getBitWidth() &&
248+
"creating constant with the wrong size");
254249

255250
if (Ty.isVector()) {
256-
unsigned EltReg = getMRI()->createGenericVirtualRegister(EltTy);
257-
buildInstr(TargetOpcode::G_CONSTANT)
258-
.addDef(EltReg)
259-
.addCImm(NewVal);
260-
261-
auto MIB = buildInstr(TargetOpcode::G_BUILD_VECTOR);
262-
Res.addDefToMIB(*getMRI(), MIB);
263-
264-
for (unsigned I = 0, E = Ty.getNumElements(); I != E; ++I)
265-
MIB.addUse(EltReg);
266-
return MIB;
251+
auto Const = buildInstr(TargetOpcode::G_CONSTANT)
252+
.addDef(getMRI()->createGenericVirtualRegister(EltTy))
253+
.addCImm(&Val);
254+
return buildSplatVector(Res, Const);
267255
}
268256

269-
auto MIB = buildInstr(TargetOpcode::G_CONSTANT);
270-
Res.addDefToMIB(*getMRI(), MIB);
271-
MIB.addCImm(NewVal);
272-
return MIB;
257+
auto Const = buildInstr(TargetOpcode::G_CONSTANT);
258+
Res.addDefToMIB(*getMRI(), Const);
259+
Const.addCImm(&Val);
260+
return Const;
273261
}
274262

275263
MachineInstrBuilder MachineIRBuilder::buildConstant(const DstOp &Res,
276264
int64_t Val) {
277265
auto IntN = IntegerType::get(getMF().getFunction().getContext(),
278-
Res.getLLTTy(*getMRI()).getSizeInBits());
266+
Res.getLLTTy(*getMRI()).getScalarSizeInBits());
279267
ConstantInt *CI = ConstantInt::get(IntN, Val, true);
280268
return buildConstant(Res, *CI);
281269
}
282270

283271
MachineInstrBuilder MachineIRBuilder::buildFConstant(const DstOp &Res,
284272
const ConstantFP &Val) {
285273
LLT Ty = Res.getLLTTy(*getMRI());
274+
LLT EltTy = Ty.getScalarType();
275+
276+
assert(APFloat::getSizeInBits(Val.getValueAPF().getSemantics())
277+
== EltTy.getSizeInBits() &&
278+
"creating fconstant with the wrong size");
286279

287280
assert(!Ty.isPointer() && "invalid operand type");
288281

289282
if (Ty.isVector()) {
290-
unsigned EltReg
291-
= getMRI()->createGenericVirtualRegister(Ty.getElementType());
292-
buildInstr(TargetOpcode::G_FCONSTANT)
293-
.addDef(EltReg)
294-
.addFPImm(&Val);
295-
296-
auto MIB = buildInstr(TargetOpcode::G_BUILD_VECTOR);
297-
Res.addDefToMIB(*getMRI(), MIB);
298-
299-
for (unsigned I = 0, E = Ty.getNumElements(); I != E; ++I)
300-
MIB.addUse(EltReg);
301-
return MIB;
283+
auto Const = buildInstr(TargetOpcode::G_FCONSTANT)
284+
.addDef(getMRI()->createGenericVirtualRegister(EltTy))
285+
.addFPImm(&Val);
286+
287+
return buildSplatVector(Res, Const);
302288
}
303289

304-
auto MIB = buildInstr(TargetOpcode::G_FCONSTANT);
305-
Res.addDefToMIB(*getMRI(), MIB);
306-
MIB.addFPImm(&Val);
307-
return MIB;
290+
auto Const = buildInstr(TargetOpcode::G_FCONSTANT);
291+
Res.addDefToMIB(*getMRI(), Const);
292+
Const.addFPImm(&Val);
293+
return Const;
294+
}
295+
296+
MachineInstrBuilder MachineIRBuilder::buildConstant(const DstOp &Res,
297+
const APInt &Val) {
298+
ConstantInt *CI = ConstantInt::get(getMF().getFunction().getContext(), Val);
299+
return buildConstant(Res, *CI);
308300
}
309301

310302
MachineInstrBuilder MachineIRBuilder::buildFConstant(const DstOp &Res,
311303
double Val) {
312304
LLT DstTy = Res.getLLTTy(*getMRI());
313305
auto &Ctx = getMF().getFunction().getContext();
314306
auto *CFP =
315-
ConstantFP::get(Ctx, getAPFloatFromSize(Val, DstTy.getSizeInBits()));
307+
ConstantFP::get(Ctx, getAPFloatFromSize(Val, DstTy.getScalarSizeInBits()));
316308
return buildFConstant(Res, *CFP);
317309
}
318310

@@ -557,6 +549,12 @@ MachineInstrBuilder MachineIRBuilder::buildBuildVector(const DstOp &Res,
557549
return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
558550
}
559551

552+
MachineInstrBuilder MachineIRBuilder::buildSplatVector(const DstOp &Res,
553+
const SrcOp &Src) {
554+
SmallVector<SrcOp, 8> TmpVec(Res.getLLTTy(*getMRI()).getNumElements(), Src);
555+
return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
556+
}
557+
560558
MachineInstrBuilder
561559
MachineIRBuilder::buildBuildVectorTrunc(const DstOp &Res,
562560
ArrayRef<unsigned> Ops) {

llvm/unittests/CodeGen/GlobalISel/CSETest.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ TEST_F(GISelMITest, TestCSE) {
2525
CSEInfo.analyze(*MF);
2626
B.setCSEInfo(&CSEInfo);
2727
CSEMIRBuilder CSEB(B.getState());
28+
2829
CSEB.setInsertPt(*EntryMBB, EntryMBB->begin());
2930
unsigned AddReg = MRI->createGenericVirtualRegister(s16);
3031
auto MIBAddCopy =
@@ -54,6 +55,18 @@ TEST_F(GISelMITest, TestCSE) {
5455
EXPECT_TRUE(&*MIBFP0 == &*MIBFP0_1);
5556
CSEInfo.print();
5657

58+
// Make sure buildConstant with a vector type doesn't crash, and the elements
59+
// CSE.
60+
auto Splat0 = CSEB.buildConstant(LLT::vector(2, s32), 0);
61+
EXPECT_EQ(TargetOpcode::G_BUILD_VECTOR, Splat0->getOpcode());
62+
EXPECT_EQ(Splat0->getOperand(1).getReg(), Splat0->getOperand(2).getReg());
63+
EXPECT_EQ(&*MIBCst, MRI->getVRegDef(Splat0->getOperand(1).getReg()));
64+
65+
auto FSplat = CSEB.buildFConstant(LLT::vector(2, s32), 1.0);
66+
EXPECT_EQ(TargetOpcode::G_BUILD_VECTOR, FSplat->getOpcode());
67+
EXPECT_EQ(FSplat->getOperand(1).getReg(), FSplat->getOperand(2).getReg());
68+
EXPECT_EQ(&*MIBFP0, MRI->getVRegDef(FSplat->getOperand(1).getReg()));
69+
5770
// Check G_UNMERGE_VALUES
5871
auto MIBUnmerge = CSEB.buildUnmerge({s32, s32}, Copies[0]);
5972
auto MIBUnmerge2 = CSEB.buildUnmerge({s32, s32}, Copies[0]);

llvm/unittests/CodeGen/GlobalISel/MachineIRBuilderTest.cpp

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ TEST_F(GISelMITest, TestBuildConstantFConstant) {
1313
if (!TM)
1414
return;
1515

16-
MachineIRBuilder B(*MF);
17-
B.setInsertPt(*EntryMBB, EntryMBB->begin());
18-
1916
B.buildConstant(LLT::scalar(32), 42);
2017
B.buildFConstant(LLT::scalar(32), 1.0);
2118

@@ -27,9 +24,44 @@ TEST_F(GISelMITest, TestBuildConstantFConstant) {
2724
CHECK: [[FCONST0:%[0-9]+]]:_(s32) = G_FCONSTANT float 1.000000e+00
2825
CHECK: [[CONST1:%[0-9]+]]:_(s32) = G_CONSTANT i32 99
2926
CHECK: [[VEC0:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[CONST1]]:_(s32), [[CONST1]]:_(s32)
30-
CHECK: [[FCONST1:%[0-9]+]]:_(s32) = G_FCONSTANT double 2.000000e+00
27+
CHECK: [[FCONST1:%[0-9]+]]:_(s32) = G_FCONSTANT float 2.000000e+00
3128
CHECK: [[VEC1:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[FCONST1]]:_(s32), [[FCONST1]]:_(s32)
3229
)";
3330

3431
EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
3532
}
33+
34+
35+
#ifdef GTEST_HAS_DEATH_TEST
36+
#ifndef NDEBUG
37+
38+
TEST_F(GISelMITest, TestBuildConstantFConstantDeath) {
39+
if (!TM)
40+
return;
41+
42+
LLVMContext &Ctx = MF->getFunction().getContext();
43+
APInt APV32(32, 12345);
44+
45+
// Test APInt version breaks
46+
EXPECT_DEATH(B.buildConstant(LLT::scalar(16), APV32),
47+
"creating constant with the wrong size");
48+
EXPECT_DEATH(B.buildConstant(LLT::vector(2, 16), APV32),
49+
"creating constant with the wrong size");
50+
51+
// Test ConstantInt version breaks
52+
ConstantInt *CI = ConstantInt::get(Ctx, APV32);
53+
EXPECT_DEATH(B.buildConstant(LLT::scalar(16), *CI),
54+
"creating constant with the wrong size");
55+
EXPECT_DEATH(B.buildConstant(LLT::vector(2, 16), *CI),
56+
"creating constant with the wrong size");
57+
58+
APFloat DoubleVal(APFloat::IEEEdouble());
59+
ConstantFP *CF = ConstantFP::get(Ctx, DoubleVal);
60+
EXPECT_DEATH(B.buildFConstant(LLT::scalar(16), *CF),
61+
"creating fconstant with the wrong size");
62+
EXPECT_DEATH(B.buildFConstant(LLT::vector(2, 16), *CF),
63+
"creating fconstant with the wrong size");
64+
}
65+
66+
#endif
67+
#endif

0 commit comments

Comments
 (0)