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