1 //===- PatternMatchTest.cpp -----------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "LegalizerHelperTest.h" 11 12 namespace { 13 14 // Test CTTZ expansion when CTTZ_ZERO_UNDEF is legal or custom, 15 // in which case it becomes CTTZ_ZERO_UNDEF with select. 16 TEST_F(LegalizerHelperTest, LowerBitCountingCTTZ0) { 17 if (!TM) 18 return; 19 20 // Declare your legalization info 21 DefineLegalizerInfo( 22 A, { getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({s64}); }); 23 // Build Instr 24 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, LLT::scalar(64), Copies[0]); 25 AInfo Info(MF->getSubtarget()); 26 LegalizerHelper Helper(*MF, Info); 27 // Perform Legalization 28 ASSERT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) == 29 LegalizerHelper::LegalizeResult::Legalized); 30 31 auto CheckStr = R"( 32 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTTZ_ZERO_UNDEF %0 33 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 34 CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64 35 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]] 36 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]] 37 )"; 38 39 // Check 40 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 41 } 42 43 // CTTZ expansion in terms of CTLZ 44 TEST_F(LegalizerHelperTest, LowerBitCountingCTTZ1) { 45 if (!TM) 46 return; 47 48 // Declare your legalization info 49 DefineLegalizerInfo(A, 50 { getActionDefinitionsBuilder(G_CTLZ).legalFor({s64}); }); 51 // Build Instr 52 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, LLT::scalar(64), Copies[0]); 53 AInfo Info(MF->getSubtarget()); 54 LegalizerHelper Helper(*MF, Info); 55 // Perform Legalization 56 ASSERT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) == 57 LegalizerHelper::LegalizeResult::Legalized); 58 59 auto CheckStr = R"( 60 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1 61 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]] 62 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]] 63 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_ 64 CHECK: [[CST64:%[0-9]+]]:_(s64) = G_CONSTANT i64 64 65 CHECK: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[AND1]]:_ 66 CHECK: G_SUB [[CST64]]:_, [[CTLZ]]:_ 67 )"; 68 69 // Check 70 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 71 } 72 73 // CTTZ expansion in terms of CTPOP 74 TEST_F(LegalizerHelperTest, LowerBitCountingCTTZ2) { 75 if (!TM) 76 return; 77 78 // Declare your legalization info 79 DefineLegalizerInfo( 80 A, { getActionDefinitionsBuilder(G_CTPOP).legalFor({s64}); }); 81 // Build 82 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, LLT::scalar(64), Copies[0]); 83 AInfo Info(MF->getSubtarget()); 84 LegalizerHelper Helper(*MF, Info); 85 ASSERT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) == 86 LegalizerHelper::LegalizeResult::Legalized); 87 88 auto CheckStr = R"( 89 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1 90 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]] 91 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]] 92 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_ 93 CHECK: [[POP:%[0-9]+]]:_(s64) = G_CTPOP [[AND1]] 94 )"; 95 96 // Check 97 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 98 } 99 100 // CTTZ_ZERO_UNDEF expansion in terms of CTTZ 101 TEST_F(LegalizerHelperTest, LowerBitCountingCTTZ3) { 102 if (!TM) 103 return; 104 105 // Declare your legalization info 106 DefineLegalizerInfo(A, 107 { getActionDefinitionsBuilder(G_CTTZ).legalFor({s64}); }); 108 // Build 109 auto MIBCTTZ = 110 B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, LLT::scalar(64), Copies[0]); 111 AInfo Info(MF->getSubtarget()); 112 LegalizerHelper Helper(*MF, Info); 113 ASSERT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) == 114 LegalizerHelper::LegalizeResult::Legalized); 115 116 auto CheckStr = R"( 117 CHECK: CTTZ 118 )"; 119 120 // Check 121 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 122 } 123 124 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF 125 TEST_F(LegalizerHelperTest, LowerBitCountingCTLZ0) { 126 if (!TM) 127 return; 128 129 // Declare your legalization info 130 DefineLegalizerInfo( 131 A, { getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({s64}); }); 132 // Build 133 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, LLT::scalar(64), Copies[0]); 134 AInfo Info(MF->getSubtarget()); 135 LegalizerHelper Helper(*MF, Info); 136 ASSERT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) == 137 LegalizerHelper::LegalizeResult::Legalized); 138 139 auto CheckStr = R"( 140 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0 141 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 142 CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64 143 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]] 144 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]] 145 )"; 146 147 // Check 148 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 149 } 150 151 // CTLZ expansion 152 TEST_F(LegalizerHelperTest, LowerBitCountingCTLZ1) { 153 if (!TM) 154 return; 155 156 // Declare your legalization info 157 DefineLegalizerInfo(A, 158 { getActionDefinitionsBuilder(G_CTPOP).legalFor({s8}); }); 159 // Build 160 // Trunc it to s8. 161 LLT s8{LLT::scalar(8)}; 162 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 163 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, s8, MIBTrunc); 164 AInfo Info(MF->getSubtarget()); 165 LegalizerHelper Helper(*MF, Info); 166 ASSERT_TRUE(Helper.lower(*MIBCTLZ, 0, s8) == 167 LegalizerHelper::LegalizeResult::Legalized); 168 169 auto CheckStr = R"( 170 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 171 CHECK: [[Cst1:%[0-9]+]]:_(s8) = G_CONSTANT i8 1 172 CHECK: [[Sh1:%[0-9]+]]:_(s8) = G_LSHR [[Trunc]]:_, [[Cst1]]:_ 173 CHECK: [[Or1:%[0-9]+]]:_(s8) = G_OR [[Trunc]]:_, [[Sh1]]:_ 174 CHECK: [[Cst2:%[0-9]+]]:_(s8) = G_CONSTANT i8 2 175 CHECK: [[Sh2:%[0-9]+]]:_(s8) = G_LSHR [[Or1]]:_, [[Cst2]]:_ 176 CHECK: [[Or2:%[0-9]+]]:_(s8) = G_OR [[Or1]]:_, [[Sh2]]:_ 177 CHECK: [[Cst4:%[0-9]+]]:_(s8) = G_CONSTANT i8 4 178 CHECK: [[Sh4:%[0-9]+]]:_(s8) = G_LSHR [[Or2]]:_, [[Cst4]]:_ 179 CHECK: [[Or4:%[0-9]+]]:_(s8) = G_OR [[Or2]]:_, [[Sh4]]:_ 180 CHECK: [[CTPOP:%[0-9]+]]:_(s8) = G_CTPOP [[Or4]]:_ 181 CHECK: [[Len:%[0-9]+]]:_(s8) = G_CONSTANT i8 8 182 CHECK: [[Sub:%[0-9]+]]:_(s8) = G_SUB [[Len]]:_, [[CTPOP]]:_ 183 )"; 184 185 // Check 186 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 187 } 188 189 // CTLZ widening. 190 TEST_F(LegalizerHelperTest, WidenBitCountingCTLZ) { 191 if (!TM) 192 return; 193 194 // Declare your legalization info 195 DefineLegalizerInfo(A, 196 { getActionDefinitionsBuilder(G_CTLZ).legalFor({s16}); }); 197 // Build 198 // Trunc it to s8. 199 LLT s8{LLT::scalar(8)}; 200 LLT s16{LLT::scalar(16)}; 201 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 202 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, s8, MIBTrunc); 203 AInfo Info(MF->getSubtarget()); 204 LegalizerHelper Helper(*MF, Info); 205 ASSERT_TRUE(Helper.widenScalar(*MIBCTLZ, 0, s16) == 206 LegalizerHelper::LegalizeResult::Legalized); 207 208 auto CheckStr = R"( 209 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 210 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 211 CHECK: [[Ctlz:%[0-9]+]]:_(s16) = G_CTLZ [[Zext]] 212 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 213 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[Ctlz]]:_, [[Cst8]]:_ 214 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]] 215 )"; 216 217 // Check 218 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 219 } 220 221 // CTLZ_ZERO_UNDEF widening. 222 TEST_F(LegalizerHelperTest, WidenBitCountingCTLZZeroUndef) { 223 if (!TM) 224 return; 225 226 // Declare your legalization info 227 DefineLegalizerInfo( 228 A, { getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({s16}); }); 229 // Build 230 // Trunc it to s8. 231 LLT s8{LLT::scalar(8)}; 232 LLT s16{LLT::scalar(16)}; 233 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 234 auto MIBCTLZ_ZU = B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, s8, MIBTrunc); 235 AInfo Info(MF->getSubtarget()); 236 LegalizerHelper Helper(*MF, Info); 237 ASSERT_TRUE(Helper.widenScalar(*MIBCTLZ_ZU, 0, s16) == 238 LegalizerHelper::LegalizeResult::Legalized); 239 240 auto CheckStr = R"( 241 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 242 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 243 CHECK: [[CtlzZu:%[0-9]+]]:_(s16) = G_CTLZ_ZERO_UNDEF [[Zext]] 244 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 245 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[CtlzZu]]:_, [[Cst8]]:_ 246 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]] 247 )"; 248 249 // Check 250 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 251 } 252 253 // CTPOP widening. 254 TEST_F(LegalizerHelperTest, WidenBitCountingCTPOP) { 255 if (!TM) 256 return; 257 258 // Declare your legalization info 259 DefineLegalizerInfo( 260 A, { getActionDefinitionsBuilder(G_CTPOP).legalFor({s16}); }); 261 // Build 262 // Trunc it to s8. 263 LLT s8{LLT::scalar(8)}; 264 LLT s16{LLT::scalar(16)}; 265 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 266 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, s8, MIBTrunc); 267 AInfo Info(MF->getSubtarget()); 268 LegalizerHelper Helper(*MF, Info); 269 ASSERT_TRUE(Helper.widenScalar(*MIBCTPOP, 0, s16) == 270 LegalizerHelper::LegalizeResult::Legalized); 271 272 auto CheckStr = R"( 273 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 274 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 275 CHECK: [[Ctpop:%[0-9]+]]:_(s16) = G_CTPOP [[Zext]] 276 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Ctpop]] 277 )"; 278 279 // Check 280 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 281 } 282 283 // CTTZ_ZERO_UNDEF widening. 284 TEST_F(LegalizerHelperTest, WidenBitCountingCTTZ_ZERO_UNDEF) { 285 if (!TM) 286 return; 287 288 // Declare your legalization info 289 DefineLegalizerInfo( 290 A, { getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({s16}); }); 291 // Build 292 // Trunc it to s8. 293 LLT s8{LLT::scalar(8)}; 294 LLT s16{LLT::scalar(16)}; 295 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 296 auto MIBCTTZ_ZERO_UNDEF = 297 B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, s8, MIBTrunc); 298 AInfo Info(MF->getSubtarget()); 299 LegalizerHelper Helper(*MF, Info); 300 ASSERT_TRUE(Helper.widenScalar(*MIBCTTZ_ZERO_UNDEF, 0, s16) == 301 LegalizerHelper::LegalizeResult::Legalized); 302 303 auto CheckStr = R"( 304 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 305 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 306 CHECK: [[CttzZu:%[0-9]+]]:_(s16) = G_CTTZ_ZERO_UNDEF [[Zext]] 307 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[CttzZu]] 308 )"; 309 310 // Check 311 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 312 } 313 314 // CTTZ widening. 315 TEST_F(LegalizerHelperTest, WidenBitCountingCTTZ) { 316 if (!TM) 317 return; 318 319 // Declare your legalization info 320 DefineLegalizerInfo(A, 321 { getActionDefinitionsBuilder(G_CTTZ).legalFor({s16}); }); 322 // Build 323 // Trunc it to s8. 324 LLT s8{LLT::scalar(8)}; 325 LLT s16{LLT::scalar(16)}; 326 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 327 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, s8, MIBTrunc); 328 AInfo Info(MF->getSubtarget()); 329 LegalizerHelper Helper(*MF, Info); 330 ASSERT_TRUE(Helper.widenScalar(*MIBCTTZ, 0, s16) == 331 LegalizerHelper::LegalizeResult::Legalized); 332 333 auto CheckStr = R"( 334 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 335 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 336 CHECK: [[Cst:%[0-9]+]]:_(s16) = G_CONSTANT i16 256 337 CHECK: [[Or:%[0-9]+]]:_(s16) = G_OR [[Zext]]:_, [[Cst]] 338 CHECK: [[Cttz:%[0-9]+]]:_(s16) = G_CTTZ [[Or]] 339 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Cttz]] 340 )"; 341 342 // Check 343 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 344 } 345 // UADDO widening. 346 TEST_F(LegalizerHelperTest, WidenUADDO) { 347 if (!TM) 348 return; 349 350 // Declare your legalization info 351 DefineLegalizerInfo(A, 352 { getActionDefinitionsBuilder(G_ADD).legalFor({s16}); }); 353 // Build 354 // Trunc it to s8. 355 LLT s8{LLT::scalar(8)}; 356 LLT s16{LLT::scalar(16)}; 357 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 358 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); 359 auto MIBUAddO = B.buildInstr(TargetOpcode::G_UADDO, s8) 360 .addDef(CarryReg) 361 .addUse(MIBTrunc->getOperand(0).getReg()) 362 .addUse(MIBTrunc->getOperand(0).getReg()); 363 AInfo Info(MF->getSubtarget()); 364 LegalizerHelper Helper(*MF, Info); 365 ASSERT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) == 366 LegalizerHelper::LegalizeResult::Legalized); 367 368 auto CheckStr = R"( 369 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 370 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 371 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 372 CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_ 373 CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255 374 CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[ADD]]:_, [[CST]]:_ 375 CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[AND]]:_ 376 CHECK: G_TRUNC [[ADD]] 377 )"; 378 379 // Check 380 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 381 } 382 383 // USUBO widening. 384 TEST_F(LegalizerHelperTest, WidenUSUBO) { 385 if (!TM) 386 return; 387 388 // Declare your legalization info 389 DefineLegalizerInfo(A, 390 { getActionDefinitionsBuilder(G_SUB).legalFor({s16}); }); 391 // Build 392 // Trunc it to s8. 393 LLT s8{LLT::scalar(8)}; 394 LLT s16{LLT::scalar(16)}; 395 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 396 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); 397 auto MIBUSUBO = B.buildInstr(TargetOpcode::G_USUBO, s8) 398 .addDef(CarryReg) 399 .addUse(MIBTrunc->getOperand(0).getReg()) 400 .addUse(MIBTrunc->getOperand(0).getReg()); 401 AInfo Info(MF->getSubtarget()); 402 LegalizerHelper Helper(*MF, Info); 403 ASSERT_TRUE(Helper.widenScalar(*MIBUSUBO, 0, s16) == 404 LegalizerHelper::LegalizeResult::Legalized); 405 406 auto CheckStr = R"( 407 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 408 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 409 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 410 CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_ 411 CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255 412 CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[SUB]]:_, [[CST]]:_ 413 CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[AND]]:_ 414 CHECK: G_TRUNC [[SUB]] 415 )"; 416 417 // Check 418 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 419 } 420 } // namespace 421