1 //===- LegalizerHelperTest.cpp 2 //-----------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "GISelMITest.h" 11 12 namespace { 13 14 class DummyGISelObserver : public GISelChangeObserver { 15 public: 16 void changingInstr(MachineInstr &MI) override {} 17 void changedInstr(MachineInstr &MI) override {} 18 void createdInstr(MachineInstr &MI) override {} 19 void erasingInstr(MachineInstr &MI) override {} 20 }; 21 22 // Test CTTZ expansion when CTTZ_ZERO_UNDEF is legal or custom, 23 // in which case it becomes CTTZ_ZERO_UNDEF with select. 24 TEST_F(GISelMITest, LowerBitCountingCTTZ0) { 25 if (!TM) 26 return; 27 28 // Declare your legalization info 29 DefineLegalizerInfo(A, { 30 getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s64, s64}}); 31 }); 32 // Build Instr 33 auto MIBCTTZ = 34 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]}); 35 AInfo Info(MF->getSubtarget()); 36 DummyGISelObserver Observer; 37 LegalizerHelper Helper(*MF, Info, Observer, B); 38 // Perform Legalization 39 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) == 40 LegalizerHelper::LegalizeResult::Legalized); 41 42 auto CheckStr = R"( 43 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTTZ_ZERO_UNDEF %0 44 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 45 CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64 46 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]] 47 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]] 48 )"; 49 50 // Check 51 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 52 } 53 54 // CTTZ expansion in terms of CTLZ 55 TEST_F(GISelMITest, LowerBitCountingCTTZ1) { 56 if (!TM) 57 return; 58 59 // Declare your legalization info 60 DefineLegalizerInfo(A, { 61 getActionDefinitionsBuilder(G_CTLZ).legalFor({{s64, s64}}); 62 }); 63 // Build Instr 64 auto MIBCTTZ = 65 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]}); 66 AInfo Info(MF->getSubtarget()); 67 DummyGISelObserver Observer; 68 LegalizerHelper Helper(*MF, Info, Observer, B); 69 // Perform Legalization 70 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) == 71 LegalizerHelper::LegalizeResult::Legalized); 72 73 auto CheckStr = R"( 74 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1 75 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]] 76 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]] 77 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_ 78 CHECK: [[CST64:%[0-9]+]]:_(s64) = G_CONSTANT i64 64 79 CHECK: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[AND1]]:_ 80 CHECK: G_SUB [[CST64]]:_, [[CTLZ]]:_ 81 )"; 82 83 // Check 84 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 85 } 86 87 // CTTZ expansion in terms of CTPOP 88 TEST_F(GISelMITest, LowerBitCountingCTTZ2) { 89 if (!TM) 90 return; 91 92 // Declare your legalization info 93 DefineLegalizerInfo(A, { 94 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s64, s64}}); 95 }); 96 // Build 97 auto MIBCTTZ = 98 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]}); 99 AInfo Info(MF->getSubtarget()); 100 DummyGISelObserver Observer; 101 LegalizerHelper Helper(*MF, Info, Observer, B); 102 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) == 103 LegalizerHelper::LegalizeResult::Legalized); 104 105 auto CheckStr = R"( 106 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1 107 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]] 108 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]] 109 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_ 110 CHECK: [[POP:%[0-9]+]]:_(s64) = G_CTPOP [[AND1]] 111 )"; 112 113 // Check 114 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 115 } 116 117 // CTPOP widening. 118 TEST_F(GISelMITest, WidenBitCountingCTPOP1) { 119 if (!TM) 120 return; 121 122 // Declare your legalization info 123 DefineLegalizerInfo(A, { 124 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}}); 125 }); 126 127 // Build 128 // Trunc it to s8. 129 LLT s8{LLT::scalar(8)}; 130 LLT s16{LLT::scalar(16)}; 131 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 132 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s16}, {MIBTrunc}); 133 AInfo Info(MF->getSubtarget()); 134 DummyGISelObserver Observer; 135 LegalizerHelper Helper(*MF, Info, Observer, B); 136 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 137 Helper.widenScalar(*MIBCTPOP, 1, s16)); 138 139 auto CheckStr = R"( 140 CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64) 141 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8) 142 CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]] 143 CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY [[CTPOP]]:_(s16) 144 )"; 145 146 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 147 } 148 149 // Test a strange case where the result is wider than the source 150 TEST_F(GISelMITest, WidenBitCountingCTPOP2) { 151 if (!TM) 152 return; 153 154 // Declare your legalization info 155 DefineLegalizerInfo(A, { 156 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s32, s16}}); 157 }); 158 159 // Build 160 // Trunc it to s8. 161 LLT s8{LLT::scalar(8)}; 162 LLT s16{LLT::scalar(16)}; 163 LLT s32{LLT::scalar(32)}; 164 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 165 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s32}, {MIBTrunc}); 166 AInfo Info(MF->getSubtarget()); 167 DummyGISelObserver Observer; 168 LegalizerHelper Helper(*MF, Info, Observer, B); 169 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 170 Helper.widenScalar(*MIBCTPOP, 1, s16)); 171 172 auto CheckStr = R"( 173 CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64) 174 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8) 175 CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]] 176 CHECK: [[COPY:%[0-9]+]]:_(s32) = G_ZEXT [[CTPOP]]:_(s16) 177 )"; 178 179 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 180 } 181 182 // CTTZ_ZERO_UNDEF expansion in terms of CTTZ 183 TEST_F(GISelMITest, LowerBitCountingCTTZ3) { 184 if (!TM) 185 return; 186 187 // Declare your legalization info 188 DefineLegalizerInfo(A, { 189 getActionDefinitionsBuilder(G_CTTZ).legalFor({{s64, s64}}); 190 }); 191 // Build 192 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, 193 {LLT::scalar(64)}, {Copies[0]}); 194 AInfo Info(MF->getSubtarget()); 195 DummyGISelObserver Observer; 196 LegalizerHelper Helper(*MF, Info, Observer, B); 197 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) == 198 LegalizerHelper::LegalizeResult::Legalized); 199 200 auto CheckStr = R"( 201 CHECK: CTTZ 202 )"; 203 204 // Check 205 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 206 } 207 208 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF 209 TEST_F(GISelMITest, LowerBitCountingCTLZ0) { 210 if (!TM) 211 return; 212 213 // Declare your legalization info 214 DefineLegalizerInfo(A, { 215 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s64, s64}}); 216 }); 217 // Build 218 auto MIBCTLZ = 219 B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(64)}, {Copies[0]}); 220 AInfo Info(MF->getSubtarget()); 221 DummyGISelObserver Observer; 222 LegalizerHelper Helper(*MF, Info, Observer, B); 223 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) == 224 LegalizerHelper::LegalizeResult::Legalized); 225 226 auto CheckStr = R"( 227 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0 228 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 229 CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64 230 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]] 231 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]] 232 )"; 233 234 // Check 235 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 236 } 237 238 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF if the latter is a libcall 239 TEST_F(GISelMITest, LowerBitCountingCTLZLibcall) { 240 if (!TM) 241 return; 242 243 // Declare your legalization info 244 DefineLegalizerInfo(A, { 245 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).libcallFor({{s64, s64}}); 246 }); 247 // Build 248 auto MIBCTLZ = 249 B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(64)}, {Copies[0]}); 250 AInfo Info(MF->getSubtarget()); 251 DummyGISelObserver Observer; 252 LegalizerHelper Helper(*MF, Info, Observer, B); 253 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) == 254 LegalizerHelper::LegalizeResult::Legalized); 255 256 auto CheckStr = R"( 257 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0 258 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 259 CHECK: [[THIRTY2:%[0-9]+]]:_(s64) = G_CONSTANT i64 64 260 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]] 261 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[THIRTY2]]:_, [[CZU]] 262 )"; 263 264 // Check 265 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 266 } 267 268 // CTLZ expansion 269 TEST_F(GISelMITest, LowerBitCountingCTLZ1) { 270 if (!TM) 271 return; 272 273 // Declare your legalization info 274 DefineLegalizerInfo(A, { 275 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s8, s8}}); 276 }); 277 // Build 278 // Trunc it to s8. 279 LLT s8{LLT::scalar(8)}; 280 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 281 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc}); 282 AInfo Info(MF->getSubtarget()); 283 DummyGISelObserver Observer; 284 LegalizerHelper Helper(*MF, Info, Observer, B); 285 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, s8) == 286 LegalizerHelper::LegalizeResult::Legalized); 287 288 auto CheckStr = R"( 289 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 290 CHECK: [[Cst1:%[0-9]+]]:_(s8) = G_CONSTANT i8 1 291 CHECK: [[Sh1:%[0-9]+]]:_(s8) = G_LSHR [[Trunc]]:_, [[Cst1]]:_ 292 CHECK: [[Or1:%[0-9]+]]:_(s8) = G_OR [[Trunc]]:_, [[Sh1]]:_ 293 CHECK: [[Cst2:%[0-9]+]]:_(s8) = G_CONSTANT i8 2 294 CHECK: [[Sh2:%[0-9]+]]:_(s8) = G_LSHR [[Or1]]:_, [[Cst2]]:_ 295 CHECK: [[Or2:%[0-9]+]]:_(s8) = G_OR [[Or1]]:_, [[Sh2]]:_ 296 CHECK: [[Cst4:%[0-9]+]]:_(s8) = G_CONSTANT i8 4 297 CHECK: [[Sh4:%[0-9]+]]:_(s8) = G_LSHR [[Or2]]:_, [[Cst4]]:_ 298 CHECK: [[Or4:%[0-9]+]]:_(s8) = G_OR [[Or2]]:_, [[Sh4]]:_ 299 CHECK: [[CTPOP:%[0-9]+]]:_(s8) = G_CTPOP [[Or4]]:_ 300 CHECK: [[Len:%[0-9]+]]:_(s8) = G_CONSTANT i8 8 301 CHECK: [[Sub:%[0-9]+]]:_(s8) = G_SUB [[Len]]:_, [[CTPOP]]:_ 302 )"; 303 304 // Check 305 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 306 } 307 308 // CTLZ widening. 309 TEST_F(GISelMITest, WidenBitCountingCTLZ) { 310 if (!TM) 311 return; 312 313 // Declare your legalization info 314 DefineLegalizerInfo(A, { 315 getActionDefinitionsBuilder(G_CTLZ).legalFor({{s16, s16}}); 316 }); 317 // Build 318 // Trunc it to s8. 319 LLT s8{LLT::scalar(8)}; 320 LLT s16{LLT::scalar(16)}; 321 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 322 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc}); 323 AInfo Info(MF->getSubtarget()); 324 DummyGISelObserver Observer; 325 LegalizerHelper Helper(*MF, Info, Observer, B); 326 EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ, 1, s16) == 327 LegalizerHelper::LegalizeResult::Legalized); 328 329 auto CheckStr = R"( 330 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 331 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 332 CHECK: [[Ctlz:%[0-9]+]]:_(s16) = G_CTLZ [[Zext]] 333 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 334 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[Ctlz]]:_, [[Cst8]]:_ 335 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]] 336 )"; 337 338 // Check 339 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 340 } 341 342 // CTLZ_ZERO_UNDEF widening. 343 TEST_F(GISelMITest, WidenBitCountingCTLZZeroUndef) { 344 if (!TM) 345 return; 346 347 // Declare your legalization info 348 DefineLegalizerInfo(A, { 349 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s16, s16}}); 350 }); 351 // Build 352 // Trunc it to s8. 353 LLT s8{LLT::scalar(8)}; 354 LLT s16{LLT::scalar(16)}; 355 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 356 auto MIBCTLZ_ZU = 357 B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {s8}, {MIBTrunc}); 358 AInfo Info(MF->getSubtarget()); 359 DummyGISelObserver Observer; 360 LegalizerHelper Helper(*MF, Info, Observer, B); 361 EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ_ZU, 1, s16) == 362 LegalizerHelper::LegalizeResult::Legalized); 363 364 auto CheckStr = R"( 365 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 366 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 367 CHECK: [[CtlzZu:%[0-9]+]]:_(s16) = G_CTLZ_ZERO_UNDEF [[Zext]] 368 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 369 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[CtlzZu]]:_, [[Cst8]]:_ 370 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]] 371 )"; 372 373 // Check 374 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 375 } 376 377 // CTPOP widening. 378 TEST_F(GISelMITest, WidenBitCountingCTPOP) { 379 if (!TM) 380 return; 381 382 // Declare your legalization info 383 DefineLegalizerInfo(A, { 384 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}}); 385 }); 386 // Build 387 // Trunc it to s8. 388 LLT s8{LLT::scalar(8)}; 389 LLT s16{LLT::scalar(16)}; 390 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 391 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s8}, {MIBTrunc}); 392 AInfo Info(MF->getSubtarget()); 393 DummyGISelObserver Observer; 394 LegalizerHelper Helper(*MF, Info, Observer, B); 395 EXPECT_TRUE(Helper.widenScalar(*MIBCTPOP, 1, s16) == 396 LegalizerHelper::LegalizeResult::Legalized); 397 398 auto CheckStr = R"( 399 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 400 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 401 CHECK: [[Ctpop:%[0-9]+]]:_(s16) = G_CTPOP [[Zext]] 402 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Ctpop]] 403 )"; 404 405 // Check 406 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 407 } 408 409 // CTTZ_ZERO_UNDEF widening. 410 TEST_F(GISelMITest, WidenBitCountingCTTZ_ZERO_UNDEF) { 411 if (!TM) 412 return; 413 414 // Declare your legalization info 415 DefineLegalizerInfo(A, { 416 getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s16, s16}}); 417 }); 418 // Build 419 // Trunc it to s8. 420 LLT s8{LLT::scalar(8)}; 421 LLT s16{LLT::scalar(16)}; 422 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 423 auto MIBCTTZ_ZERO_UNDEF = 424 B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, {s8}, {MIBTrunc}); 425 AInfo Info(MF->getSubtarget()); 426 DummyGISelObserver Observer; 427 LegalizerHelper Helper(*MF, Info, Observer, B); 428 EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ_ZERO_UNDEF, 1, s16) == 429 LegalizerHelper::LegalizeResult::Legalized); 430 431 auto CheckStr = R"( 432 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 433 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 434 CHECK: [[CttzZu:%[0-9]+]]:_(s16) = G_CTTZ_ZERO_UNDEF [[Zext]] 435 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[CttzZu]] 436 )"; 437 438 // Check 439 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 440 } 441 442 // CTTZ widening. 443 TEST_F(GISelMITest, WidenBitCountingCTTZ) { 444 if (!TM) 445 return; 446 447 // Declare your legalization info 448 DefineLegalizerInfo(A, { 449 getActionDefinitionsBuilder(G_CTTZ).legalFor({{s16, s16}}); 450 }); 451 // Build 452 // Trunc it to s8. 453 LLT s8{LLT::scalar(8)}; 454 LLT s16{LLT::scalar(16)}; 455 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 456 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, {s8}, {MIBTrunc}); 457 AInfo Info(MF->getSubtarget()); 458 DummyGISelObserver Observer; 459 LegalizerHelper Helper(*MF, Info, Observer, B); 460 EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ, 1, s16) == 461 LegalizerHelper::LegalizeResult::Legalized); 462 463 auto CheckStr = R"( 464 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 465 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 466 CHECK: [[Cst:%[0-9]+]]:_(s16) = G_CONSTANT i16 256 467 CHECK: [[Or:%[0-9]+]]:_(s16) = G_OR [[Zext]]:_, [[Cst]] 468 CHECK: [[Cttz:%[0-9]+]]:_(s16) = G_CTTZ [[Or]] 469 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Cttz]] 470 )"; 471 472 // Check 473 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 474 } 475 // UADDO widening. 476 TEST_F(GISelMITest, WidenUADDO) { 477 if (!TM) 478 return; 479 480 // Declare your legalization info 481 DefineLegalizerInfo(A, { 482 getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}}); 483 }); 484 // Build 485 // Trunc it to s8. 486 LLT s8{LLT::scalar(8)}; 487 LLT s16{LLT::scalar(16)}; 488 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 489 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); 490 auto MIBUAddO = 491 B.buildInstr(TargetOpcode::G_UADDO, {s8, CarryReg}, {MIBTrunc, MIBTrunc}); 492 AInfo Info(MF->getSubtarget()); 493 DummyGISelObserver Observer; 494 LegalizerHelper Helper(*MF, Info, Observer, B); 495 EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) == 496 LegalizerHelper::LegalizeResult::Legalized); 497 498 auto CheckStr = R"( 499 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 500 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 501 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 502 CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_ 503 CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255 504 CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[ADD]]:_, [[CST]]:_ 505 CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[AND]]:_ 506 CHECK: G_TRUNC [[ADD]] 507 )"; 508 509 // Check 510 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 511 } 512 513 // USUBO widening. 514 TEST_F(GISelMITest, WidenUSUBO) { 515 if (!TM) 516 return; 517 518 // Declare your legalization info 519 DefineLegalizerInfo(A, { 520 getActionDefinitionsBuilder(G_SUB).legalFor({{s16, s16}}); 521 }); 522 // Build 523 // Trunc it to s8. 524 LLT s8{LLT::scalar(8)}; 525 LLT s16{LLT::scalar(16)}; 526 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 527 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); 528 auto MIBUSUBO = 529 B.buildInstr(TargetOpcode::G_USUBO, {s8, CarryReg}, {MIBTrunc, MIBTrunc}); 530 AInfo Info(MF->getSubtarget()); 531 DummyGISelObserver Observer; 532 LegalizerHelper Helper(*MF, Info, Observer, B); 533 EXPECT_TRUE(Helper.widenScalar(*MIBUSUBO, 0, s16) == 534 LegalizerHelper::LegalizeResult::Legalized); 535 536 auto CheckStr = R"( 537 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 538 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 539 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 540 CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_ 541 CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255 542 CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[SUB]]:_, [[CST]]:_ 543 CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[AND]]:_ 544 CHECK: G_TRUNC [[SUB]] 545 )"; 546 547 // Check 548 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 549 } 550 551 TEST_F(GISelMITest, FewerElementsAnd) { 552 if (!TM) 553 return; 554 555 const LLT V2S32 = LLT::vector(2, 32); 556 const LLT V5S32 = LLT::vector(5, 32); 557 558 // Declare your legalization info 559 DefineLegalizerInfo(A, { 560 getActionDefinitionsBuilder(G_AND) 561 .legalFor({s32}); 562 }); 563 564 auto Op0 = B.buildUndef(V5S32); 565 auto Op1 = B.buildUndef(V5S32); 566 auto And = B.buildAnd(V5S32, Op0, Op1); 567 568 AInfo Info(MF->getSubtarget()); 569 DummyGISelObserver Observer; 570 LegalizerHelper Helper(*MF, Info, Observer, B); 571 EXPECT_TRUE(Helper.fewerElementsVector(*And, 0, V2S32) == 572 LegalizerHelper::LegalizeResult::Legalized); 573 574 auto CheckStr = R"( 575 CHECK: [[IMP_DEF0:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF 576 CHECK: [[IMP_DEF1:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF 577 CHECK: [[IMP_DEF2:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF 578 CHECK: [[EXTRACT0:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 0 579 CHECK: [[EXTRACT1:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 0 580 CHECK: [[AND0:%[0-9]+]]:_(<2 x s32>) = G_AND [[EXTRACT0]]:_, [[EXTRACT1]]:_ 581 CHECK: [[INSERT0:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[IMP_DEF2]]:_, [[AND0]]:_(<2 x s32>), 0 582 583 CHECK: [[EXTRACT2:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 64 584 CHECK: [[EXTRACT3:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 64 585 CHECK: [[AND1:%[0-9]+]]:_(<2 x s32>) = G_AND [[EXTRACT2]]:_, [[EXTRACT3]]:_ 586 CHECK: [[INSERT1:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT0]]:_, [[AND1]]:_(<2 x s32>), 64 587 588 CHECK: [[EXTRACT4:%[0-9]+]]:_(s32) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 128 589 CHECK: [[EXTRACT5:%[0-9]+]]:_(s32) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 128 590 CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[EXTRACT4]]:_, [[EXTRACT5]]:_ 591 CHECK: [[INSERT2:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT1]]:_, [[AND2]]:_(s32), 128 592 )"; 593 594 // Check 595 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 596 } 597 598 TEST_F(GISelMITest, MoreElementsAnd) { 599 if (!TM) 600 return; 601 602 LLT s32 = LLT::scalar(32); 603 LLT v2s32 = LLT::vector(2, 32); 604 LLT v6s32 = LLT::vector(6, 32); 605 606 LegalizerInfo LI; 607 LI.getActionDefinitionsBuilder(TargetOpcode::G_AND) 608 .legalFor({v6s32}) 609 .clampMinNumElements(0, s32, 6); 610 LI.computeTables(); 611 612 DummyGISelObserver Observer; 613 LegalizerHelper Helper(*MF, LI, Observer, B); 614 615 B.setInsertPt(*EntryMBB, EntryMBB->end()); 616 617 auto Val0 = B.buildBitcast(v2s32, Copies[0]); 618 auto Val1 = B.buildBitcast(v2s32, Copies[1]); 619 620 auto And = B.buildAnd(v2s32, Val0, Val1); 621 622 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 623 Helper.moreElementsVector(*And, 0, v6s32)); 624 625 auto CheckStr = R"( 626 CHECK: [[BITCAST0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST 627 CHECK: [[BITCAST1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST 628 CHECK: [[IMP_DEF0:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF 629 CHECK: [[CONCAT0:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>) 630 CHECK: [[IMP_DEF1:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF 631 CHECK: [[CONCAT1:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>) 632 CHECK: [[AND:%[0-9]+]]:_(<6 x s32>) = G_AND [[CONCAT0]]:_, [[CONCAT1]]:_ 633 CHECK: (<2 x s32>) = G_EXTRACT [[AND]]:_(<6 x s32>), 0 634 )"; 635 636 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 637 } 638 639 TEST_F(GISelMITest, FewerElementsPhi) { 640 if (!TM) 641 return; 642 643 LLT s1 = LLT::scalar(1); 644 LLT s32 = LLT::scalar(32); 645 LLT s64 = LLT::scalar(64); 646 LLT v2s32 = LLT::vector(2, 32); 647 LLT v5s32 = LLT::vector(5, 32); 648 649 LegalizerInfo LI; 650 LI.getActionDefinitionsBuilder(TargetOpcode::G_PHI) 651 .legalFor({v2s32}) 652 .clampMinNumElements(0, s32, 2); 653 LI.computeTables(); 654 655 LLT PhiTy = v5s32; 656 DummyGISelObserver Observer; 657 LegalizerHelper Helper(*MF, LI, Observer, B); 658 B.setMBB(*EntryMBB); 659 660 MachineBasicBlock *MidMBB = MF->CreateMachineBasicBlock(); 661 MachineBasicBlock *EndMBB = MF->CreateMachineBasicBlock(); 662 MF->insert(MF->end(), MidMBB); 663 MF->insert(MF->end(), EndMBB); 664 665 EntryMBB->addSuccessor(MidMBB); 666 EntryMBB->addSuccessor(EndMBB); 667 MidMBB->addSuccessor(EndMBB); 668 669 auto InitVal = B.buildUndef(PhiTy); 670 auto InitOtherVal = B.buildConstant(s64, 999); 671 672 auto ICmp = B.buildICmp(CmpInst::ICMP_EQ, s1, Copies[0], Copies[1]); 673 B.buildBrCond(ICmp.getReg(0), *MidMBB); 674 B.buildBr(*EndMBB); 675 676 677 B.setMBB(*MidMBB); 678 auto MidVal = B.buildUndef(PhiTy); 679 auto MidOtherVal = B.buildConstant(s64, 345); 680 B.buildBr(*EndMBB); 681 682 B.setMBB(*EndMBB); 683 auto Phi = B.buildInstr(TargetOpcode::G_PHI) 684 .addDef(MRI->createGenericVirtualRegister(PhiTy)) 685 .addUse(InitVal.getReg(0)) 686 .addMBB(EntryMBB) 687 .addUse(MidVal.getReg(0)) 688 .addMBB(MidMBB); 689 690 // Insert another irrelevant phi to make sure the rebuild is inserted after 691 // it. 692 B.buildInstr(TargetOpcode::G_PHI) 693 .addDef(MRI->createGenericVirtualRegister(s64)) 694 .addUse(InitOtherVal.getReg(0)) 695 .addMBB(EntryMBB) 696 .addUse(MidOtherVal.getReg(0)) 697 .addMBB(MidMBB); 698 699 // Add some use instruction after the phis. 700 B.buildAnd(PhiTy, Phi.getReg(0), Phi.getReg(0)); 701 702 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 703 Helper.fewerElementsVector(*Phi, 0, v2s32)); 704 705 auto CheckStr = R"( 706 CHECK: [[INITVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF 707 CHECK: [[EXTRACT0:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 0 708 CHECK: [[EXTRACT1:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 64 709 CHECK: [[EXTRACT2:%[0-9]+]]:_(s32) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 128 710 CHECK: G_BRCOND 711 712 CHECK: [[MIDVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF 713 CHECK: [[EXTRACT3:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 0 714 CHECK: [[EXTRACT4:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 64 715 CHECK: [[EXTRACT5:%[0-9]+]]:_(s32) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 128 716 CHECK: G_BR 717 718 CHECK: [[PHI0:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT0]]:_(<2 x s32>), %bb.0, [[EXTRACT3]]:_(<2 x s32>), %bb.1 719 CHECK: [[PHI1:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT1]]:_(<2 x s32>), %bb.0, [[EXTRACT4]]:_(<2 x s32>), %bb.1 720 CHECK: [[PHI2:%[0-9]+]]:_(s32) = G_PHI [[EXTRACT2]]:_(s32), %bb.0, [[EXTRACT5]]:_(s32), %bb.1 721 722 CHECK: [[OTHER_PHI:%[0-9]+]]:_(s64) = G_PHI 723 CHECK: [[REBUILD_VAL_IMPDEF:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF 724 CHECK: [[INSERT0:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[REBUILD_VAL_IMPDEF]]:_, [[PHI0]]:_(<2 x s32>), 0 725 CHECK: [[INSERT1:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT0]]:_, [[PHI1]]:_(<2 x s32>), 64 726 CHECK: [[INSERT2:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT1]]:_, [[PHI2]]:_(s32), 128 727 CHECK: [[USE_OP:%[0-9]+]]:_(<5 x s32>) = G_AND [[INSERT2]]:_, [[INSERT2]]:_ 728 )"; 729 730 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 731 } 732 733 // FNEG expansion in terms of FSUB 734 TEST_F(GISelMITest, LowerFNEG) { 735 if (!TM) 736 return; 737 738 // Declare your legalization info 739 DefineLegalizerInfo(A, { 740 getActionDefinitionsBuilder(G_FSUB).legalFor({s64}); 741 }); 742 743 // Build Instr. Make sure FMF are preserved. 744 auto FAdd = 745 B.buildInstr(TargetOpcode::G_FADD, {LLT::scalar(64)}, {Copies[0], Copies[1]}, 746 MachineInstr::MIFlag::FmNsz); 747 748 // Should not propagate the flags of src instruction. 749 auto FNeg0 = 750 B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {FAdd.getReg(0)}, 751 {MachineInstr::MIFlag::FmArcp}); 752 753 // Preserve the one flag. 754 auto FNeg1 = 755 B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {Copies[0]}, 756 MachineInstr::MIFlag::FmNoInfs); 757 758 AInfo Info(MF->getSubtarget()); 759 DummyGISelObserver Observer; 760 LegalizerHelper Helper(*MF, Info, Observer, B); 761 // Perform Legalization 762 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 763 Helper.lower(*FNeg0, 0, LLT::scalar(64))); 764 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 765 Helper.lower(*FNeg1, 0, LLT::scalar(64))); 766 767 auto CheckStr = R"( 768 CHECK: [[FADD:%[0-9]+]]:_(s64) = nsz G_FADD %0:_, %1:_ 769 CHECK: [[CONST0:%[0-9]+]]:_(s64) = G_FCONSTANT double -0.000000e+00 770 CHECK: [[FSUB0:%[0-9]+]]:_(s64) = arcp G_FSUB [[CONST0]]:_, [[FADD]]:_ 771 CHECK: [[CONST1:%[0-9]+]]:_(s64) = G_FCONSTANT double -0.000000e+00 772 CHECK: [[FSUB1:%[0-9]+]]:_(s64) = ninf G_FSUB [[CONST1]]:_, %0:_ 773 )"; 774 775 // Check 776 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 777 } 778 } // namespace 779