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