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