xref: /llvm-project/llvm/unittests/CodeGen/GlobalISel/CSETest.cpp (revision 220004d2f8692e3a224dc75f7a7c6001711d3d58)
1 //===- CSETest.cpp -----------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "GISelMITest.h"
10 #include "llvm/CodeGen/GlobalISel/CSEInfo.h"
11 #include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h"
12 #include "gtest/gtest.h"
13 
14 namespace {
15 
16 TEST_F(AArch64GISelMITest, TestCSE) {
17   setUp();
18   if (!TM)
19     GTEST_SKIP();
20 
21   LLT s16{LLT::scalar(16)};
22   LLT s32{LLT::scalar(32)};
23   auto MIBInput = B.buildInstr(TargetOpcode::G_TRUNC, {s16}, {Copies[0]});
24   auto MIBInput1 = B.buildInstr(TargetOpcode::G_TRUNC, {s16}, {Copies[1]});
25   auto MIBAdd = B.buildInstr(TargetOpcode::G_ADD, {s16}, {MIBInput, MIBInput});
26   GISelCSEInfo CSEInfo;
27   CSEInfo.setCSEConfig(std::make_unique<CSEConfigFull>());
28   CSEInfo.analyze(*MF);
29   B.setCSEInfo(&CSEInfo);
30   CSEMIRBuilder CSEB(B.getState());
31 
32   CSEB.setInsertPt(B.getMBB(), B.getInsertPt());
33   Register AddReg = MRI->createGenericVirtualRegister(s16);
34   auto MIBAddCopy =
35       CSEB.buildInstr(TargetOpcode::G_ADD, {AddReg}, {MIBInput, MIBInput});
36   EXPECT_EQ(MIBAddCopy->getOpcode(), TargetOpcode::COPY);
37   auto MIBAdd2 =
38       CSEB.buildInstr(TargetOpcode::G_ADD, {s16}, {MIBInput, MIBInput});
39   EXPECT_TRUE(&*MIBAdd == &*MIBAdd2);
40   auto MIBAdd4 =
41       CSEB.buildInstr(TargetOpcode::G_ADD, {s16}, {MIBInput, MIBInput});
42   EXPECT_TRUE(&*MIBAdd == &*MIBAdd4);
43   auto MIBAdd5 =
44       CSEB.buildInstr(TargetOpcode::G_ADD, {s16}, {MIBInput, MIBInput1});
45   EXPECT_TRUE(&*MIBAdd != &*MIBAdd5);
46 
47   // Try building G_CONSTANTS.
48   auto MIBCst = CSEB.buildConstant(s32, 0);
49   auto MIBCst1 = CSEB.buildConstant(s32, 0);
50   EXPECT_TRUE(&*MIBCst == &*MIBCst1);
51   // Try the CFing of BinaryOps.
52   auto MIBCF1 = CSEB.buildInstr(TargetOpcode::G_ADD, {s32}, {MIBCst, MIBCst});
53   EXPECT_TRUE(&*MIBCF1 == &*MIBCst);
54 
55   // Try out building FCONSTANTs.
56   auto MIBFP0 = CSEB.buildFConstant(s32, 1.0);
57   auto MIBFP0_1 = CSEB.buildFConstant(s32, 1.0);
58   EXPECT_TRUE(&*MIBFP0 == &*MIBFP0_1);
59   CSEInfo.print();
60 
61   // Make sure buildConstant with a vector type doesn't crash, and the elements
62   // CSE.
63   auto Splat0 = CSEB.buildConstant(LLT::fixed_vector(2, s32), 0);
64   EXPECT_EQ(TargetOpcode::G_BUILD_VECTOR, Splat0->getOpcode());
65   EXPECT_EQ(Splat0.getReg(1), Splat0.getReg(2));
66   EXPECT_EQ(&*MIBCst, MRI->getVRegDef(Splat0.getReg(1)));
67 
68   auto FSplat = CSEB.buildFConstant(LLT::fixed_vector(2, s32), 1.0);
69   EXPECT_EQ(TargetOpcode::G_BUILD_VECTOR, FSplat->getOpcode());
70   EXPECT_EQ(FSplat.getReg(1), FSplat.getReg(2));
71   EXPECT_EQ(&*MIBFP0, MRI->getVRegDef(FSplat.getReg(1)));
72 
73   // Check G_UNMERGE_VALUES
74   auto MIBUnmerge = CSEB.buildUnmerge({s32, s32}, Copies[0]);
75   auto MIBUnmerge2 = CSEB.buildUnmerge({s32, s32}, Copies[0]);
76   EXPECT_TRUE(&*MIBUnmerge == &*MIBUnmerge2);
77 
78   // Check G_FADD
79   {
80     auto MIBFAdd = CSEB.buildFAdd(s32, Copies[0], Copies[1]);
81     auto MIBFAdd2 = CSEB.buildFAdd(s32, Copies[0], Copies[1]);
82     EXPECT_TRUE(&*MIBFAdd == &*MIBFAdd2);
83 
84     auto MIBFAdd3 =
85         CSEB.buildFAdd(s32, Copies[0], Copies[1], MachineInstr::FmNsz);
86     EXPECT_FALSE(&*MIBFAdd == &*MIBFAdd3);
87 
88     MIBFAdd2->setFlag(MachineInstr::FmNsz);
89     MIBFAdd2->clearFlag(MachineInstr::FmNsz);
90     EXPECT_TRUE(&*MIBFAdd == &*MIBFAdd2);
91   }
92 
93   // Check G_FSUB
94   {
95     auto MIBFSub = CSEB.buildFSub(s32, Copies[0], Copies[1]);
96     auto MIBFSub2 = CSEB.buildFSub(s32, Copies[0], Copies[1]);
97     EXPECT_TRUE(&*MIBFSub == &*MIBFSub2);
98 
99     auto MIBFSub3 =
100         CSEB.buildFSub(s32, Copies[0], Copies[1], MachineInstr::FmNoNans);
101     EXPECT_FALSE(&*MIBFSub == &*MIBFSub3);
102 
103     MIBFSub2->setFlag(MachineInstr::FmNoNans);
104     MIBFSub2->clearFlag(MachineInstr::FmNoNans);
105     EXPECT_TRUE(&*MIBFSub == &*MIBFSub2);
106   }
107 
108   // Check G_FMUL
109   {
110     auto MIBFMul = CSEB.buildFMul(s32, Copies[0], Copies[1]);
111     auto MIBFMul2 = CSEB.buildFMul(s32, Copies[0], Copies[1]);
112     EXPECT_TRUE(&*MIBFMul == &*MIBFMul2);
113 
114     auto MIBFMul3 =
115         CSEB.buildFMul(s32, Copies[0], Copies[1], MachineInstr::FmNoNans);
116     EXPECT_FALSE(&*MIBFMul == &*MIBFMul3);
117 
118     MIBFMul2->setFlag(MachineInstr::FmNoNans);
119     MIBFMul2->clearFlag(MachineInstr::FmNoNans);
120     EXPECT_TRUE(&*MIBFMul == &*MIBFMul2);
121   }
122 
123   // Check G_FDIV
124   {
125     auto MIBFDiv = CSEB.buildFDiv(s32, Copies[0], Copies[1]);
126     auto MIBFDiv2 = CSEB.buildFDiv(s32, Copies[0], Copies[1]);
127     EXPECT_TRUE(&*MIBFDiv == &*MIBFDiv2);
128 
129     auto MIBFDiv3 =
130         CSEB.buildFDiv(s32, Copies[0], Copies[1], MachineInstr::FmNoNans);
131     EXPECT_FALSE(&*MIBFDiv == &*MIBFDiv3);
132 
133     MIBFDiv2->setFlag(MachineInstr::FmNoNans);
134     MIBFDiv2->clearFlag(MachineInstr::FmNoNans);
135     EXPECT_TRUE(&*MIBFDiv == &*MIBFDiv2);
136   }
137 
138   // Check G_FABS
139   {
140     auto MIBFAbs = CSEB.buildFAbs(s32, Copies[0]);
141     auto MIBFAbs2 = CSEB.buildFAbs(s32, Copies[0]);
142     EXPECT_TRUE(&*MIBFAbs == &*MIBFAbs2);
143 
144     auto MIBFAbs3 = CSEB.buildFAbs(s32, Copies[0], MachineInstr::FmNsz);
145     EXPECT_FALSE(&*MIBFAbs == &*MIBFAbs3);
146 
147     MIBFAbs2->setFlag(MachineInstr::FmNsz);
148     MIBFAbs2->clearFlag(MachineInstr::FmNsz);
149     EXPECT_TRUE(&*MIBFAbs == &*MIBFAbs2);
150   }
151 
152   // Check G_FMINNUM/F_MAXNUM:
153   {
154     auto MIBFMinNum = CSEB.buildFMinNum(s32, Copies[0], Copies[1]);
155     auto MIBFMinNum2 = CSEB.buildFMinNum(s32, Copies[0], Copies[1]);
156     EXPECT_TRUE(&*MIBFMinNum == &*MIBFMinNum2);
157 
158     auto MIBFMinNum3 =
159         CSEB.buildFMinNum(s32, Copies[0], Copies[1], MachineInstr::FmNsz);
160     EXPECT_FALSE(&*MIBFMinNum == &*MIBFMinNum3);
161 
162     MIBFMinNum2->setFlag(MachineInstr::FmNsz);
163     MIBFMinNum2->clearFlag(MachineInstr::FmNsz);
164     EXPECT_TRUE(&*MIBFMinNum == &*MIBFMinNum2);
165   }
166 
167   {
168     auto MIBFMaxNum = CSEB.buildFMaxNum(s32, Copies[0], Copies[1]);
169     auto MIBFMaxNum2 = CSEB.buildFMaxNum(s32, Copies[0], Copies[1]);
170     EXPECT_TRUE(&*MIBFMaxNum == &*MIBFMaxNum2);
171 
172     auto MIBFMaxNum3 =
173         CSEB.buildFMaxNum(s32, Copies[0], Copies[1], MachineInstr::FmNsz);
174     EXPECT_FALSE(&*MIBFMaxNum == &*MIBFMaxNum3);
175 
176     MIBFMaxNum2->setFlag(MachineInstr::FmNsz);
177     MIBFMaxNum2->clearFlag(MachineInstr::FmNsz);
178     EXPECT_TRUE(&*MIBFMaxNum == &*MIBFMaxNum2);
179   }
180 
181   // Check G_FMINNUM_IEEE/F_MAXNUM_IEEE:
182   {
183     auto MIBFMinNumIEEE = CSEB.buildFMinNumIEEE(s32, Copies[0], Copies[1]);
184     auto MIBFMinNumIEEE2 = CSEB.buildFMinNumIEEE(s32, Copies[0], Copies[1]);
185     EXPECT_TRUE(&*MIBFMinNumIEEE == &*MIBFMinNumIEEE2);
186 
187     auto MIBFMinNumIEEE3 =
188         CSEB.buildFMinNumIEEE(s32, Copies[0], Copies[1], MachineInstr::FmNsz);
189     EXPECT_FALSE(&*MIBFMinNumIEEE == &*MIBFMinNumIEEE3);
190 
191     MIBFMinNumIEEE2->setFlag(MachineInstr::FmNsz);
192     MIBFMinNumIEEE2->clearFlag(MachineInstr::FmNsz);
193     EXPECT_TRUE(&*MIBFMinNumIEEE == &*MIBFMinNumIEEE2);
194   }
195 
196   {
197     auto MIBFMaxNumIEEE = CSEB.buildFMaxNumIEEE(s32, Copies[0], Copies[1]);
198     auto MIBFMaxNumIEEE2 = CSEB.buildFMaxNumIEEE(s32, Copies[0], Copies[1]);
199     EXPECT_TRUE(&*MIBFMaxNumIEEE == &*MIBFMaxNumIEEE2);
200 
201     auto MIBFMaxNumIEEE3 =
202         CSEB.buildFMaxNumIEEE(s32, Copies[0], Copies[1], MachineInstr::FmNsz);
203     EXPECT_FALSE(&*MIBFMaxNumIEEE == &*MIBFMaxNumIEEE3);
204 
205     MIBFMaxNumIEEE2->setFlag(MachineInstr::FmNsz);
206     MIBFMaxNumIEEE2->clearFlag(MachineInstr::FmNsz);
207     EXPECT_TRUE(&*MIBFMaxNumIEEE == &*MIBFMaxNumIEEE2);
208   }
209 
210   // Check G_BUILD_VECTOR
211   Register Reg1 = MRI->createGenericVirtualRegister(s32);
212   Register Reg2 = MRI->createGenericVirtualRegister(s32);
213   auto BuildVec1 =
214       CSEB.buildBuildVector(LLT::fixed_vector(4, 32), {Reg1, Reg2, Reg1, Reg2});
215   auto BuildVec2 =
216       CSEB.buildBuildVector(LLT::fixed_vector(4, 32), {Reg1, Reg2, Reg1, Reg2});
217   EXPECT_EQ(TargetOpcode::G_BUILD_VECTOR, BuildVec1->getOpcode());
218   EXPECT_EQ(TargetOpcode::G_BUILD_VECTOR, BuildVec2->getOpcode());
219   EXPECT_TRUE(&*BuildVec1 == &*BuildVec2);
220 
221   // Check G_BUILD_VECTOR_TRUNC
222   auto BuildVecTrunc1 = CSEB.buildBuildVectorTrunc(LLT::fixed_vector(4, 16),
223                                                    {Reg1, Reg2, Reg1, Reg2});
224   auto BuildVecTrunc2 = CSEB.buildBuildVectorTrunc(LLT::fixed_vector(4, 16),
225                                                    {Reg1, Reg2, Reg1, Reg2});
226   EXPECT_EQ(TargetOpcode::G_BUILD_VECTOR_TRUNC, BuildVecTrunc1->getOpcode());
227   EXPECT_EQ(TargetOpcode::G_BUILD_VECTOR_TRUNC, BuildVecTrunc2->getOpcode());
228   EXPECT_TRUE(&*BuildVecTrunc1 == &*BuildVecTrunc2);
229 
230   // Check G_IMPLICIT_DEF
231   auto Undef0 = CSEB.buildUndef(s32);
232   auto Undef1 = CSEB.buildUndef(s32);
233   EXPECT_EQ(&*Undef0, &*Undef1);
234 
235   // If the observer is installed to the MF, CSE can also
236   // track new instructions built without the CSEBuilder and
237   // the newly built instructions are available for CSEing next
238   // time a build call is made through the CSEMIRBuilder.
239   // Additionally, the CSE implementation lazily hashes instructions
240   // (every build call) to give chance for the instruction to be fully
241   // built (say using .addUse().addDef().. so on).
242   GISelObserverWrapper WrapperObserver(&CSEInfo);
243   RAIIMFObsDelInstaller Installer(*MF, WrapperObserver);
244   MachineIRBuilder RegularBuilder(*MF);
245   RegularBuilder.setInsertPt(*EntryMBB, EntryMBB->begin());
246   auto NonCSEFMul = RegularBuilder.buildInstr(TargetOpcode::G_AND)
247                         .addDef(MRI->createGenericVirtualRegister(s32))
248                         .addUse(Copies[0])
249                         .addUse(Copies[1]);
250   auto CSEFMul =
251       CSEB.buildInstr(TargetOpcode::G_AND, {s32}, {Copies[0], Copies[1]});
252   EXPECT_EQ(&*CSEFMul, &*NonCSEFMul);
253 
254   auto ExtractMIB = CSEB.buildInstr(TargetOpcode::G_EXTRACT, {s16},
255                                     {Copies[0], static_cast<uint64_t>(0)});
256   auto ExtractMIB1 = CSEB.buildInstr(TargetOpcode::G_EXTRACT, {s16},
257                                      {Copies[0], static_cast<uint64_t>(0)});
258   auto ExtractMIB2 = CSEB.buildInstr(TargetOpcode::G_EXTRACT, {s16},
259                                      {Copies[0], static_cast<uint64_t>(1)});
260   EXPECT_EQ(&*ExtractMIB, &*ExtractMIB1);
261   EXPECT_NE(&*ExtractMIB, &*ExtractMIB2);
262 
263 
264   auto SextInRegMIB = CSEB.buildSExtInReg(s16, Copies[0], 0);
265   auto SextInRegMIB1 = CSEB.buildSExtInReg(s16, Copies[0], 0);
266   auto SextInRegMIB2 = CSEB.buildSExtInReg(s16, Copies[0], 1);
267   EXPECT_EQ(&*SextInRegMIB, &*SextInRegMIB1);
268   EXPECT_NE(&*SextInRegMIB, &*SextInRegMIB2);
269 }
270 
271 TEST_F(AArch64GISelMITest, TestCSEConstantConfig) {
272   setUp();
273   if (!TM)
274     GTEST_SKIP();
275 
276   LLT s16{LLT::scalar(16)};
277   auto MIBInput = B.buildInstr(TargetOpcode::G_TRUNC, {s16}, {Copies[0]});
278   auto MIBAdd = B.buildInstr(TargetOpcode::G_ADD, {s16}, {MIBInput, MIBInput});
279   auto MIBZero = B.buildConstant(s16, 0);
280   GISelCSEInfo CSEInfo;
281   CSEInfo.setCSEConfig(std::make_unique<CSEConfigConstantOnly>());
282   CSEInfo.analyze(*MF);
283   B.setCSEInfo(&CSEInfo);
284   CSEMIRBuilder CSEB(B.getState());
285   CSEB.setInsertPt(*EntryMBB, EntryMBB->begin());
286   auto MIBAdd1 =
287       CSEB.buildInstr(TargetOpcode::G_ADD, {s16}, {MIBInput, MIBInput});
288   // We should CSE constants only. Adds should not be CSEd.
289   EXPECT_TRUE(MIBAdd1->getOpcode() != TargetOpcode::COPY);
290   EXPECT_TRUE(&*MIBAdd1 != &*MIBAdd);
291   // We should CSE constant.
292   auto MIBZeroTmp = CSEB.buildConstant(s16, 0);
293   EXPECT_TRUE(&*MIBZero == &*MIBZeroTmp);
294 
295   // Check G_IMPLICIT_DEF
296   auto Undef0 = CSEB.buildUndef(s16);
297   auto Undef1 = CSEB.buildUndef(s16);
298   EXPECT_EQ(&*Undef0, &*Undef1);
299 }
300 
301 TEST_F(AArch64GISelMITest, TestCSEImmediateNextCSE) {
302   setUp();
303   if (!TM)
304     GTEST_SKIP();
305 
306   LLT s32{LLT::scalar(32)};
307   // We want to check that when the CSE hit is on the next instruction, i.e. at
308   // the current insert pt, that the insertion point is moved ahead of the
309   // instruction.
310 
311   GISelCSEInfo CSEInfo;
312   CSEInfo.setCSEConfig(std::make_unique<CSEConfigConstantOnly>());
313   CSEInfo.analyze(*MF);
314   B.setCSEInfo(&CSEInfo);
315   CSEMIRBuilder CSEB(B.getState());
316   CSEB.buildConstant(s32, 0);
317   auto MIBCst2 = CSEB.buildConstant(s32, 2);
318 
319   // Move the insert point before the second constant.
320   CSEB.setInsertPt(CSEB.getMBB(), --CSEB.getInsertPt());
321   auto MIBCst3 = CSEB.buildConstant(s32, 2);
322   EXPECT_TRUE(&*MIBCst2 == &*MIBCst3);
323   EXPECT_TRUE(CSEB.getInsertPt() == CSEB.getMBB().end());
324 }
325 
326 TEST_F(AArch64GISelMITest, TestConstantFoldCTL) {
327   setUp();
328   if (!TM)
329     GTEST_SKIP();
330 
331   LLT s32 = LLT::scalar(32);
332 
333   GISelCSEInfo CSEInfo;
334   CSEInfo.setCSEConfig(std::make_unique<CSEConfigConstantOnly>());
335   CSEInfo.analyze(*MF);
336   B.setCSEInfo(&CSEInfo);
337   CSEMIRBuilder CSEB(B.getState());
338   auto Cst8 = CSEB.buildConstant(s32, 8);
339   auto *CtlzDef = &*CSEB.buildCTLZ(s32, Cst8);
340   EXPECT_TRUE(CtlzDef->getOpcode() == TargetOpcode::G_CONSTANT);
341   EXPECT_TRUE(CtlzDef->getOperand(1).getCImm()->getZExtValue() == 28);
342 
343   // Test vector.
344   auto Cst16 = CSEB.buildConstant(s32, 16);
345   auto Cst32 = CSEB.buildConstant(s32, 32);
346   auto Cst64 = CSEB.buildConstant(s32, 64);
347   LLT VecTy = LLT::fixed_vector(4, s32);
348   auto BV = CSEB.buildBuildVector(VecTy, {Cst8.getReg(0), Cst16.getReg(0),
349                                           Cst32.getReg(0), Cst64.getReg(0)});
350   CSEB.buildCTLZ(VecTy, BV);
351 
352   auto CheckStr = R"(
353   ; CHECK: [[CST8:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
354   ; CHECK: [[CST28:%[0-9]+]]:_(s32) = G_CONSTANT i32 28
355   ; CHECK: [[CST16:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
356   ; CHECK: [[CST32:%[0-9]+]]:_(s32) = G_CONSTANT i32 32
357   ; CHECK: [[CST64:%[0-9]+]]:_(s32) = G_CONSTANT i32 64
358   ; CHECK: [[BV1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[CST8]]:_(s32), [[CST16]]:_(s32), [[CST32]]:_(s32), [[CST64]]:_(s32)
359   ; CHECK: [[CST27:%[0-9]+]]:_(s32) = G_CONSTANT i32 27
360   ; CHECK: [[CST26:%[0-9]+]]:_(s32) = G_CONSTANT i32 26
361   ; CHECK: [[CST25:%[0-9]+]]:_(s32) = G_CONSTANT i32 25
362   ; CHECK: [[BV2:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[CST28]]:_(s32), [[CST27]]:_(s32), [[CST26]]:_(s32), [[CST25]]:_(s32)
363   )";
364 
365   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
366 }
367 
368 TEST_F(AArch64GISelMITest, TestConstantFoldCTT) {
369   setUp();
370   if (!TM)
371     GTEST_SKIP();
372 
373   LLT s32 = LLT::scalar(32);
374 
375   GISelCSEInfo CSEInfo;
376   CSEInfo.setCSEConfig(std::make_unique<CSEConfigConstantOnly>());
377   CSEInfo.analyze(*MF);
378   B.setCSEInfo(&CSEInfo);
379   CSEMIRBuilder CSEB(B.getState());
380   auto Cst8 = CSEB.buildConstant(s32, 8);
381   auto *CttzDef = &*CSEB.buildCTTZ(s32, Cst8);
382   EXPECT_TRUE(CttzDef->getOpcode() == TargetOpcode::G_CONSTANT);
383   EXPECT_TRUE(CttzDef->getOperand(1).getCImm()->getZExtValue() == 3);
384 
385   // Test vector.
386   auto Cst16 = CSEB.buildConstant(s32, 16);
387   auto Cst32 = CSEB.buildConstant(s32, 32);
388   auto Cst64 = CSEB.buildConstant(s32, 64);
389   LLT VecTy = LLT::fixed_vector(4, s32);
390   auto BV = CSEB.buildBuildVector(VecTy, {Cst8.getReg(0), Cst16.getReg(0),
391                                           Cst32.getReg(0), Cst64.getReg(0)});
392   CSEB.buildCTTZ(VecTy, BV);
393 
394   auto CheckStr = R"(
395   ; CHECK: [[CST8:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
396   ; CHECK: [[CST3:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
397   ; CHECK: [[CST16:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
398   ; CHECK: [[CST32:%[0-9]+]]:_(s32) = G_CONSTANT i32 32
399   ; CHECK: [[CST64:%[0-9]+]]:_(s32) = G_CONSTANT i32 64
400   ; CHECK: [[BV1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[CST8]]:_(s32), [[CST16]]:_(s32), [[CST32]]:_(s32), [[CST64]]:_(s32)
401   ; CHECK: [[CST27:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
402   ; CHECK: [[CST26:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
403   ; CHECK: [[CST25:%[0-9]+]]:_(s32) = G_CONSTANT i32 6
404   ; CHECK: [[BV2:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[CST3]]:_(s32), [[CST27]]:_(s32), [[CST26]]:_(s32), [[CST25]]:_(s32)
405   )";
406 
407   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
408 }
409 
410 TEST_F(AArch64GISelMITest, TestConstantFoldICMP) {
411   setUp();
412   if (!TM)
413     GTEST_SKIP();
414 
415   LLT s32 = LLT::scalar(32);
416   LLT s1 = LLT::scalar(1);
417 
418   GISelCSEInfo CSEInfo;
419   CSEInfo.setCSEConfig(std::make_unique<CSEConfigConstantOnly>());
420   CSEInfo.analyze(*MF);
421   B.setCSEInfo(&CSEInfo);
422   CSEMIRBuilder CSEB(B.getState());
423 
424   auto One = CSEB.buildConstant(s32, 1);
425   auto Two = CSEB.buildConstant(s32, 2);
426   auto MinusOne = CSEB.buildConstant(s32, -1);
427   auto MinusTwo = CSEB.buildConstant(s32, -2);
428 
429   // ICMP_EQ
430   {
431     auto I = CSEB.buildICmp(CmpInst::Predicate::ICMP_EQ, s1, One, One);
432     EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT);
433     EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue());
434   }
435 
436   // ICMP_NE
437   {
438     auto I = CSEB.buildICmp(CmpInst::Predicate::ICMP_NE, s1, One, Two);
439     EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT);
440     EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue());
441   }
442 
443   // ICMP_UGT
444   {
445     auto I = CSEB.buildICmp(CmpInst::Predicate::ICMP_UGT, s1, Two, One);
446     EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT);
447     EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue());
448   }
449 
450   // ICMP_UGE
451   {
452     auto I = CSEB.buildICmp(CmpInst::Predicate::ICMP_UGE, s1, One, One);
453     EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT);
454     EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue());
455   }
456 
457   // ICMP_ULT
458   {
459     auto I = CSEB.buildICmp(CmpInst::Predicate::ICMP_ULT, s1, One, Two);
460     EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT);
461     EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue());
462   }
463 
464   // ICMP_ULE
465   {
466     auto I = CSEB.buildICmp(CmpInst::Predicate::ICMP_ULE, s1, Two, Two);
467     EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT);
468     EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue());
469   }
470 
471   // ICMP_SGT
472   {
473     auto I =
474         CSEB.buildICmp(CmpInst::Predicate::ICMP_SGT, s1, MinusOne, MinusTwo);
475     EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT);
476     EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue());
477   }
478 
479   // ICMP_SGE
480   {
481     auto I =
482         CSEB.buildICmp(CmpInst::Predicate::ICMP_SGE, s1, MinusOne, MinusOne);
483     EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT);
484     EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue());
485   }
486 
487   // ICMP_SLT
488   {
489     auto I =
490         CSEB.buildICmp(CmpInst::Predicate::ICMP_SLT, s1, MinusTwo, MinusOne);
491     EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT);
492     EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue());
493   }
494 
495   // ICMP_SLE
496   {
497     auto I =
498         CSEB.buildICmp(CmpInst::Predicate::ICMP_SLE, s1, MinusTwo, MinusOne);
499     EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT);
500     EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue());
501   }
502 
503   LLT VecTy = LLT::fixed_vector(2, s32);
504   LLT DstTy = LLT::fixed_vector(2, s1);
505   auto Three = CSEB.buildConstant(s32, 3);
506   auto MinusThree = CSEB.buildConstant(s32, -3);
507   auto OneOne = CSEB.buildBuildVector(VecTy, {One.getReg(0), One.getReg(0)});
508   auto OneTwo = CSEB.buildBuildVector(VecTy, {One.getReg(0), Two.getReg(0)});
509   auto TwoThree =
510       CSEB.buildBuildVector(VecTy, {Two.getReg(0), Three.getReg(0)});
511   auto MinusOneOne =
512       CSEB.buildBuildVector(VecTy, {MinusOne.getReg(0), MinusOne.getReg(0)});
513   auto MinusOneTwo =
514       CSEB.buildBuildVector(VecTy, {MinusOne.getReg(0), MinusTwo.getReg(0)});
515   auto MinusTwoThree =
516       CSEB.buildBuildVector(VecTy, {MinusTwo.getReg(0), MinusThree.getReg(0)});
517 
518   // ICMP_EQ
519   CSEB.buildICmp(CmpInst::Predicate::ICMP_EQ, DstTy, OneOne, OneOne);
520 
521   // ICMP_NE
522   CSEB.buildICmp(CmpInst::Predicate::ICMP_NE, DstTy, OneOne, OneTwo);
523 
524   // ICMP_UGT
525   CSEB.buildICmp(CmpInst::Predicate::ICMP_UGT, DstTy, TwoThree, OneTwo);
526 
527   // ICMP_UGE
528   CSEB.buildICmp(CmpInst::Predicate::ICMP_UGE, DstTy, OneTwo, OneOne);
529 
530   // ICMP_ULT
531   CSEB.buildICmp(CmpInst::Predicate::ICMP_ULT, DstTy, OneOne, OneTwo);
532 
533   // ICMP_ULE
534   CSEB.buildICmp(CmpInst::Predicate::ICMP_ULE, DstTy, OneTwo, OneOne);
535 
536   // ICMP_SGT
537   CSEB.buildICmp(CmpInst::Predicate::ICMP_SGT, DstTy, MinusOneTwo,
538                  MinusTwoThree);
539 
540   // ICMP_SGE
541   CSEB.buildICmp(CmpInst::Predicate::ICMP_SGE, DstTy, MinusOneTwo, MinusOneOne);
542 
543   // ICMP_SLT
544   CSEB.buildICmp(CmpInst::Predicate::ICMP_SLT, DstTy, MinusTwoThree,
545                  MinusOneTwo);
546 
547   // ICMP_SLE
548   CSEB.buildICmp(CmpInst::Predicate::ICMP_SLE, DstTy, MinusOneTwo, MinusOneOne);
549 
550   auto CheckStr = R"(
551   ; CHECK: [[One:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
552   ; CHECK: [[Two:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
553   ; CHECK: [[MinusOne:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
554   ; CHECK: [[MinusTwo:%[0-9]+]]:_(s32) = G_CONSTANT i32 -2
555   ; CHECK: [[True:%[0-9]+]]:_(s1) = G_CONSTANT i1 true
556   ; CHECK: [[Three:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
557   ; CHECK: [[MinusThree:%[0-9]+]]:_(s32) = G_CONSTANT i32 -3
558   ; CHECK: {{%[0-9]+}}:_(<2 x s32>) = G_BUILD_VECTOR [[One]]:_(s32), [[One]]:_(s32)
559   ; CHECK: {{%[0-9]+}}:_(<2 x s32>) = G_BUILD_VECTOR [[One]]:_(s32), [[Two]]:_(s32)
560   ; CHECK: {{%[0-9]+}}:_(<2 x s32>) = G_BUILD_VECTOR [[Two]]:_(s32), [[Three]]:_(s32)
561   ; CHECK: {{%[0-9]+}}:_(<2 x s32>) = G_BUILD_VECTOR [[MinusOne]]:_(s32), [[MinusOne]]:_(s32)
562   ; CHECK: {{%[0-9]+}}:_(<2 x s32>) = G_BUILD_VECTOR [[MinusOne]]:_(s32), [[MinusTwo]]:_(s32)
563   ; CHECK: {{%[0-9]+}}:_(<2 x s32>) = G_BUILD_VECTOR [[MinusTwo]]:_(s32), [[MinusThree]]:_(s32)
564   ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[True]]:_(s1), [[True]]:_(s1)
565   ; CHECK: [[False:%[0-9]+]]:_(s1) = G_CONSTANT i1 false
566   ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[False]]:_(s1), [[True]]:_(s1)
567   ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[True]]:_(s1), [[True]]:_(s1)
568   ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[True]]:_(s1), [[True]]:_(s1)
569   ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[False]]:_(s1), [[True]]:_(s1)
570   ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[True]]:_(s1), [[False]]:_(s1)
571   ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[True]]:_(s1), [[True]]:_(s1)
572   ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[True]]:_(s1), [[False]]:_(s1)
573   ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[True]]:_(s1), [[True]]:_(s1)
574   ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[True]]:_(s1), [[True]]:_(s1)
575   )";
576 
577   EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
578 }
579 
580 } // namespace
581