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 using namespace LegalizeActions; 13 using namespace LegalizeMutations; 14 using namespace LegalityPredicates; 15 16 namespace { 17 18 class DummyGISelObserver : public GISelChangeObserver { 19 public: 20 void changingInstr(MachineInstr &MI) override {} 21 void changedInstr(MachineInstr &MI) override {} 22 void createdInstr(MachineInstr &MI) override {} 23 void erasingInstr(MachineInstr &MI) override {} 24 }; 25 26 // Test CTTZ expansion when CTTZ_ZERO_UNDEF is legal or custom, 27 // in which case it becomes CTTZ_ZERO_UNDEF with select. 28 TEST_F(GISelMITest, LowerBitCountingCTTZ0) { 29 setUp(); 30 if (!TM) 31 return; 32 33 // Declare your legalization info 34 DefineLegalizerInfo(A, { 35 getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s64, s64}}); 36 }); 37 // Build Instr 38 auto MIBCTTZ = 39 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]}); 40 AInfo Info(MF->getSubtarget()); 41 DummyGISelObserver Observer; 42 LegalizerHelper Helper(*MF, Info, Observer, B); 43 // Perform Legalization 44 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) == 45 LegalizerHelper::LegalizeResult::Legalized); 46 47 auto CheckStr = R"( 48 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTTZ_ZERO_UNDEF %0 49 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 50 CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64 51 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]] 52 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]] 53 )"; 54 55 // Check 56 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 57 } 58 59 // CTTZ expansion in terms of CTLZ 60 TEST_F(GISelMITest, LowerBitCountingCTTZ1) { 61 setUp(); 62 if (!TM) 63 return; 64 65 // Declare your legalization info 66 DefineLegalizerInfo(A, { 67 getActionDefinitionsBuilder(G_CTLZ).legalFor({{s64, s64}}); 68 }); 69 // Build Instr 70 auto MIBCTTZ = 71 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]}); 72 AInfo Info(MF->getSubtarget()); 73 DummyGISelObserver Observer; 74 LegalizerHelper Helper(*MF, Info, Observer, B); 75 // Perform Legalization 76 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) == 77 LegalizerHelper::LegalizeResult::Legalized); 78 79 auto CheckStr = R"( 80 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1 81 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]] 82 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]] 83 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_ 84 CHECK: [[CST64:%[0-9]+]]:_(s64) = G_CONSTANT i64 64 85 CHECK: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[AND1]]:_ 86 CHECK: G_SUB [[CST64]]:_, [[CTLZ]]:_ 87 )"; 88 89 // Check 90 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 91 } 92 93 // CTTZ expansion in terms of CTPOP 94 TEST_F(GISelMITest, LowerBitCountingCTTZ2) { 95 setUp(); 96 if (!TM) 97 return; 98 99 // Declare your legalization info 100 DefineLegalizerInfo(A, { 101 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s64, s64}}); 102 }); 103 // Build 104 auto MIBCTTZ = 105 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]}); 106 AInfo Info(MF->getSubtarget()); 107 DummyGISelObserver Observer; 108 LegalizerHelper Helper(*MF, Info, Observer, B); 109 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) == 110 LegalizerHelper::LegalizeResult::Legalized); 111 112 auto CheckStr = R"( 113 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1 114 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]] 115 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]] 116 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_ 117 CHECK: [[POP:%[0-9]+]]:_(s64) = G_CTPOP [[AND1]] 118 )"; 119 120 // Check 121 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 122 } 123 124 // CTPOP widening. 125 TEST_F(GISelMITest, WidenBitCountingCTPOP1) { 126 if (!TM) 127 return; 128 129 // Declare your legalization info 130 DefineLegalizerInfo(A, { 131 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}}); 132 }); 133 134 // Build 135 // Trunc it to s8. 136 LLT s8{LLT::scalar(8)}; 137 LLT s16{LLT::scalar(16)}; 138 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 139 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s16}, {MIBTrunc}); 140 AInfo Info(MF->getSubtarget()); 141 DummyGISelObserver Observer; 142 LegalizerHelper Helper(*MF, Info, Observer, B); 143 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 144 Helper.widenScalar(*MIBCTPOP, 1, s16)); 145 146 auto CheckStr = R"( 147 CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64) 148 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8) 149 CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]] 150 CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY [[CTPOP]]:_(s16) 151 )"; 152 153 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 154 } 155 156 // Test a strange case where the result is wider than the source 157 TEST_F(GISelMITest, WidenBitCountingCTPOP2) { 158 if (!TM) 159 return; 160 161 // Declare your legalization info 162 DefineLegalizerInfo(A, { 163 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s32, s16}}); 164 }); 165 166 // Build 167 // Trunc it to s8. 168 LLT s8{LLT::scalar(8)}; 169 LLT s16{LLT::scalar(16)}; 170 LLT s32{LLT::scalar(32)}; 171 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 172 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s32}, {MIBTrunc}); 173 AInfo Info(MF->getSubtarget()); 174 DummyGISelObserver Observer; 175 LegalizerHelper Helper(*MF, Info, Observer, B); 176 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 177 Helper.widenScalar(*MIBCTPOP, 1, s16)); 178 179 auto CheckStr = R"( 180 CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64) 181 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8) 182 CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]] 183 CHECK: [[COPY:%[0-9]+]]:_(s32) = G_ZEXT [[CTPOP]]:_(s16) 184 )"; 185 186 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 187 } 188 189 // CTTZ_ZERO_UNDEF expansion in terms of CTTZ 190 TEST_F(GISelMITest, LowerBitCountingCTTZ3) { 191 setUp(); 192 if (!TM) 193 return; 194 195 // Declare your legalization info 196 DefineLegalizerInfo(A, { 197 getActionDefinitionsBuilder(G_CTTZ).legalFor({{s64, s64}}); 198 }); 199 // Build 200 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, 201 {LLT::scalar(64)}, {Copies[0]}); 202 AInfo Info(MF->getSubtarget()); 203 DummyGISelObserver Observer; 204 LegalizerHelper Helper(*MF, Info, Observer, B); 205 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) == 206 LegalizerHelper::LegalizeResult::Legalized); 207 208 auto CheckStr = R"( 209 CHECK: CTTZ 210 )"; 211 212 // Check 213 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 214 } 215 216 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF 217 TEST_F(GISelMITest, LowerBitCountingCTLZ0) { 218 setUp(); 219 if (!TM) 220 return; 221 222 // Declare your legalization info 223 DefineLegalizerInfo(A, { 224 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s64, s64}}); 225 }); 226 // Build 227 auto MIBCTLZ = 228 B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(64)}, {Copies[0]}); 229 AInfo Info(MF->getSubtarget()); 230 DummyGISelObserver Observer; 231 LegalizerHelper Helper(*MF, Info, Observer, B); 232 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) == 233 LegalizerHelper::LegalizeResult::Legalized); 234 235 auto CheckStr = R"( 236 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0 237 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 238 CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64 239 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]] 240 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]] 241 )"; 242 243 // Check 244 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 245 } 246 247 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF if the latter is a libcall 248 TEST_F(GISelMITest, LowerBitCountingCTLZLibcall) { 249 setUp(); 250 if (!TM) 251 return; 252 253 // Declare your legalization info 254 DefineLegalizerInfo(A, { 255 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).libcallFor({{s64, s64}}); 256 }); 257 // Build 258 auto MIBCTLZ = 259 B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(64)}, {Copies[0]}); 260 AInfo Info(MF->getSubtarget()); 261 DummyGISelObserver Observer; 262 LegalizerHelper Helper(*MF, Info, Observer, B); 263 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) == 264 LegalizerHelper::LegalizeResult::Legalized); 265 266 auto CheckStr = R"( 267 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0 268 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 269 CHECK: [[THIRTY2:%[0-9]+]]:_(s64) = G_CONSTANT i64 64 270 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]] 271 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[THIRTY2]]:_, [[CZU]] 272 )"; 273 274 // Check 275 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 276 } 277 278 // CTLZ expansion 279 TEST_F(GISelMITest, LowerBitCountingCTLZ1) { 280 setUp(); 281 if (!TM) 282 return; 283 284 // Declare your legalization info 285 DefineLegalizerInfo(A, { 286 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s8, s8}}); 287 }); 288 // Build 289 // Trunc it to s8. 290 LLT s8{LLT::scalar(8)}; 291 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 292 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc}); 293 AInfo Info(MF->getSubtarget()); 294 DummyGISelObserver Observer; 295 LegalizerHelper Helper(*MF, Info, Observer, B); 296 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, s8) == 297 LegalizerHelper::LegalizeResult::Legalized); 298 299 auto CheckStr = R"( 300 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 301 CHECK: [[Cst1:%[0-9]+]]:_(s8) = G_CONSTANT i8 1 302 CHECK: [[Sh1:%[0-9]+]]:_(s8) = G_LSHR [[Trunc]]:_, [[Cst1]]:_ 303 CHECK: [[Or1:%[0-9]+]]:_(s8) = G_OR [[Trunc]]:_, [[Sh1]]:_ 304 CHECK: [[Cst2:%[0-9]+]]:_(s8) = G_CONSTANT i8 2 305 CHECK: [[Sh2:%[0-9]+]]:_(s8) = G_LSHR [[Or1]]:_, [[Cst2]]:_ 306 CHECK: [[Or2:%[0-9]+]]:_(s8) = G_OR [[Or1]]:_, [[Sh2]]:_ 307 CHECK: [[Cst4:%[0-9]+]]:_(s8) = G_CONSTANT i8 4 308 CHECK: [[Sh4:%[0-9]+]]:_(s8) = G_LSHR [[Or2]]:_, [[Cst4]]:_ 309 CHECK: [[Or4:%[0-9]+]]:_(s8) = G_OR [[Or2]]:_, [[Sh4]]:_ 310 CHECK: [[CTPOP:%[0-9]+]]:_(s8) = G_CTPOP [[Or4]]:_ 311 CHECK: [[Len:%[0-9]+]]:_(s8) = G_CONSTANT i8 8 312 CHECK: [[Sub:%[0-9]+]]:_(s8) = G_SUB [[Len]]:_, [[CTPOP]]:_ 313 )"; 314 315 // Check 316 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 317 } 318 319 // CTLZ widening. 320 TEST_F(GISelMITest, WidenBitCountingCTLZ) { 321 setUp(); 322 if (!TM) 323 return; 324 325 // Declare your legalization info 326 DefineLegalizerInfo(A, { 327 getActionDefinitionsBuilder(G_CTLZ).legalFor({{s16, s16}}); 328 }); 329 // Build 330 // Trunc it to s8. 331 LLT s8{LLT::scalar(8)}; 332 LLT s16{LLT::scalar(16)}; 333 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 334 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc}); 335 AInfo Info(MF->getSubtarget()); 336 DummyGISelObserver Observer; 337 LegalizerHelper Helper(*MF, Info, Observer, B); 338 EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ, 1, s16) == 339 LegalizerHelper::LegalizeResult::Legalized); 340 341 auto CheckStr = R"( 342 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 343 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 344 CHECK: [[Ctlz:%[0-9]+]]:_(s16) = G_CTLZ [[Zext]] 345 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 346 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[Ctlz]]:_, [[Cst8]]:_ 347 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]] 348 )"; 349 350 // Check 351 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 352 } 353 354 // CTLZ_ZERO_UNDEF widening. 355 TEST_F(GISelMITest, WidenBitCountingCTLZZeroUndef) { 356 setUp(); 357 if (!TM) 358 return; 359 360 // Declare your legalization info 361 DefineLegalizerInfo(A, { 362 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s16, s16}}); 363 }); 364 // Build 365 // Trunc it to s8. 366 LLT s8{LLT::scalar(8)}; 367 LLT s16{LLT::scalar(16)}; 368 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 369 auto MIBCTLZ_ZU = 370 B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {s8}, {MIBTrunc}); 371 AInfo Info(MF->getSubtarget()); 372 DummyGISelObserver Observer; 373 LegalizerHelper Helper(*MF, Info, Observer, B); 374 EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ_ZU, 1, s16) == 375 LegalizerHelper::LegalizeResult::Legalized); 376 377 auto CheckStr = R"( 378 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 379 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 380 CHECK: [[CtlzZu:%[0-9]+]]:_(s16) = G_CTLZ_ZERO_UNDEF [[Zext]] 381 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 382 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[CtlzZu]]:_, [[Cst8]]:_ 383 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]] 384 )"; 385 386 // Check 387 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 388 } 389 390 // CTPOP widening. 391 TEST_F(GISelMITest, WidenBitCountingCTPOP) { 392 setUp(); 393 if (!TM) 394 return; 395 396 // Declare your legalization info 397 DefineLegalizerInfo(A, { 398 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}}); 399 }); 400 // Build 401 // Trunc it to s8. 402 LLT s8{LLT::scalar(8)}; 403 LLT s16{LLT::scalar(16)}; 404 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 405 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s8}, {MIBTrunc}); 406 AInfo Info(MF->getSubtarget()); 407 DummyGISelObserver Observer; 408 LegalizerHelper Helper(*MF, Info, Observer, B); 409 EXPECT_TRUE(Helper.widenScalar(*MIBCTPOP, 1, s16) == 410 LegalizerHelper::LegalizeResult::Legalized); 411 412 auto CheckStr = R"( 413 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 414 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 415 CHECK: [[Ctpop:%[0-9]+]]:_(s16) = G_CTPOP [[Zext]] 416 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Ctpop]] 417 )"; 418 419 // Check 420 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 421 } 422 423 // CTTZ_ZERO_UNDEF widening. 424 TEST_F(GISelMITest, WidenBitCountingCTTZ_ZERO_UNDEF) { 425 setUp(); 426 if (!TM) 427 return; 428 429 // Declare your legalization info 430 DefineLegalizerInfo(A, { 431 getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s16, s16}}); 432 }); 433 // Build 434 // Trunc it to s8. 435 LLT s8{LLT::scalar(8)}; 436 LLT s16{LLT::scalar(16)}; 437 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 438 auto MIBCTTZ_ZERO_UNDEF = 439 B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, {s8}, {MIBTrunc}); 440 AInfo Info(MF->getSubtarget()); 441 DummyGISelObserver Observer; 442 LegalizerHelper Helper(*MF, Info, Observer, B); 443 EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ_ZERO_UNDEF, 1, s16) == 444 LegalizerHelper::LegalizeResult::Legalized); 445 446 auto CheckStr = R"( 447 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 448 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 449 CHECK: [[CttzZu:%[0-9]+]]:_(s16) = G_CTTZ_ZERO_UNDEF [[Zext]] 450 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[CttzZu]] 451 )"; 452 453 // Check 454 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 455 } 456 457 // CTTZ widening. 458 TEST_F(GISelMITest, WidenBitCountingCTTZ) { 459 setUp(); 460 if (!TM) 461 return; 462 463 // Declare your legalization info 464 DefineLegalizerInfo(A, { 465 getActionDefinitionsBuilder(G_CTTZ).legalFor({{s16, s16}}); 466 }); 467 // Build 468 // Trunc it to s8. 469 LLT s8{LLT::scalar(8)}; 470 LLT s16{LLT::scalar(16)}; 471 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 472 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, {s8}, {MIBTrunc}); 473 AInfo Info(MF->getSubtarget()); 474 DummyGISelObserver Observer; 475 LegalizerHelper Helper(*MF, Info, Observer, B); 476 EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ, 1, s16) == 477 LegalizerHelper::LegalizeResult::Legalized); 478 479 auto CheckStr = R"( 480 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 481 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 482 CHECK: [[Cst:%[0-9]+]]:_(s16) = G_CONSTANT i16 256 483 CHECK: [[Or:%[0-9]+]]:_(s16) = G_OR [[Zext]]:_, [[Cst]] 484 CHECK: [[Cttz:%[0-9]+]]:_(s16) = G_CTTZ [[Or]] 485 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Cttz]] 486 )"; 487 488 // Check 489 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 490 } 491 // UADDO widening. 492 TEST_F(GISelMITest, WidenUADDO) { 493 setUp(); 494 if (!TM) 495 return; 496 497 // Declare your legalization info 498 DefineLegalizerInfo(A, { 499 getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}}); 500 }); 501 // Build 502 // Trunc it to s8. 503 LLT s8{LLT::scalar(8)}; 504 LLT s16{LLT::scalar(16)}; 505 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 506 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); 507 auto MIBUAddO = 508 B.buildInstr(TargetOpcode::G_UADDO, {s8, CarryReg}, {MIBTrunc, MIBTrunc}); 509 AInfo Info(MF->getSubtarget()); 510 DummyGISelObserver Observer; 511 LegalizerHelper Helper(*MF, Info, Observer, B); 512 EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) == 513 LegalizerHelper::LegalizeResult::Legalized); 514 515 auto CheckStr = R"( 516 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 517 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 518 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 519 CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_ 520 CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255 521 CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[ADD]]:_, [[CST]]:_ 522 CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[AND]]:_ 523 CHECK: G_TRUNC [[ADD]] 524 )"; 525 526 // Check 527 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 528 } 529 530 // USUBO widening. 531 TEST_F(GISelMITest, WidenUSUBO) { 532 setUp(); 533 if (!TM) 534 return; 535 536 // Declare your legalization info 537 DefineLegalizerInfo(A, { 538 getActionDefinitionsBuilder(G_SUB).legalFor({{s16, s16}}); 539 }); 540 // Build 541 // Trunc it to s8. 542 LLT s8{LLT::scalar(8)}; 543 LLT s16{LLT::scalar(16)}; 544 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 545 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); 546 auto MIBUSUBO = 547 B.buildInstr(TargetOpcode::G_USUBO, {s8, CarryReg}, {MIBTrunc, MIBTrunc}); 548 AInfo Info(MF->getSubtarget()); 549 DummyGISelObserver Observer; 550 LegalizerHelper Helper(*MF, Info, Observer, B); 551 EXPECT_TRUE(Helper.widenScalar(*MIBUSUBO, 0, s16) == 552 LegalizerHelper::LegalizeResult::Legalized); 553 554 auto CheckStr = R"( 555 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 556 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 557 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 558 CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_ 559 CHECK: [[CST:%[0-9]+]]:_(s16) = G_CONSTANT i16 255 560 CHECK: [[AND:%[0-9]+]]:_(s16) = G_AND [[SUB]]:_, [[CST]]:_ 561 CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[AND]]:_ 562 CHECK: G_TRUNC [[SUB]] 563 )"; 564 565 // Check 566 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 567 } 568 569 TEST_F(GISelMITest, FewerElementsAnd) { 570 if (!TM) 571 return; 572 573 const LLT V2S32 = LLT::vector(2, 32); 574 const LLT V5S32 = LLT::vector(5, 32); 575 576 // Declare your legalization info 577 DefineLegalizerInfo(A, { 578 getActionDefinitionsBuilder(G_AND) 579 .legalFor({s32}); 580 }); 581 582 auto Op0 = B.buildUndef(V5S32); 583 auto Op1 = B.buildUndef(V5S32); 584 auto And = B.buildAnd(V5S32, Op0, Op1); 585 586 AInfo Info(MF->getSubtarget()); 587 DummyGISelObserver Observer; 588 LegalizerHelper Helper(*MF, Info, Observer, B); 589 EXPECT_TRUE(Helper.fewerElementsVector(*And, 0, V2S32) == 590 LegalizerHelper::LegalizeResult::Legalized); 591 592 auto CheckStr = R"( 593 CHECK: [[IMP_DEF0:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF 594 CHECK: [[IMP_DEF1:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF 595 CHECK: [[IMP_DEF2:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF 596 CHECK: [[EXTRACT0:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 0 597 CHECK: [[EXTRACT1:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 0 598 CHECK: [[AND0:%[0-9]+]]:_(<2 x s32>) = G_AND [[EXTRACT0]]:_, [[EXTRACT1]]:_ 599 CHECK: [[INSERT0:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[IMP_DEF2]]:_, [[AND0]]:_(<2 x s32>), 0 600 601 CHECK: [[EXTRACT2:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 64 602 CHECK: [[EXTRACT3:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 64 603 CHECK: [[AND1:%[0-9]+]]:_(<2 x s32>) = G_AND [[EXTRACT2]]:_, [[EXTRACT3]]:_ 604 CHECK: [[INSERT1:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT0]]:_, [[AND1]]:_(<2 x s32>), 64 605 606 CHECK: [[EXTRACT4:%[0-9]+]]:_(s32) = G_EXTRACT [[IMP_DEF0]]:_(<5 x s32>), 128 607 CHECK: [[EXTRACT5:%[0-9]+]]:_(s32) = G_EXTRACT [[IMP_DEF1]]:_(<5 x s32>), 128 608 CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[EXTRACT4]]:_, [[EXTRACT5]]:_ 609 CHECK: [[INSERT2:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT1]]:_, [[AND2]]:_(s32), 128 610 )"; 611 612 // Check 613 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 614 } 615 616 TEST_F(GISelMITest, MoreElementsAnd) { 617 if (!TM) 618 return; 619 620 LLT s32 = LLT::scalar(32); 621 LLT v2s32 = LLT::vector(2, 32); 622 LLT v6s32 = LLT::vector(6, 32); 623 624 LegalizerInfo LI; 625 LI.getActionDefinitionsBuilder(TargetOpcode::G_AND) 626 .legalFor({v6s32}) 627 .clampMinNumElements(0, s32, 6); 628 LI.computeTables(); 629 630 DummyGISelObserver Observer; 631 LegalizerHelper Helper(*MF, LI, Observer, B); 632 633 B.setInsertPt(*EntryMBB, EntryMBB->end()); 634 635 auto Val0 = B.buildBitcast(v2s32, Copies[0]); 636 auto Val1 = B.buildBitcast(v2s32, Copies[1]); 637 638 auto And = B.buildAnd(v2s32, Val0, Val1); 639 640 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 641 Helper.moreElementsVector(*And, 0, v6s32)); 642 643 auto CheckStr = R"( 644 CHECK: [[BITCAST0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST 645 CHECK: [[BITCAST1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST 646 CHECK: [[IMP_DEF0:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF 647 CHECK: [[CONCAT0:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>), [[IMP_DEF0]]:_(<2 x s32>) 648 CHECK: [[IMP_DEF1:%[0-9]+]]:_(<2 x s32>) = G_IMPLICIT_DEF 649 CHECK: [[CONCAT1:%[0-9]+]]:_(<6 x s32>) = G_CONCAT_VECTORS [[BITCAST1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>), [[IMP_DEF1]]:_(<2 x s32>) 650 CHECK: [[AND:%[0-9]+]]:_(<6 x s32>) = G_AND [[CONCAT0]]:_, [[CONCAT1]]:_ 651 CHECK: (<2 x s32>) = G_EXTRACT [[AND]]:_(<6 x s32>), 0 652 )"; 653 654 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 655 } 656 657 TEST_F(GISelMITest, FewerElementsPhi) { 658 if (!TM) 659 return; 660 661 LLT s1 = LLT::scalar(1); 662 LLT s32 = LLT::scalar(32); 663 LLT s64 = LLT::scalar(64); 664 LLT v2s32 = LLT::vector(2, 32); 665 LLT v5s32 = LLT::vector(5, 32); 666 667 LegalizerInfo LI; 668 LI.getActionDefinitionsBuilder(TargetOpcode::G_PHI) 669 .legalFor({v2s32}) 670 .clampMinNumElements(0, s32, 2); 671 LI.computeTables(); 672 673 LLT PhiTy = v5s32; 674 DummyGISelObserver Observer; 675 LegalizerHelper Helper(*MF, LI, Observer, B); 676 B.setMBB(*EntryMBB); 677 678 MachineBasicBlock *MidMBB = MF->CreateMachineBasicBlock(); 679 MachineBasicBlock *EndMBB = MF->CreateMachineBasicBlock(); 680 MF->insert(MF->end(), MidMBB); 681 MF->insert(MF->end(), EndMBB); 682 683 EntryMBB->addSuccessor(MidMBB); 684 EntryMBB->addSuccessor(EndMBB); 685 MidMBB->addSuccessor(EndMBB); 686 687 auto InitVal = B.buildUndef(PhiTy); 688 auto InitOtherVal = B.buildConstant(s64, 999); 689 690 auto ICmp = B.buildICmp(CmpInst::ICMP_EQ, s1, Copies[0], Copies[1]); 691 B.buildBrCond(ICmp.getReg(0), *MidMBB); 692 B.buildBr(*EndMBB); 693 694 695 B.setMBB(*MidMBB); 696 auto MidVal = B.buildUndef(PhiTy); 697 auto MidOtherVal = B.buildConstant(s64, 345); 698 B.buildBr(*EndMBB); 699 700 B.setMBB(*EndMBB); 701 auto Phi = B.buildInstr(TargetOpcode::G_PHI) 702 .addDef(MRI->createGenericVirtualRegister(PhiTy)) 703 .addUse(InitVal.getReg(0)) 704 .addMBB(EntryMBB) 705 .addUse(MidVal.getReg(0)) 706 .addMBB(MidMBB); 707 708 // Insert another irrelevant phi to make sure the rebuild is inserted after 709 // it. 710 B.buildInstr(TargetOpcode::G_PHI) 711 .addDef(MRI->createGenericVirtualRegister(s64)) 712 .addUse(InitOtherVal.getReg(0)) 713 .addMBB(EntryMBB) 714 .addUse(MidOtherVal.getReg(0)) 715 .addMBB(MidMBB); 716 717 // Add some use instruction after the phis. 718 B.buildAnd(PhiTy, Phi.getReg(0), Phi.getReg(0)); 719 720 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 721 Helper.fewerElementsVector(*Phi, 0, v2s32)); 722 723 auto CheckStr = R"( 724 CHECK: [[INITVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF 725 CHECK: [[EXTRACT0:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 0 726 CHECK: [[EXTRACT1:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 64 727 CHECK: [[EXTRACT2:%[0-9]+]]:_(s32) = G_EXTRACT [[INITVAL]]:_(<5 x s32>), 128 728 CHECK: G_BRCOND 729 730 CHECK: [[MIDVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF 731 CHECK: [[EXTRACT3:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 0 732 CHECK: [[EXTRACT4:%[0-9]+]]:_(<2 x s32>) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 64 733 CHECK: [[EXTRACT5:%[0-9]+]]:_(s32) = G_EXTRACT [[MIDVAL]]:_(<5 x s32>), 128 734 CHECK: G_BR 735 736 CHECK: [[PHI0:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT0]]:_(<2 x s32>), %bb.0, [[EXTRACT3]]:_(<2 x s32>), %bb.1 737 CHECK: [[PHI1:%[0-9]+]]:_(<2 x s32>) = G_PHI [[EXTRACT1]]:_(<2 x s32>), %bb.0, [[EXTRACT4]]:_(<2 x s32>), %bb.1 738 CHECK: [[PHI2:%[0-9]+]]:_(s32) = G_PHI [[EXTRACT2]]:_(s32), %bb.0, [[EXTRACT5]]:_(s32), %bb.1 739 740 CHECK: [[OTHER_PHI:%[0-9]+]]:_(s64) = G_PHI 741 CHECK: [[REBUILD_VAL_IMPDEF:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF 742 CHECK: [[INSERT0:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[REBUILD_VAL_IMPDEF]]:_, [[PHI0]]:_(<2 x s32>), 0 743 CHECK: [[INSERT1:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT0]]:_, [[PHI1]]:_(<2 x s32>), 64 744 CHECK: [[INSERT2:%[0-9]+]]:_(<5 x s32>) = G_INSERT [[INSERT1]]:_, [[PHI2]]:_(s32), 128 745 CHECK: [[USE_OP:%[0-9]+]]:_(<5 x s32>) = G_AND [[INSERT2]]:_, [[INSERT2]]:_ 746 )"; 747 748 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 749 } 750 751 // FNEG expansion in terms of FSUB 752 TEST_F(GISelMITest, LowerFNEG) { 753 if (!TM) 754 return; 755 756 // Declare your legalization info 757 DefineLegalizerInfo(A, { 758 getActionDefinitionsBuilder(G_FSUB).legalFor({s64}); 759 }); 760 761 // Build Instr. Make sure FMF are preserved. 762 auto FAdd = 763 B.buildInstr(TargetOpcode::G_FADD, {LLT::scalar(64)}, {Copies[0], Copies[1]}, 764 MachineInstr::MIFlag::FmNsz); 765 766 // Should not propagate the flags of src instruction. 767 auto FNeg0 = 768 B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {FAdd.getReg(0)}, 769 {MachineInstr::MIFlag::FmArcp}); 770 771 // Preserve the one flag. 772 auto FNeg1 = 773 B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {Copies[0]}, 774 MachineInstr::MIFlag::FmNoInfs); 775 776 AInfo Info(MF->getSubtarget()); 777 DummyGISelObserver Observer; 778 LegalizerHelper Helper(*MF, Info, Observer, B); 779 // Perform Legalization 780 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 781 Helper.lower(*FNeg0, 0, LLT::scalar(64))); 782 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 783 Helper.lower(*FNeg1, 0, LLT::scalar(64))); 784 785 auto CheckStr = R"( 786 CHECK: [[FADD:%[0-9]+]]:_(s64) = nsz G_FADD %0:_, %1:_ 787 CHECK: [[CONST0:%[0-9]+]]:_(s64) = G_FCONSTANT double -0.000000e+00 788 CHECK: [[FSUB0:%[0-9]+]]:_(s64) = arcp G_FSUB [[CONST0]]:_, [[FADD]]:_ 789 CHECK: [[CONST1:%[0-9]+]]:_(s64) = G_FCONSTANT double -0.000000e+00 790 CHECK: [[FSUB1:%[0-9]+]]:_(s64) = ninf G_FSUB [[CONST1]]:_, %0:_ 791 )"; 792 793 // Check 794 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 795 } 796 797 TEST_F(GISelMITest, LowerMinMax) { 798 if (!TM) 799 return; 800 801 LLT s64 = LLT::scalar(64); 802 LLT v2s32 = LLT::vector(2, 32); 803 804 DefineLegalizerInfo(A, { 805 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX}) 806 .lowerFor({s64, LLT::vector(2, s32)}); 807 }); 808 809 auto SMin = B.buildSMin(s64, Copies[0], Copies[1]); 810 auto SMax = B.buildSMax(s64, Copies[0], Copies[1]); 811 auto UMin = B.buildUMin(s64, Copies[0], Copies[1]); 812 auto UMax = B.buildUMax(s64, Copies[0], Copies[1]); 813 814 auto VecVal0 = B.buildBitcast(v2s32, Copies[0]); 815 auto VecVal1 = B.buildBitcast(v2s32, Copies[1]); 816 817 auto SMinV = B.buildSMin(v2s32, VecVal0, VecVal1); 818 auto SMaxV = B.buildSMax(v2s32, VecVal0, VecVal1); 819 auto UMinV = B.buildUMin(v2s32, VecVal0, VecVal1); 820 auto UMaxV = B.buildUMax(v2s32, VecVal0, VecVal1); 821 822 AInfo Info(MF->getSubtarget()); 823 DummyGISelObserver Observer; 824 LegalizerHelper Helper(*MF, Info, Observer, B); 825 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 826 Helper.lower(*SMin, 0, s64)); 827 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 828 Helper.lower(*SMax, 0, s64)); 829 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 830 Helper.lower(*UMin, 0, s64)); 831 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 832 Helper.lower(*UMax, 0, s64)); 833 834 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 835 Helper.lower(*SMinV, 0, v2s32)); 836 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 837 Helper.lower(*SMaxV, 0, v2s32)); 838 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 839 Helper.lower(*UMinV, 0, v2s32)); 840 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 841 Helper.lower(*UMaxV, 0, v2s32)); 842 843 auto CheckStr = R"( 844 CHECK: [[CMP0:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), %0:_(s64), %1:_ 845 CHECK: [[SMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP0]]:_(s1), %0:_, %1:_ 846 847 CHECK: [[CMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), %0:_(s64), %1:_ 848 CHECK: [[SMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP1]]:_(s1), %0:_, %1:_ 849 850 CHECK: [[CMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(ult), %0:_(s64), %1:_ 851 CHECK: [[UMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP2]]:_(s1), %0:_, %1:_ 852 853 CHECK: [[CMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(ugt), %0:_(s64), %1:_ 854 CHECK: [[UMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP3]]:_(s1), %0:_, %1:_ 855 856 CHECK: [[VEC0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %0:_(s64) 857 CHECK: [[VEC1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %1:_(s64) 858 859 CHECK: [[VCMP0:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(slt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_ 860 CHECK: [[SMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP0]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_ 861 862 CHECK: [[VCMP1:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(sgt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_ 863 CHECK: [[SMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP1]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_ 864 865 CHECK: [[VCMP2:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ult), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_ 866 CHECK: [[UMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP2]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_ 867 868 CHECK: [[VCMP3:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ugt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_ 869 CHECK: [[UMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP3]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_ 870 )"; 871 872 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 873 } 874 875 TEST_F(GISelMITest, WidenScalarBuildVector) { 876 if (!TM) 877 return; 878 879 LLT S32 = LLT::scalar(32); 880 LLT S16 = LLT::scalar(16); 881 LLT V2S16 = LLT::vector(2, S16); 882 LLT V2S32 = LLT::vector(2, S32); 883 884 DefineLegalizerInfo(A, { 885 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX}) 886 .lowerFor({s64, LLT::vector(2, s32)}); 887 }); 888 889 AInfo Info(MF->getSubtarget()); 890 DummyGISelObserver Observer; 891 LegalizerHelper Helper(*MF, Info, Observer, B); 892 B.setInsertPt(*EntryMBB, EntryMBB->end()); 893 894 Register Constant0 = B.buildConstant(S16, 1).getReg(0); 895 Register Constant1 = B.buildConstant(S16, 2).getReg(0); 896 auto BV0 = B.buildBuildVector(V2S16, {Constant0, Constant1}); 897 auto BV1 = B.buildBuildVector(V2S16, {Constant0, Constant1}); 898 899 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 900 Helper.widenScalar(*BV0, 0, V2S32)); 901 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 902 Helper.widenScalar(*BV1, 1, S32)); 903 904 auto CheckStr = R"( 905 CHECK: [[K0:%[0-9]+]]:_(s16) = G_CONSTANT i16 1 906 CHECK-NEXT: [[K1:%[0-9]+]]:_(s16) = G_CONSTANT i16 2 907 CHECK-NEXT: [[EXT_K0_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]] 908 CHECK-NEXT: [[EXT_K1_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]] 909 CHECK-NEXT: [[BV0:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[EXT_K0_0]]:_(s32), [[EXT_K1_0]]:_(s32) 910 CHECK-NEXT: [[BV0_TRUNC:%[0-9]+]]:_(<2 x s16>) = G_TRUNC [[BV0]] 911 912 CHECK: [[EXT_K0_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]] 913 CHECK-NEXT: [[EXT_K1_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]] 914 915 CHECK-NEXT: [[BV1:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR_TRUNC [[EXT_K0_1]]:_(s32), [[EXT_K1_1]]:_(s32) 916 )"; 917 918 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 919 } 920 921 TEST_F(GISelMITest, LowerMergeValues) { 922 if (!TM) 923 return; 924 925 const LLT S32 = LLT::scalar(32); 926 const LLT S24 = LLT::scalar(24); 927 const LLT S21 = LLT::scalar(21); 928 const LLT S16 = LLT::scalar(16); 929 const LLT S9 = LLT::scalar(9); 930 const LLT S8 = LLT::scalar(8); 931 const LLT S3 = LLT::scalar(3); 932 933 DefineLegalizerInfo(A, { 934 getActionDefinitionsBuilder(G_UNMERGE_VALUES) 935 .widenScalarIf(typeIs(1, LLT::scalar(3)), changeTo(1, LLT::scalar(9))); 936 }); 937 938 AInfo Info(MF->getSubtarget()); 939 DummyGISelObserver Observer; 940 LegalizerHelper Helper(*MF, Info, Observer, B); 941 B.setInsertPt(*EntryMBB, EntryMBB->end()); 942 943 // 24 = 3 3 3 3 3 3 3 3 944 // => 9 945 // 946 // This can do 3 merges, but need an extra implicit_def. 947 SmallVector<Register, 8> Merge0Ops; 948 for (int I = 0; I != 8; ++I) 949 Merge0Ops.push_back(B.buildConstant(S3, I).getReg(0)); 950 951 auto Merge0 = B.buildMerge(S24, Merge0Ops); 952 953 // 21 = 3 3 3 3 3 3 3 954 // => 9, 2 extra implicit_def needed 955 // 956 SmallVector<Register, 8> Merge1Ops; 957 for (int I = 0; I != 7; ++I) 958 Merge1Ops.push_back(B.buildConstant(S3, I).getReg(0)); 959 960 auto Merge1 = B.buildMerge(S21, Merge1Ops); 961 962 SmallVector<Register, 8> Merge2Ops; 963 for (int I = 0; I != 2; ++I) 964 Merge2Ops.push_back(B.buildConstant(S8, I).getReg(0)); 965 966 auto Merge2 = B.buildMerge(S16, Merge2Ops); 967 968 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 969 Helper.widenScalar(*Merge0, 1, S9)); 970 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 971 Helper.widenScalar(*Merge1, 1, S9)); 972 973 // Request a source size greater than the original destination size. 974 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 975 Helper.widenScalar(*Merge2, 1, S32)); 976 977 auto CheckStr = R"( 978 CHECK: [[K0:%[0-9]+]]:_(s3) = G_CONSTANT i3 0 979 CHECK-NEXT: [[K1:%[0-9]+]]:_(s3) = G_CONSTANT i3 1 980 CHECK-NEXT: [[K2:%[0-9]+]]:_(s3) = G_CONSTANT i3 2 981 CHECK-NEXT: [[K3:%[0-9]+]]:_(s3) = G_CONSTANT i3 3 982 CHECK-NEXT: [[K4:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4 983 CHECK-NEXT: [[K5:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3 984 CHECK-NEXT: [[K6:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2 985 CHECK-NEXT: [[K7:%[0-9]+]]:_(s3) = G_CONSTANT i3 -1 986 CHECK-NEXT: [[IMPDEF0:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF 987 CHECK-NEXT: [[MERGE0:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K0]]:_(s3), [[K1]]:_(s3), [[K2]]:_(s3) 988 CHECK-NEXT: [[MERGE1:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K3]]:_(s3), [[K4]]:_(s3), [[K5]]:_(s3) 989 CHECK-NEXT: [[MERGE2:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K6]]:_(s3), [[K7]]:_(s3), [[IMPDEF0]]:_(s3) 990 CHECK-NEXT: [[MERGE3:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE0]]:_(s9), [[MERGE1]]:_(s9), [[MERGE2]]:_(s9) 991 CHECK-NEXT: (s24) = G_TRUNC [[MERGE3]]:_(s27) 992 993 994 CHECK: [[K8:%[0-9]+]]:_(s3) = G_CONSTANT i3 0 995 CHECK-NEXT: [[K9:%[0-9]+]]:_(s3) = G_CONSTANT i3 1 996 CHECK-NEXT: [[K10:%[0-9]+]]:_(s3) = G_CONSTANT i3 2 997 CHECK-NEXT: [[K11:%[0-9]+]]:_(s3) = G_CONSTANT i3 3 998 CHECK-NEXT: [[K12:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4 999 CHECK-NEXT: [[K13:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3 1000 CHECK-NEXT: [[K14:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2 1001 CHECK-NEXT: [[IMPDEF1:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF 1002 CHECK-NEXT: [[MERGE4:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K8]]:_(s3), [[K9]]:_(s3), [[K10]]:_(s3) 1003 CHECK-NEXT: [[MERGE5:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K11]]:_(s3), [[K12]]:_(s3), [[K13]]:_(s3) 1004 CHECK-NEXT: [[MERGE6:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K14]]:_(s3), [[IMPDEF1]]:_(s3), [[IMPDEF1]]:_(s3) 1005 CHECK-NEXT: [[MERGE7:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE4]]:_(s9), [[MERGE5]]:_(s9), [[MERGE6]]:_(s9) 1006 CHECK-NEXT: (s21) = G_TRUNC [[MERGE7]]:_(s27) 1007 1008 1009 CHECK: [[K15:%[0-9]+]]:_(s8) = G_CONSTANT i8 0 1010 CHECK-NEXT: [[K16:%[0-9]+]]:_(s8) = G_CONSTANT i8 1 1011 CHECK-NEXT: [[ZEXT_K15:[0-9]+]]:_(s32) = G_ZEXT [[K15]]:_(s8) 1012 CHECK-NEXT: [[ZEXT_K16:[0-9]+]]:_(s32) = G_ZEXT [[K16]]:_(s8) 1013 [[K16:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 1014 [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ZEXT_K16]]:_, [[K16]]:_(s32) 1015 [[OR:%[0-9]+]]:_(s32) = G_OR [[ZEXT_K16]]:_, [[SHL]]:_ 1016 (s16) = G_TRUNC [[OR]]:_(s32) 1017 )"; 1018 1019 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1020 } 1021 1022 TEST_F(GISelMITest, WidenScalarMergeValuesPointer) { 1023 if (!TM) 1024 return; 1025 1026 DefineLegalizerInfo(A, {}); 1027 1028 AInfo Info(MF->getSubtarget()); 1029 DummyGISelObserver Observer; 1030 LegalizerHelper Helper(*MF, Info, Observer, B); 1031 B.setInsertPt(*EntryMBB, EntryMBB->end()); 1032 1033 const LLT S32 = LLT::scalar(32); 1034 const LLT S64 = LLT::scalar(64); 1035 const LLT P0 = LLT::pointer(0, 64); 1036 1037 auto Lo = B.buildTrunc(S32, Copies[0]); 1038 auto Hi = B.buildTrunc(S32, Copies[1]); 1039 1040 auto Merge = B.buildMerge(P0, {Lo.getReg(0), Hi.getReg(0)}); 1041 1042 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1043 Helper.widenScalar(*Merge, 1, S64)); 1044 1045 auto CheckStr = R"( 1046 CHECK: [[TRUNC0:%[0-9]+]]:_(s32) = G_TRUNC 1047 CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC 1048 CHECK: [[ZEXT_TRUNC0:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC0]] 1049 CHECK: [[ZEXT_TRUNC1:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC1]] 1050 CHECK: [[SHIFT_AMT:%[0-9]+]]:_(s64) = G_CONSTANT i64 32 1051 CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT_TRUNC1]]:_, [[SHIFT_AMT]] 1052 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[ZEXT_TRUNC0]]:_, [[SHL]] 1053 CHECK: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[OR]]:_(s64) 1054 )"; 1055 1056 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1057 } 1058 1059 TEST_F(GISelMITest, WidenSEXTINREG) { 1060 if (!TM) 1061 return; 1062 1063 // Declare your legalization info 1064 DefineLegalizerInfo(A, { 1065 getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); 1066 }); 1067 // Build Instr 1068 auto MIB = B.buildInstr( 1069 TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)}, 1070 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}), 1071 uint64_t(8)}); 1072 AInfo Info(MF->getSubtarget()); 1073 DummyGISelObserver Observer; 1074 LegalizerHelper Helper(*MF, Info, Observer, B); 1075 // Perform Legalization 1076 ASSERT_TRUE(Helper.widenScalar(*MIB, 0, LLT::scalar(64)) == 1077 LegalizerHelper::LegalizeResult::Legalized); 1078 1079 auto CheckStr = R"( 1080 CHECK: [[T0:%[0-9]+]]:_(s32) = G_TRUNC 1081 CHECK: [[T1:%[0-9]+]]:_(s64) = G_ANYEXT [[T0]]:_(s32) 1082 CHECK: [[T2:%[0-9]+]]:_(s64) = G_SEXT_INREG [[T1]]:_, 8 1083 CHECK: [[T3:%[0-9]+]]:_(s32) = G_TRUNC [[T2]]:_(s64) 1084 )"; 1085 1086 // Check 1087 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 1088 } 1089 1090 TEST_F(GISelMITest, NarrowSEXTINREG) { 1091 if (!TM) 1092 return; 1093 1094 // Declare your legalization info, these aren't actually relevant to the test. 1095 DefineLegalizerInfo(A, { 1096 getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); 1097 }); 1098 // Build Instr 1099 auto MIB = B.buildInstr( 1100 TargetOpcode::G_SEXT_INREG, {LLT::scalar(16)}, 1101 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(16)}, {Copies[0]}), 1102 uint64_t(8)}); 1103 AInfo Info(MF->getSubtarget()); 1104 DummyGISelObserver Observer; 1105 LegalizerHelper Helper(*MF, Info, Observer, B); 1106 // Perform Legalization 1107 ASSERT_TRUE(Helper.narrowScalar(*MIB, 0, LLT::scalar(10)) == 1108 LegalizerHelper::LegalizeResult::Legalized); 1109 1110 auto CheckStr = R"( 1111 CHECK: [[T0:%[0-9]+]]:_(s16) = G_TRUNC 1112 CHECK: [[T1:%[0-9]+]]:_(s10) = G_TRUNC [[T0]]:_(s16) 1113 CHECK: [[T2:%[0-9]+]]:_(s10) = G_SEXT_INREG [[T1]]:_, 8 1114 CHECK: [[T3:%[0-9]+]]:_(s16) = G_SEXT [[T2]]:_(s10) 1115 )"; 1116 1117 // Check 1118 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 1119 } 1120 1121 TEST_F(GISelMITest, NarrowSEXTINREG2) { 1122 if (!TM) 1123 return; 1124 1125 // Declare your legalization info, these aren't actually relevant to the test. 1126 DefineLegalizerInfo( 1127 A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); }); 1128 // Build Instr 1129 auto MIB = B.buildInstr( 1130 TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)}, 1131 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}), 1132 uint64_t(9)}); 1133 AInfo Info(MF->getSubtarget()); 1134 DummyGISelObserver Observer; 1135 LegalizerHelper Helper(*MF, Info, Observer, B); 1136 // Perform Legalization 1137 ASSERT_TRUE(Helper.narrowScalar(*MIB, 0, LLT::scalar(8)) == 1138 LegalizerHelper::LegalizeResult::Legalized); 1139 1140 auto CheckStr = R"( 1141 CHECK: [[T0:%[0-9]+]]:_(s32) = G_TRUNC 1142 CHECK: [[T1:%[0-9]+]]:_(s8), [[T2:%[0-9]+]]:_(s8), [[T3:%[0-9]+]]:_(s8), [[T4:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[T0]]:_(s32) 1143 CHECK: [[CST2:%[0-9]+]]:_(s8) = G_CONSTANT i8 7 1144 CHECK: [[T5:%[0-9]+]]:_(s8) = G_SEXT_INREG [[T2]]:_, 1 1145 CHECK: [[T6:%[0-9]+]]:_(s8) = G_ASHR [[T5]]:_, [[CST2]]:_ 1146 CHECK: [[T7:%[0-9]+]]:_(s32) = G_MERGE_VALUES [[T1]]:_(s8), [[T5]]:_(s8), [[T6]]:_(s8), [[T6]]:_(s8) 1147 )"; 1148 1149 // Check 1150 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 1151 } 1152 1153 TEST_F(GISelMITest, LowerSEXTINREG) { 1154 if (!TM) 1155 return; 1156 1157 // Declare your legalization info, these aren't actually relevant to the test. 1158 DefineLegalizerInfo( 1159 A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); }); 1160 // Build Instr 1161 auto MIB = B.buildInstr( 1162 TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)}, 1163 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}), 1164 uint64_t(8)}); 1165 AInfo Info(MF->getSubtarget()); 1166 DummyGISelObserver Observer; 1167 LegalizerHelper Helper(*MF, Info, Observer, B); 1168 // Perform Legalization 1169 ASSERT_TRUE(Helper.lower(*MIB, 0, LLT()) == 1170 LegalizerHelper::LegalizeResult::Legalized); 1171 1172 auto CheckStr = R"( 1173 CHECK: [[T1:%[0-9]+]]:_(s32) = G_TRUNC 1174 CHECK: [[CST:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 1175 CHECK: [[T2:%[0-9]+]]:_(s32) = G_SHL [[T1]]:_, [[CST]]:_ 1176 CHECK: [[T3:%[0-9]+]]:_(s32) = G_ASHR [[T2]]:_, [[CST]]:_ 1177 )"; 1178 1179 // Check 1180 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 1181 } 1182 } // namespace 1183