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 #include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h" 12 13 using namespace LegalizeActions; 14 using namespace LegalizeMutations; 15 using namespace LegalityPredicates; 16 17 namespace { 18 19 class DummyGISelObserver : public GISelChangeObserver { 20 public: 21 void changingInstr(MachineInstr &MI) override {} 22 void changedInstr(MachineInstr &MI) override {} 23 void createdInstr(MachineInstr &MI) override {} 24 void erasingInstr(MachineInstr &MI) override {} 25 }; 26 27 // Test G_ROTL/G_ROTR lowering. 28 TEST_F(AArch64GISelMITest, LowerRotates) { 29 setUp(); 30 if (!TM) 31 return; 32 33 // Declare your legalization info 34 DefineLegalizerInfo(A, { 35 getActionDefinitionsBuilder({G_ROTR, G_ROTL}).lower(); }); 36 37 LLT S32 = LLT::scalar(32); 38 auto Src = B.buildTrunc(S32, Copies[0]); 39 auto Amt = B.buildTrunc(S32, Copies[1]); 40 auto ROTR = B.buildInstr(TargetOpcode::G_ROTR, {S32}, {Src, Amt}); 41 auto ROTL = B.buildInstr(TargetOpcode::G_ROTL, {S32}, {Src, Amt}); 42 43 AInfo Info(MF->getSubtarget()); 44 DummyGISelObserver Observer; 45 LegalizerHelper Helper(*MF, Info, Observer, B); 46 // Perform Legalization 47 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 48 Helper.lower(*ROTR, 0, S32)); 49 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 50 Helper.lower(*ROTL, 0, S32)); 51 52 auto CheckStr = R"( 53 ; Check G_ROTR 54 CHECK: [[SRC:%[0-9]+]]:_(s32) = G_TRUNC 55 CHECK: [[AMT:%[0-9]+]]:_(s32) = G_TRUNC 56 CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 57 CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 31 58 CHECK: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[C]]:_, [[AMT]]:_ 59 CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[AMT]]:_, [[C1]]:_ 60 CHECK: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[SRC]]:_, [[AND]]:_(s32) 61 CHECK: [[AND1:%[0-9]+]]:_(s32) = G_AND [[SUB]]:_, [[C1]]:_ 62 CHECK: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[SRC]]:_, [[AND1]]:_(s32) 63 CHECK: G_OR [[LSHR]]:_, [[SHL]]:_ 64 65 ; Check G_ROTL 66 CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 67 CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 31 68 CHECK: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[C]]:_, [[AMT]]:_ 69 CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[AMT]]:_, [[C1]]:_ 70 CHECK: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[SRC]]:_, [[AND]]:_(s32) 71 CHECK: [[AND1:%[0-9]+]]:_(s32) = G_AND [[SUB]]:_, [[C1]]:_ 72 CHECK: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[SRC]]:_, [[AND1]]:_(s32) 73 CHECK: G_OR [[SHL]]:_, [[LSHR]]:_ 74 )"; 75 76 // Check 77 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 78 } 79 80 // Test G_ROTL/G_ROTR non-pow2 lowering. 81 TEST_F(AArch64GISelMITest, LowerRotatesNonPow2) { 82 setUp(); 83 if (!TM) 84 return; 85 86 // Declare your legalization info 87 DefineLegalizerInfo(A, { 88 getActionDefinitionsBuilder({G_ROTR, G_ROTL}).lower(); }); 89 90 LLT S24 = LLT::scalar(24); 91 auto Src = B.buildTrunc(S24, Copies[0]); 92 auto Amt = B.buildTrunc(S24, Copies[1]); 93 auto ROTR = B.buildInstr(TargetOpcode::G_ROTR, {S24}, {Src, Amt}); 94 auto ROTL = B.buildInstr(TargetOpcode::G_ROTL, {S24}, {Src, Amt}); 95 96 AInfo Info(MF->getSubtarget()); 97 DummyGISelObserver Observer; 98 LegalizerHelper Helper(*MF, Info, Observer, B); 99 // Perform Legalization 100 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 101 Helper.lower(*ROTR, 0, S24)); 102 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 103 Helper.lower(*ROTL, 0, S24)); 104 105 auto CheckStr = R"( 106 ; Check G_ROTR 107 CHECK: [[SRC:%[0-9]+]]:_(s24) = G_TRUNC 108 CHECK: [[AMT:%[0-9]+]]:_(s24) = G_TRUNC 109 CHECK: [[C:%[0-9]+]]:_(s24) = G_CONSTANT i24 0 110 CHECK: [[C1:%[0-9]+]]:_(s24) = G_CONSTANT i24 23 111 CHECK: [[C2:%[0-9]+]]:_(s24) = G_CONSTANT i24 24 112 CHECK: [[UREM:%[0-9]+]]:_(s24) = G_UREM [[AMT]]:_, [[C2]]:_ 113 CHECK: [[LSHR:%[0-9]+]]:_(s24) = G_LSHR [[SRC]]:_, [[UREM]]:_(s24) 114 CHECK: [[SUB:%[0-9]+]]:_(s24) = G_SUB [[C1]]:_, [[UREM]]:_ 115 CHECK: [[C4:%[0-9]+]]:_(s24) = G_CONSTANT i24 1 116 CHECK: [[SHL:%[0-9]+]]:_(s24) = G_SHL [[SRC]]:_, [[C4]]:_(s24) 117 CHECK: [[SHL2:%[0-9]+]]:_(s24) = G_SHL [[SHL]]:_, [[SUB]]:_(s24) 118 CHECK: G_OR [[LSHR]]:_, [[SHL2]]:_ 119 120 ; Check G_ROTL 121 CHECK: [[C:%[0-9]+]]:_(s24) = G_CONSTANT i24 0 122 CHECK: [[C1:%[0-9]+]]:_(s24) = G_CONSTANT i24 23 123 CHECK: [[C2:%[0-9]+]]:_(s24) = G_CONSTANT i24 24 124 CHECK: [[UREM:%[0-9]+]]:_(s24) = G_UREM [[AMT]]:_, [[C2]]:_ 125 CHECK: [[SHL:%[0-9]+]]:_(s24) = G_SHL [[SRC]]:_, [[UREM]]:_(s24) 126 CHECK: [[SUB:%[0-9]+]]:_(s24) = G_SUB [[C1]]:_, [[UREM]]:_ 127 CHECK: [[C4:%[0-9]+]]:_(s24) = G_CONSTANT i24 1 128 CHECK: [[LSHR:%[0-9]+]]:_(s24) = G_LSHR [[SRC]]:_, [[C4]]:_(s24) 129 CHECK: [[LSHR2:%[0-9]+]]:_(s24) = G_LSHR [[LSHR]]:_, [[SUB]]:_(s24) 130 CHECK: G_OR [[SHL]]:_, [[LSHR2]]:_ 131 )"; 132 133 // Check 134 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 135 } 136 137 // Test vector G_ROTR lowering. 138 TEST_F(AArch64GISelMITest, LowerRotatesVector) { 139 setUp(); 140 if (!TM) 141 return; 142 143 // Declare your legalization info 144 DefineLegalizerInfo(A, { 145 getActionDefinitionsBuilder({G_ROTR, G_ROTL}).lower(); }); 146 147 LLT S32 = LLT::scalar(32); 148 LLT V4S32 = LLT::fixed_vector(4, S32); 149 auto SrcTrunc = B.buildTrunc(S32, Copies[0]); 150 auto Src = B.buildSplatVector(V4S32, SrcTrunc); 151 auto AmtTrunc = B.buildTrunc(S32, Copies[1]); 152 auto Amt = B.buildSplatVector(V4S32, AmtTrunc); 153 auto ROTR = B.buildInstr(TargetOpcode::G_ROTR, {V4S32}, {Src, Amt}); 154 155 AInfo Info(MF->getSubtarget()); 156 DummyGISelObserver Observer; 157 LegalizerHelper Helper(*MF, Info, Observer, B); 158 // Perform Legalization 159 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 160 Helper.lower(*ROTR, 0, V4S32)); 161 162 auto CheckStr = R"( 163 CHECK: [[SRCTRUNC:%[0-9]+]]:_(s32) = G_TRUNC 164 CHECK: [[SRC:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[SRCTRUNC]] 165 CHECK: [[AMTTRUNC:%[0-9]+]]:_(s32) = G_TRUNC 166 CHECK: [[AMT:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[AMTTRUNC]] 167 CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 168 CHECK: [[ZERO:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]] 169 CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 31 170 CHECK: [[VEC31:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C1]] 171 CHECK: [[SUB:%[0-9]+]]:_(<4 x s32>) = G_SUB [[ZERO]]:_, [[AMT]]:_ 172 CHECK: [[AND:%[0-9]+]]:_(<4 x s32>) = G_AND [[AMT]]:_, [[VEC31]]:_ 173 CHECK: [[LSHR:%[0-9]+]]:_(<4 x s32>) = G_LSHR [[SRC]]:_, [[AND]]:_(<4 x s32>) 174 CHECK: [[AND1:%[0-9]+]]:_(<4 x s32>) = G_AND [[SUB]]:_, [[VEC31]]:_ 175 CHECK: [[SHL:%[0-9]+]]:_(<4 x s32>) = G_SHL [[SRC]]:_, [[AND1]]:_(<4 x s32>) 176 CHECK: G_OR [[LSHR]]:_, [[SHL]]:_ 177 )"; 178 179 // Check 180 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 181 } 182 183 // Test CTTZ expansion when CTTZ_ZERO_UNDEF is legal or custom, 184 // in which case it becomes CTTZ_ZERO_UNDEF with select. 185 TEST_F(AArch64GISelMITest, LowerBitCountingCTTZ0) { 186 setUp(); 187 if (!TM) 188 return; 189 190 // Declare your legalization info 191 DefineLegalizerInfo(A, { 192 getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s32, s64}}); 193 }); 194 // Build Instr 195 auto MIBCTTZ = 196 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(32)}, {Copies[0]}); 197 AInfo Info(MF->getSubtarget()); 198 DummyGISelObserver Observer; 199 LegalizerHelper Helper(*MF, Info, Observer, B); 200 // Perform Legalization 201 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 202 Helper.lower(*MIBCTTZ, 0, LLT::scalar(64))); 203 204 auto CheckStr = R"( 205 CHECK: [[CZU:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF %0 206 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 207 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]] 208 CHECK: [[SIXTY4:%[0-9]+]]:_(s32) = G_CONSTANT i32 64 209 CHECK: [[SEL:%[0-9]+]]:_(s32) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]] 210 )"; 211 212 // Check 213 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 214 } 215 216 // CTTZ expansion in terms of CTLZ 217 TEST_F(AArch64GISelMITest, LowerBitCountingCTTZ1) { 218 setUp(); 219 if (!TM) 220 return; 221 222 // Declare your legalization info 223 DefineLegalizerInfo(A, { 224 getActionDefinitionsBuilder(G_CTLZ).legalFor({{s64, s64}}); 225 }); 226 // Build Instr 227 auto MIBCTTZ = 228 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]}); 229 AInfo Info(MF->getSubtarget()); 230 DummyGISelObserver Observer; 231 LegalizerHelper Helper(*MF, Info, Observer, B); 232 // Perform Legalization 233 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) == 234 LegalizerHelper::LegalizeResult::Legalized); 235 236 auto CheckStr = R"( 237 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1 238 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]] 239 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]] 240 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_ 241 CHECK: [[CST64:%[0-9]+]]:_(s64) = G_CONSTANT i64 64 242 CHECK: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[AND1]]:_ 243 CHECK: G_SUB [[CST64]]:_, [[CTLZ]]:_ 244 )"; 245 246 // Check 247 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 248 } 249 250 // CTLZ scalar narrowing 251 TEST_F(AArch64GISelMITest, NarrowScalarCTLZ) { 252 setUp(); 253 if (!TM) 254 return; 255 256 // Declare your legalization info 257 DefineLegalizerInfo(A, { 258 getActionDefinitionsBuilder(G_CTLZ).legalFor({{s32, s32}}); 259 }); 260 // Build Instr 261 auto CTLZ = 262 B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(32)}, {Copies[0]}); 263 AInfo Info(MF->getSubtarget()); 264 DummyGISelObserver Observer; 265 LegalizerHelper Helper(*MF, Info, Observer, B); 266 // Perform Legalization 267 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 268 Helper.narrowScalar(*CTLZ, 1, LLT::scalar(32))); 269 270 auto CheckStr = R"( 271 CHECK: [[UNMERGE_LO:%[0-9]+]]:_(s32), [[UNMERGE_HI:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES %0:_(s64) 272 CHECK: [[ZERO:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 273 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[UNMERGE_HI]]:_(s32), [[ZERO]]:_ 274 CHECK: [[CTLZ_LO:%[0-9]+]]:_(s32) = G_CTLZ [[UNMERGE_LO]]:_(s32) 275 CHECK: [[THIRTYTWO:%[0-9]+]]:_(s32) = G_CONSTANT i32 32 276 CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[CTLZ_LO]]:_, [[THIRTYTWO]]:_ 277 CHECK: [[CTLZ_HI:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[UNMERGE_HI]]:_(s32) 278 CHECK: %{{[0-9]+}}:_(s32) = G_SELECT [[CMP]]:_(s1), [[ADD]]:_, [[CTLZ_HI]]:_ 279 )"; 280 281 // Check 282 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 283 } 284 285 // CTTZ scalar narrowing 286 TEST_F(AArch64GISelMITest, NarrowScalarCTTZ) { 287 setUp(); 288 if (!TM) 289 return; 290 291 // Declare your legalization info 292 DefineLegalizerInfo(A, { 293 getActionDefinitionsBuilder(G_CTTZ).legalFor({{s32, s64}}); 294 }); 295 // Build Instr 296 auto CTTZ = 297 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(32)}, {Copies[0]}); 298 AInfo Info(MF->getSubtarget()); 299 DummyGISelObserver Observer; 300 LegalizerHelper Helper(*MF, Info, Observer, B); 301 // Perform Legalization 302 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 303 Helper.narrowScalar(*CTTZ, 1, LLT::scalar(32))); 304 305 auto CheckStr = R"( 306 CHECK: [[UNMERGE_LO:%[0-9]+]]:_(s32), [[UNMERGE_HI:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES %0:_(s64) 307 CHECK: [[ZERO:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 308 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[UNMERGE_LO]]:_(s32), [[ZERO]]:_ 309 CHECK: [[CTTZ_HI:%[0-9]+]]:_(s32) = G_CTTZ [[UNMERGE_HI]]:_(s32) 310 CHECK: [[THIRTYTWO:%[0-9]+]]:_(s32) = G_CONSTANT i32 32 311 CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[CTTZ_HI]]:_, [[THIRTYTWO]]:_ 312 CHECK: [[CTTZ_LO:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[UNMERGE_LO]]:_(s32) 313 CHECK: %{{[0-9]+}}:_(s32) = G_SELECT [[CMP]]:_(s1), [[ADD]]:_, [[CTTZ_LO]]:_ 314 )"; 315 316 // Check 317 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 318 } 319 320 // CTTZ expansion in terms of CTPOP 321 TEST_F(AArch64GISelMITest, LowerBitCountingCTTZ2) { 322 setUp(); 323 if (!TM) 324 return; 325 326 // Declare your legalization info 327 DefineLegalizerInfo(A, { 328 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s64, s64}}); 329 }); 330 // Build 331 auto MIBCTTZ = 332 B.buildInstr(TargetOpcode::G_CTTZ, {LLT::scalar(64)}, {Copies[0]}); 333 AInfo Info(MF->getSubtarget()); 334 DummyGISelObserver Observer; 335 LegalizerHelper Helper(*MF, Info, Observer, B); 336 337 B.setInsertPt(*EntryMBB, MIBCTTZ->getIterator()); 338 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) == 339 LegalizerHelper::LegalizeResult::Legalized); 340 341 auto CheckStr = R"( 342 CHECK: [[NEG1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1 343 CHECK: [[NOT:%[0-9]+]]:_(s64) = G_XOR %0:_, [[NEG1]] 344 CHECK: [[SUB1:%[0-9]+]]:_(s64) = G_ADD %0:_, [[NEG1]] 345 CHECK: [[AND1:%[0-9]+]]:_(s64) = G_AND [[NOT]]:_, [[SUB1]]:_ 346 CHECK: [[POP:%[0-9]+]]:_(s64) = G_CTPOP [[AND1]] 347 )"; 348 349 // Check 350 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 351 } 352 353 // CTPOP widening. 354 TEST_F(AArch64GISelMITest, WidenBitCountingCTPOP1) { 355 setUp(); 356 if (!TM) 357 return; 358 359 // Declare your legalization info 360 DefineLegalizerInfo(A, { 361 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}}); 362 }); 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 MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s16}, {MIBTrunc}); 370 AInfo Info(MF->getSubtarget()); 371 DummyGISelObserver Observer; 372 LegalizerHelper Helper(*MF, Info, Observer, B); 373 B.setInstr(*MIBCTPOP); 374 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 375 Helper.widenScalar(*MIBCTPOP, 1, s16)); 376 377 auto CheckStr = R"( 378 CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64) 379 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8) 380 CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]] 381 CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY [[CTPOP]]:_(s16) 382 )"; 383 384 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 385 } 386 387 // Test a strange case where the result is wider than the source 388 TEST_F(AArch64GISelMITest, WidenBitCountingCTPOP2) { 389 setUp(); 390 if (!TM) 391 return; 392 393 // Declare your legalization info 394 DefineLegalizerInfo(A, { 395 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s32, s16}}); 396 }); 397 398 // Build 399 // Trunc it to s8. 400 LLT s8{LLT::scalar(8)}; 401 LLT s16{LLT::scalar(16)}; 402 LLT s32{LLT::scalar(32)}; 403 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 404 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s32}, {MIBTrunc}); 405 AInfo Info(MF->getSubtarget()); 406 DummyGISelObserver Observer; 407 LegalizerHelper Helper(*MF, Info, Observer, B); 408 B.setInstr(*MIBCTPOP); 409 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 410 Helper.widenScalar(*MIBCTPOP, 1, s16)); 411 412 auto CheckStr = R"( 413 CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC %0:_(s64) 414 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC]]:_(s8) 415 CHECK: [[CTPOP:%[0-9]+]]:_(s16) = G_CTPOP [[ZEXT]] 416 CHECK: [[COPY:%[0-9]+]]:_(s32) = G_ZEXT [[CTPOP]]:_(s16) 417 )"; 418 419 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 420 } 421 422 // CTTZ_ZERO_UNDEF expansion in terms of CTTZ 423 TEST_F(AArch64GISelMITest, LowerBitCountingCTTZ3) { 424 setUp(); 425 if (!TM) 426 return; 427 428 // Declare your legalization info 429 DefineLegalizerInfo(A, { 430 getActionDefinitionsBuilder(G_CTTZ).legalFor({{s64, s64}}); 431 }); 432 // Build 433 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, 434 {LLT::scalar(64)}, {Copies[0]}); 435 AInfo Info(MF->getSubtarget()); 436 DummyGISelObserver Observer; 437 LegalizerHelper Helper(*MF, Info, Observer, B); 438 EXPECT_TRUE(Helper.lower(*MIBCTTZ, 0, LLT::scalar(64)) == 439 LegalizerHelper::LegalizeResult::Legalized); 440 441 auto CheckStr = R"( 442 CHECK: CTTZ 443 )"; 444 445 // Check 446 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 447 } 448 449 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF 450 TEST_F(AArch64GISelMITest, LowerBitCountingCTLZ0) { 451 setUp(); 452 if (!TM) 453 return; 454 455 // Declare your legalization info 456 DefineLegalizerInfo(A, { 457 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s64, s64}}); 458 }); 459 // Build 460 auto MIBCTLZ = 461 B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(64)}, {Copies[0]}); 462 AInfo Info(MF->getSubtarget()); 463 DummyGISelObserver Observer; 464 LegalizerHelper Helper(*MF, Info, Observer, B); 465 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, LLT::scalar(64)) == 466 LegalizerHelper::LegalizeResult::Legalized); 467 468 auto CheckStr = R"( 469 CHECK: [[CZU:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF %0 470 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 471 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]] 472 CHECK: [[SIXTY4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64 473 CHECK: [[SEL:%[0-9]+]]:_(s64) = G_SELECT [[CMP]]:_(s1), [[SIXTY4]]:_, [[CZU]] 474 )"; 475 476 // Check 477 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 478 } 479 480 // CTLZ expansion in terms of CTLZ_ZERO_UNDEF if the latter is a libcall 481 TEST_F(AArch64GISelMITest, LowerBitCountingCTLZLibcall) { 482 setUp(); 483 if (!TM) 484 return; 485 486 // Declare your legalization info 487 DefineLegalizerInfo(A, { 488 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).libcallFor({{s32, s64}}); 489 }); 490 // Build 491 auto MIBCTLZ = 492 B.buildInstr(TargetOpcode::G_CTLZ, {LLT::scalar(32)}, {Copies[0]}); 493 AInfo Info(MF->getSubtarget()); 494 DummyGISelObserver Observer; 495 LegalizerHelper Helper(*MF, Info, Observer, B); 496 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 497 Helper.lower(*MIBCTLZ, 0, LLT::scalar(32))); 498 499 auto CheckStr = R"( 500 CHECK: [[CZU:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF %0 501 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 502 CHECK: [[CMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), %0:_(s64), [[ZERO]] 503 CHECK: [[THIRTY2:%[0-9]+]]:_(s32) = G_CONSTANT i32 64 504 CHECK: [[SEL:%[0-9]+]]:_(s32) = G_SELECT [[CMP]]:_(s1), [[THIRTY2]]:_, [[CZU]] 505 )"; 506 507 // Check 508 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 509 } 510 511 // CTLZ expansion 512 TEST_F(AArch64GISelMITest, LowerBitCountingCTLZ1) { 513 setUp(); 514 if (!TM) 515 return; 516 517 // Declare your legalization info 518 DefineLegalizerInfo(A, { 519 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s8, s8}}); 520 }); 521 // Build 522 // Trunc it to s8. 523 LLT s8{LLT::scalar(8)}; 524 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 525 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc}); 526 AInfo Info(MF->getSubtarget()); 527 DummyGISelObserver Observer; 528 LegalizerHelper Helper(*MF, Info, Observer, B); 529 EXPECT_TRUE(Helper.lower(*MIBCTLZ, 0, s8) == 530 LegalizerHelper::LegalizeResult::Legalized); 531 532 auto CheckStr = R"( 533 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 534 CHECK: [[Cst1:%[0-9]+]]:_(s8) = G_CONSTANT i8 1 535 CHECK: [[Sh1:%[0-9]+]]:_(s8) = G_LSHR [[Trunc]]:_, [[Cst1]]:_ 536 CHECK: [[Or1:%[0-9]+]]:_(s8) = G_OR [[Trunc]]:_, [[Sh1]]:_ 537 CHECK: [[Cst2:%[0-9]+]]:_(s8) = G_CONSTANT i8 2 538 CHECK: [[Sh2:%[0-9]+]]:_(s8) = G_LSHR [[Or1]]:_, [[Cst2]]:_ 539 CHECK: [[Or2:%[0-9]+]]:_(s8) = G_OR [[Or1]]:_, [[Sh2]]:_ 540 CHECK: [[Cst4:%[0-9]+]]:_(s8) = G_CONSTANT i8 4 541 CHECK: [[Sh4:%[0-9]+]]:_(s8) = G_LSHR [[Or2]]:_, [[Cst4]]:_ 542 CHECK: [[Or4:%[0-9]+]]:_(s8) = G_OR [[Or2]]:_, [[Sh4]]:_ 543 CHECK: [[CTPOP:%[0-9]+]]:_(s8) = G_CTPOP [[Or4]]:_ 544 CHECK: [[Len:%[0-9]+]]:_(s8) = G_CONSTANT i8 8 545 CHECK: [[Sub:%[0-9]+]]:_(s8) = G_SUB [[Len]]:_, [[CTPOP]]:_ 546 )"; 547 548 // Check 549 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 550 } 551 552 // CTLZ widening. 553 TEST_F(AArch64GISelMITest, WidenBitCountingCTLZ) { 554 setUp(); 555 if (!TM) 556 return; 557 558 // Declare your legalization info 559 DefineLegalizerInfo(A, { 560 getActionDefinitionsBuilder(G_CTLZ).legalFor({{s16, s16}}); 561 }); 562 // Build 563 // Trunc it to s8. 564 LLT s8{LLT::scalar(8)}; 565 LLT s16{LLT::scalar(16)}; 566 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 567 auto MIBCTLZ = B.buildInstr(TargetOpcode::G_CTLZ, {s8}, {MIBTrunc}); 568 AInfo Info(MF->getSubtarget()); 569 DummyGISelObserver Observer; 570 LegalizerHelper Helper(*MF, Info, Observer, B); 571 EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ, 1, s16) == 572 LegalizerHelper::LegalizeResult::Legalized); 573 574 auto CheckStr = R"( 575 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 576 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 577 CHECK: [[Ctlz:%[0-9]+]]:_(s16) = G_CTLZ [[Zext]] 578 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 579 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[Ctlz]]:_, [[Cst8]]:_ 580 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]] 581 )"; 582 583 // Check 584 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 585 } 586 587 // CTLZ_ZERO_UNDEF widening. 588 TEST_F(AArch64GISelMITest, WidenBitCountingCTLZZeroUndef) { 589 setUp(); 590 if (!TM) 591 return; 592 593 // Declare your legalization info 594 DefineLegalizerInfo(A, { 595 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF).legalFor({{s16, s16}}); 596 }); 597 // Build 598 // Trunc it to s8. 599 LLT s8{LLT::scalar(8)}; 600 LLT s16{LLT::scalar(16)}; 601 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 602 auto MIBCTLZ_ZU = 603 B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {s8}, {MIBTrunc}); 604 AInfo Info(MF->getSubtarget()); 605 DummyGISelObserver Observer; 606 LegalizerHelper Helper(*MF, Info, Observer, B); 607 EXPECT_TRUE(Helper.widenScalar(*MIBCTLZ_ZU, 1, s16) == 608 LegalizerHelper::LegalizeResult::Legalized); 609 610 auto CheckStr = R"( 611 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 612 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 613 CHECK: [[CtlzZu:%[0-9]+]]:_(s16) = G_CTLZ_ZERO_UNDEF [[Zext]] 614 CHECK: [[Cst8:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 615 CHECK: [[Sub:%[0-9]+]]:_(s16) = G_SUB [[CtlzZu]]:_, [[Cst8]]:_ 616 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Sub]] 617 )"; 618 619 // Check 620 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 621 } 622 623 // CTPOP widening. 624 TEST_F(AArch64GISelMITest, WidenBitCountingCTPOP) { 625 setUp(); 626 if (!TM) 627 return; 628 629 // Declare your legalization info 630 DefineLegalizerInfo(A, { 631 getActionDefinitionsBuilder(G_CTPOP).legalFor({{s16, s16}}); 632 }); 633 // Build 634 // Trunc it to s8. 635 LLT s8{LLT::scalar(8)}; 636 LLT s16{LLT::scalar(16)}; 637 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 638 auto MIBCTPOP = B.buildInstr(TargetOpcode::G_CTPOP, {s8}, {MIBTrunc}); 639 AInfo Info(MF->getSubtarget()); 640 DummyGISelObserver Observer; 641 LegalizerHelper Helper(*MF, Info, Observer, B); 642 EXPECT_TRUE(Helper.widenScalar(*MIBCTPOP, 1, s16) == 643 LegalizerHelper::LegalizeResult::Legalized); 644 645 auto CheckStr = R"( 646 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 647 CHECK: [[Zext:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 648 CHECK: [[Ctpop:%[0-9]+]]:_(s16) = G_CTPOP [[Zext]] 649 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Ctpop]] 650 )"; 651 652 // Check 653 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 654 } 655 656 // CTTZ_ZERO_UNDEF widening. 657 TEST_F(AArch64GISelMITest, WidenBitCountingCTTZ_ZERO_UNDEF) { 658 setUp(); 659 if (!TM) 660 return; 661 662 // Declare your legalization info 663 DefineLegalizerInfo(A, { 664 getActionDefinitionsBuilder(G_CTTZ_ZERO_UNDEF).legalFor({{s16, s16}}); 665 }); 666 // Build 667 // Trunc it to s8. 668 LLT s8{LLT::scalar(8)}; 669 LLT s16{LLT::scalar(16)}; 670 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 671 auto MIBCTTZ_ZERO_UNDEF = 672 B.buildInstr(TargetOpcode::G_CTTZ_ZERO_UNDEF, {s8}, {MIBTrunc}); 673 AInfo Info(MF->getSubtarget()); 674 DummyGISelObserver Observer; 675 LegalizerHelper Helper(*MF, Info, Observer, B); 676 EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ_ZERO_UNDEF, 1, s16) == 677 LegalizerHelper::LegalizeResult::Legalized); 678 679 auto CheckStr = R"( 680 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 681 CHECK: [[AnyExt:%[0-9]+]]:_(s16) = G_ANYEXT [[Trunc]] 682 CHECK: [[CttzZu:%[0-9]+]]:_(s16) = G_CTTZ_ZERO_UNDEF [[AnyExt]] 683 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[CttzZu]] 684 )"; 685 686 // Check 687 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 688 } 689 690 // CTTZ widening. 691 TEST_F(AArch64GISelMITest, WidenBitCountingCTTZ) { 692 setUp(); 693 if (!TM) 694 return; 695 696 // Declare your legalization info 697 DefineLegalizerInfo(A, { 698 getActionDefinitionsBuilder(G_CTTZ).legalFor({{s16, s16}}); 699 }); 700 // Build 701 // Trunc it to s8. 702 LLT s8{LLT::scalar(8)}; 703 LLT s16{LLT::scalar(16)}; 704 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 705 auto MIBCTTZ = B.buildInstr(TargetOpcode::G_CTTZ, {s8}, {MIBTrunc}); 706 AInfo Info(MF->getSubtarget()); 707 DummyGISelObserver Observer; 708 LegalizerHelper Helper(*MF, Info, Observer, B); 709 EXPECT_TRUE(Helper.widenScalar(*MIBCTTZ, 1, s16) == 710 LegalizerHelper::LegalizeResult::Legalized); 711 712 auto CheckStr = R"( 713 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 714 CHECK: [[AnyExt:%[0-9]+]]:_(s16) = G_ANYEXT [[Trunc]] 715 CHECK: [[Cst:%[0-9]+]]:_(s16) = G_CONSTANT i16 256 716 CHECK: [[Or:%[0-9]+]]:_(s16) = G_OR [[AnyExt]]:_, [[Cst]] 717 CHECK: [[Cttz:%[0-9]+]]:_(s16) = G_CTTZ_ZERO_UNDEF [[Or]] 718 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC [[Cttz]] 719 )"; 720 721 // Check 722 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 723 } 724 // UADDO widening. 725 TEST_F(AArch64GISelMITest, WidenUADDO) { 726 setUp(); 727 if (!TM) 728 return; 729 730 // Declare your legalization info 731 DefineLegalizerInfo(A, { 732 getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}}); 733 }); 734 // Build 735 // Trunc it to s8. 736 LLT s8{LLT::scalar(8)}; 737 LLT s16{LLT::scalar(16)}; 738 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 739 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); 740 auto MIBUAddO = 741 B.buildInstr(TargetOpcode::G_UADDO, {s8, CarryReg}, {MIBTrunc, MIBTrunc}); 742 AInfo Info(MF->getSubtarget()); 743 DummyGISelObserver Observer; 744 LegalizerHelper Helper(*MF, Info, Observer, B); 745 EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) == 746 LegalizerHelper::LegalizeResult::Legalized); 747 748 auto CheckStr = R"( 749 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 750 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 751 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 752 CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_ 753 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[ADD]] 754 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC1]] 755 CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[ZEXT]]:_ 756 CHECK: G_TRUNC [[ADD]] 757 )"; 758 759 // Check 760 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 761 } 762 763 // USUBO widening. 764 TEST_F(AArch64GISelMITest, WidenUSUBO) { 765 setUp(); 766 if (!TM) 767 return; 768 769 // Declare your legalization info 770 DefineLegalizerInfo(A, { 771 getActionDefinitionsBuilder(G_SUB).legalFor({{s16, s16}}); 772 }); 773 // Build 774 // Trunc it to s8. 775 LLT s8{LLT::scalar(8)}; 776 LLT s16{LLT::scalar(16)}; 777 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 778 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); 779 auto MIBUSUBO = 780 B.buildInstr(TargetOpcode::G_USUBO, {s8, CarryReg}, {MIBTrunc, MIBTrunc}); 781 AInfo Info(MF->getSubtarget()); 782 DummyGISelObserver Observer; 783 LegalizerHelper Helper(*MF, Info, Observer, B); 784 EXPECT_TRUE(Helper.widenScalar(*MIBUSUBO, 0, s16) == 785 LegalizerHelper::LegalizeResult::Legalized); 786 787 auto CheckStr = R"( 788 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 789 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 790 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 791 CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_ 792 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[SUB]] 793 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC1]] 794 CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[ZEXT]]:_ 795 CHECK: G_TRUNC [[SUB]] 796 )"; 797 798 // Check 799 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 800 } 801 802 // SADDO widening. 803 TEST_F(AArch64GISelMITest, WidenSADDO) { 804 setUp(); 805 if (!TM) 806 return; 807 808 // Declare your legalization info 809 DefineLegalizerInfo(A, { 810 getActionDefinitionsBuilder(G_ADD).legalFor({{s16, s16}}); 811 }); 812 // Build 813 // Trunc it to s8. 814 LLT s8{LLT::scalar(8)}; 815 LLT s16{LLT::scalar(16)}; 816 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 817 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); 818 auto MIBSAddO = 819 B.buildInstr(TargetOpcode::G_SADDO, {s8, CarryReg}, {MIBTrunc, MIBTrunc}); 820 AInfo Info(MF->getSubtarget()); 821 DummyGISelObserver Observer; 822 LegalizerHelper Helper(*MF, Info, Observer, B); 823 EXPECT_TRUE(Helper.widenScalar(*MIBSAddO, 0, s16) == 824 LegalizerHelper::LegalizeResult::Legalized); 825 826 auto CheckStr = R"( 827 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 828 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]] 829 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]] 830 CHECK: [[ADD:%[0-9]+]]:_(s16) = G_ADD [[LHS]]:_, [[RHS]]:_ 831 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[ADD]] 832 CHECK: [[SEXT:%[0-9]+]]:_(s16) = G_SEXT [[TRUNC1]] 833 CHECK: G_ICMP intpred(ne), [[ADD]]:_(s16), [[SEXT]]:_ 834 CHECK: G_TRUNC [[ADD]] 835 )"; 836 837 // Check 838 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 839 } 840 841 // SSUBO widening. 842 TEST_F(AArch64GISelMITest, WidenSSUBO) { 843 setUp(); 844 if (!TM) 845 return; 846 847 // Declare your legalization info 848 DefineLegalizerInfo(A, { 849 getActionDefinitionsBuilder(G_SUB).legalFor({{s16, s16}}); 850 }); 851 // Build 852 // Trunc it to s8. 853 LLT s8{LLT::scalar(8)}; 854 LLT s16{LLT::scalar(16)}; 855 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 856 unsigned CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); 857 auto MIBSSUBO = 858 B.buildInstr(TargetOpcode::G_SSUBO, {s8, CarryReg}, {MIBTrunc, MIBTrunc}); 859 AInfo Info(MF->getSubtarget()); 860 DummyGISelObserver Observer; 861 LegalizerHelper Helper(*MF, Info, Observer, B); 862 EXPECT_TRUE(Helper.widenScalar(*MIBSSUBO, 0, s16) == 863 LegalizerHelper::LegalizeResult::Legalized); 864 865 auto CheckStr = R"( 866 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 867 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]] 868 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]] 869 CHECK: [[SUB:%[0-9]+]]:_(s16) = G_SUB [[LHS]]:_, [[RHS]]:_ 870 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[SUB]] 871 CHECK: [[SEXT:%[0-9]+]]:_(s16) = G_SEXT [[TRUNC1]] 872 CHECK: G_ICMP intpred(ne), [[SUB]]:_(s16), [[SEXT]]:_ 873 CHECK: G_TRUNC [[SUB]] 874 )"; 875 876 // Check 877 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 878 } 879 880 TEST_F(AArch64GISelMITest, WidenUADDE) { 881 setUp(); 882 if (!TM) 883 return; 884 885 // Declare your legalization info 886 DefineLegalizerInfo(A, { 887 getActionDefinitionsBuilder(G_UADDE).legalFor({{s16, s16}}); 888 }); 889 // Build 890 // Trunc it to s8. 891 LLT s8{LLT::scalar(8)}; 892 LLT s16{LLT::scalar(16)}; 893 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 894 auto CarryIn = B.buildUndef(LLT::scalar(1)); 895 Register CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); 896 auto MIBUAddO = B.buildInstr(TargetOpcode::G_UADDE, {s8, CarryReg}, 897 {MIBTrunc, MIBTrunc, CarryIn}); 898 AInfo Info(MF->getSubtarget()); 899 DummyGISelObserver Observer; 900 LegalizerHelper Helper(*MF, Info, Observer, B); 901 EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) == 902 LegalizerHelper::LegalizeResult::Legalized); 903 904 const char *CheckStr = R"( 905 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 906 CHECK: [[Implicit:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF 907 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 908 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 909 CHECK: [[UADDE:%[0-9]+]]:_(s16), [[CARRY:%[0-9]+]]:_(s1) = G_UADDE [[LHS]]:_, [[RHS]]:_, [[Implicit]]:_ 910 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[UADDE]] 911 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC1]] 912 CHECK: G_ICMP intpred(ne), [[UADDE]]:_(s16), [[ZEXT]]:_ 913 CHECK: G_TRUNC [[UADDE]] 914 )"; 915 916 // Check 917 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 918 } 919 920 TEST_F(AArch64GISelMITest, WidenUSUBE) { 921 setUp(); 922 if (!TM) 923 return; 924 925 // Declare your legalization info 926 DefineLegalizerInfo(A, { 927 getActionDefinitionsBuilder(G_USUBE).legalFor({{s16, s16}}); 928 }); 929 // Build 930 // Trunc it to s8. 931 LLT s8{LLT::scalar(8)}; 932 LLT s16{LLT::scalar(16)}; 933 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 934 auto CarryIn = B.buildUndef(LLT::scalar(1)); 935 Register CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); 936 auto MIBUSUBE = B.buildInstr(TargetOpcode::G_USUBE, {s8, CarryReg}, 937 {MIBTrunc, MIBTrunc, CarryIn}); 938 AInfo Info(MF->getSubtarget()); 939 DummyGISelObserver Observer; 940 LegalizerHelper Helper(*MF, Info, Observer, B); 941 EXPECT_TRUE(Helper.widenScalar(*MIBUSUBE, 0, s16) == 942 LegalizerHelper::LegalizeResult::Legalized); 943 944 const char *CheckStr = R"( 945 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 946 CHECK: [[Implicit:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF 947 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 948 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_ZEXT [[Trunc]] 949 CHECK: [[USUBE:%[0-9]+]]:_(s16), [[CARRY:%[0-9]+]]:_(s1) = G_USUBE [[LHS]]:_, [[RHS]]:_, [[Implicit]]:_ 950 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[USUBE]] 951 CHECK: [[ZEXT:%[0-9]+]]:_(s16) = G_ZEXT [[TRUNC1]] 952 CHECK: G_ICMP intpred(ne), [[USUBE]]:_(s16), [[ZEXT]]:_ 953 CHECK: G_TRUNC [[USUBE]] 954 )"; 955 956 // Check 957 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 958 } 959 960 TEST_F(AArch64GISelMITest, WidenSADDE) { 961 setUp(); 962 if (!TM) 963 return; 964 965 // Declare your legalization info 966 DefineLegalizerInfo(A, { 967 getActionDefinitionsBuilder({G_SADDE, G_UADDE}).legalFor({{s16, s16}}); 968 }); 969 // Build 970 // Trunc it to s8. 971 LLT s8{LLT::scalar(8)}; 972 LLT s16{LLT::scalar(16)}; 973 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 974 auto CarryIn = B.buildUndef(LLT::scalar(1)); 975 Register CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); 976 auto MIBUAddO = B.buildInstr(TargetOpcode::G_SADDE, {s8, CarryReg}, 977 {MIBTrunc, MIBTrunc, CarryIn}); 978 AInfo Info(MF->getSubtarget()); 979 DummyGISelObserver Observer; 980 LegalizerHelper Helper(*MF, Info, Observer, B); 981 EXPECT_TRUE(Helper.widenScalar(*MIBUAddO, 0, s16) == 982 LegalizerHelper::LegalizeResult::Legalized); 983 984 const char *CheckStr = R"( 985 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 986 CHECK: [[Implicit:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF 987 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]] 988 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]] 989 CHECK: [[SADDE:%[0-9]+]]:_(s16), [[CARRY:%[0-9]+]]:_(s1) = G_UADDE [[LHS]]:_, [[RHS]]:_, [[Implicit]]:_ 990 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[SADDE]] 991 CHECK: [[SEXT:%[0-9]+]]:_(s16) = G_SEXT [[TRUNC1]] 992 CHECK: G_ICMP intpred(ne), [[SADDE]]:_(s16), [[SEXT]]:_ 993 CHECK: G_TRUNC [[SADDE]] 994 )"; 995 996 // Check 997 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 998 } 999 1000 TEST_F(AArch64GISelMITest, WidenSSUBE) { 1001 setUp(); 1002 if (!TM) 1003 return; 1004 1005 // Declare your legalization info 1006 DefineLegalizerInfo(A, { 1007 getActionDefinitionsBuilder({G_SSUBE, G_USUBE}).legalFor({{s16, s16}}); 1008 }); 1009 // Build 1010 // Trunc it to s8. 1011 LLT s8{LLT::scalar(8)}; 1012 LLT s16{LLT::scalar(16)}; 1013 auto MIBTrunc = B.buildTrunc(s8, Copies[0]); 1014 auto CarryIn = B.buildUndef(LLT::scalar(1)); 1015 Register CarryReg = MRI->createGenericVirtualRegister(LLT::scalar(1)); 1016 auto MIBSSUBE = B.buildInstr(TargetOpcode::G_SSUBE, {s8, CarryReg}, 1017 {MIBTrunc, MIBTrunc, CarryIn}); 1018 AInfo Info(MF->getSubtarget()); 1019 DummyGISelObserver Observer; 1020 LegalizerHelper Helper(*MF, Info, Observer, B); 1021 EXPECT_TRUE(Helper.widenScalar(*MIBSSUBE, 0, s16) == 1022 LegalizerHelper::LegalizeResult::Legalized); 1023 1024 const char *CheckStr = R"( 1025 CHECK: [[Trunc:%[0-9]+]]:_(s8) = G_TRUNC 1026 CHECK: [[Implicit:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF 1027 CHECK: [[LHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]] 1028 CHECK: [[RHS:%[0-9]+]]:_(s16) = G_SEXT [[Trunc]] 1029 CHECK: [[SSUBE:%[0-9]+]]:_(s16), [[CARRY:%[0-9]+]]:_(s1) = G_USUBE [[LHS]]:_, [[RHS]]:_, [[Implicit]]:_ 1030 CHECK: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[SSUBE]] 1031 CHECK: [[SEXT:%[0-9]+]]:_(s16) = G_SEXT [[TRUNC1]] 1032 CHECK: G_ICMP intpred(ne), [[SSUBE]]:_(s16), [[SEXT]]:_ 1033 CHECK: G_TRUNC [[SSUBE]] 1034 )"; 1035 1036 // Check 1037 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1038 } 1039 1040 TEST_F(AArch64GISelMITest, NarrowUADDO) { 1041 setUp(); 1042 if (!TM) 1043 return; 1044 1045 LLT S1 = LLT::scalar(1); 1046 LLT S32 = LLT::scalar(32); 1047 LLT S96 = LLT::scalar(96); 1048 DefineLegalizerInfo(A, { 1049 getActionDefinitionsBuilder({G_UADDO, G_UADDE}) 1050 .legalFor({{LLT::scalar(32), LLT::scalar(1)}}); 1051 }); 1052 1053 auto Op0 = B.buildUndef(S96); 1054 auto Op1 = B.buildUndef(S96); 1055 auto UADDO = B.buildUAddo(S96, S1, Op0, Op1); 1056 1057 AInfo Info(MF->getSubtarget()); 1058 DummyGISelObserver Observer; 1059 LegalizerHelper Helper(*MF, Info, Observer, B); 1060 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1061 Helper.narrowScalar(*UADDO, 0, S32)); 1062 1063 const char *CheckStr = R"( 1064 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF 1065 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF 1066 CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]] 1067 CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]] 1068 CHECK: [[UADDO0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_UADDO [[OP0_0]]:_, [[OP1_0]]:_ 1069 CHECK: [[UADDO1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_UADDE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_ 1070 CHECK: [[UADDO2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_UADDE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_ 1071 CHECK: [[UADDO:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[UADDO0]]:_(s32), [[UADDO1]]:_(s32), [[UADDO2]]:_(s32) 1072 )"; 1073 1074 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1075 } 1076 1077 TEST_F(AArch64GISelMITest, NarrowUSUBO) { 1078 setUp(); 1079 if (!TM) 1080 return; 1081 1082 LLT S1 = LLT::scalar(1); 1083 LLT S32 = LLT::scalar(32); 1084 LLT S96 = LLT::scalar(96); 1085 DefineLegalizerInfo(A, { 1086 getActionDefinitionsBuilder({G_USUBO, G_USUBE}) 1087 .legalFor({{LLT::scalar(32), LLT::scalar(1)}}); 1088 }); 1089 1090 auto Op0 = B.buildUndef(S96); 1091 auto Op1 = B.buildUndef(S96); 1092 auto USUBO = B.buildUSubo(S96, S1, Op0, Op1); 1093 1094 AInfo Info(MF->getSubtarget()); 1095 DummyGISelObserver Observer; 1096 LegalizerHelper Helper(*MF, Info, Observer, B); 1097 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1098 Helper.narrowScalar(*USUBO, 0, S32)); 1099 1100 const char *CheckStr = R"( 1101 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF 1102 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF 1103 CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]] 1104 CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]] 1105 CHECK: [[USUBO0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_USUBO [[OP0_0]]:_, [[OP1_0]]:_ 1106 CHECK: [[USUBO1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_USUBE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_ 1107 CHECK: [[USUBO2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_USUBE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_ 1108 CHECK: [[USUBO:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[USUBO0]]:_(s32), [[USUBO1]]:_(s32), [[USUBO2]]:_(s32) 1109 )"; 1110 1111 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1112 } 1113 1114 TEST_F(AArch64GISelMITest, NarrowSADDO) { 1115 setUp(); 1116 if (!TM) 1117 return; 1118 1119 LLT S1 = LLT::scalar(1); 1120 LLT S32 = LLT::scalar(32); 1121 LLT S96 = LLT::scalar(96); 1122 DefineLegalizerInfo(A, { 1123 getActionDefinitionsBuilder({G_UADDO, G_UADDE, G_SADDE}) 1124 .legalFor({{LLT::scalar(32), LLT::scalar(1)}}); 1125 }); 1126 1127 auto Op0 = B.buildUndef(S96); 1128 auto Op1 = B.buildUndef(S96); 1129 auto SADDO = B.buildSAddo(S96, S1, Op0, Op1); 1130 1131 AInfo Info(MF->getSubtarget()); 1132 DummyGISelObserver Observer; 1133 LegalizerHelper Helper(*MF, Info, Observer, B); 1134 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1135 Helper.narrowScalar(*SADDO, 0, S32)); 1136 1137 const char *CheckStr = R"( 1138 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF 1139 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF 1140 CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]] 1141 CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]] 1142 CHECK: [[SADDO0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_UADDO [[OP0_0]]:_, [[OP1_0]]:_ 1143 CHECK: [[SADDO1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_UADDE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_ 1144 CHECK: [[SADDO2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_SADDE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_ 1145 CHECK: [[SADDO:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[SADDO0]]:_(s32), [[SADDO1]]:_(s32), [[SADDO2]]:_(s32) 1146 )"; 1147 1148 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1149 } 1150 1151 TEST_F(AArch64GISelMITest, NarrowSSUBO) { 1152 setUp(); 1153 if (!TM) 1154 return; 1155 1156 LLT S1 = LLT::scalar(1); 1157 LLT S32 = LLT::scalar(32); 1158 LLT S96 = LLT::scalar(96); 1159 DefineLegalizerInfo(A, { 1160 getActionDefinitionsBuilder({G_USUBO, G_USUBE, G_SSUBE}) 1161 .legalFor({{LLT::scalar(32), LLT::scalar(1)}}); 1162 }); 1163 1164 auto Op0 = B.buildUndef(S96); 1165 auto Op1 = B.buildUndef(S96); 1166 auto SSUBO = B.buildSSubo(S96, S1, Op0, Op1); 1167 1168 AInfo Info(MF->getSubtarget()); 1169 DummyGISelObserver Observer; 1170 LegalizerHelper Helper(*MF, Info, Observer, B); 1171 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1172 Helper.narrowScalar(*SSUBO, 0, S32)); 1173 1174 const char *CheckStr = R"( 1175 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF 1176 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF 1177 CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]] 1178 CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]] 1179 CHECK: [[SSUBO0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_USUBO [[OP0_0]]:_, [[OP1_0]]:_ 1180 CHECK: [[SSUBO1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_USUBE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_ 1181 CHECK: [[SSUBO2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_SSUBE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_ 1182 CHECK: [[SSUBO:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[SSUBO0]]:_(s32), [[SSUBO1]]:_(s32), [[SSUBO2]]:_(s32) 1183 )"; 1184 1185 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1186 } 1187 1188 TEST_F(AArch64GISelMITest, NarrowUADDE) { 1189 setUp(); 1190 if (!TM) 1191 return; 1192 1193 LLT S1 = LLT::scalar(1); 1194 LLT S32 = LLT::scalar(32); 1195 LLT S96 = LLT::scalar(96); 1196 DefineLegalizerInfo(A, { 1197 getActionDefinitionsBuilder(G_UADDE).legalFor( 1198 {{LLT::scalar(32), LLT::scalar(1)}}); 1199 }); 1200 1201 auto Op0 = B.buildUndef(S96); 1202 auto Op1 = B.buildUndef(S96); 1203 auto Op2 = B.buildUndef(S1); 1204 auto UADDE = B.buildUAdde(S96, S1, Op0, Op1, Op2); 1205 1206 AInfo Info(MF->getSubtarget()); 1207 DummyGISelObserver Observer; 1208 LegalizerHelper Helper(*MF, Info, Observer, B); 1209 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1210 Helper.narrowScalar(*UADDE, 0, S32)); 1211 1212 const char *CheckStr = R"( 1213 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF 1214 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF 1215 CHECK: [[IMP_DEF2:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF 1216 CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]] 1217 CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]] 1218 CHECK: [[UADDE0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_UADDE [[OP0_0]]:_, [[OP1_0]]:_, [[IMP_DEF2]]:_ 1219 CHECK: [[UADDE1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_UADDE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_ 1220 CHECK: [[UADDE2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_UADDE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_ 1221 CHECK: [[UADDE:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[UADDE0]]:_(s32), [[UADDE1]]:_(s32), [[UADDE2]]:_(s32) 1222 )"; 1223 1224 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1225 } 1226 1227 TEST_F(AArch64GISelMITest, NarrowUSUBE) { 1228 setUp(); 1229 if (!TM) 1230 return; 1231 1232 LLT S1 = LLT::scalar(1); 1233 LLT S32 = LLT::scalar(32); 1234 LLT S96 = LLT::scalar(96); 1235 DefineLegalizerInfo(A, { 1236 getActionDefinitionsBuilder(G_USUBE).legalFor( 1237 {{LLT::scalar(32), LLT::scalar(1)}}); 1238 }); 1239 1240 auto Op0 = B.buildUndef(S96); 1241 auto Op1 = B.buildUndef(S96); 1242 auto Op2 = B.buildUndef(S1); 1243 auto USUBE = B.buildUSube(S96, S1, Op0, Op1, Op2); 1244 1245 AInfo Info(MF->getSubtarget()); 1246 DummyGISelObserver Observer; 1247 LegalizerHelper Helper(*MF, Info, Observer, B); 1248 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1249 Helper.narrowScalar(*USUBE, 0, S32)); 1250 1251 const char *CheckStr = R"( 1252 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF 1253 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF 1254 CHECK: [[IMP_DEF2:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF 1255 CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]] 1256 CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]] 1257 CHECK: [[USUBE0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_USUBE [[OP0_0]]:_, [[OP1_0]]:_, [[IMP_DEF2]]:_ 1258 CHECK: [[USUBE1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_USUBE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_ 1259 CHECK: [[USUBE2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_USUBE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_ 1260 CHECK: [[USUBE:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[USUBE0]]:_(s32), [[USUBE1]]:_(s32), [[USUBE2]]:_(s32) 1261 )"; 1262 1263 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1264 } 1265 1266 TEST_F(AArch64GISelMITest, NarrowSADDE) { 1267 setUp(); 1268 if (!TM) 1269 return; 1270 1271 LLT S1 = LLT::scalar(1); 1272 LLT S32 = LLT::scalar(32); 1273 LLT S96 = LLT::scalar(96); 1274 DefineLegalizerInfo(A, { 1275 getActionDefinitionsBuilder({G_SADDE, G_UADDE}) 1276 .legalFor({{LLT::scalar(32), LLT::scalar(1)}}); 1277 }); 1278 1279 auto Op0 = B.buildUndef(S96); 1280 auto Op1 = B.buildUndef(S96); 1281 auto Op2 = B.buildUndef(S1); 1282 auto SADDE = B.buildSAdde(S96, S1, Op0, Op1, Op2); 1283 1284 AInfo Info(MF->getSubtarget()); 1285 DummyGISelObserver Observer; 1286 LegalizerHelper Helper(*MF, Info, Observer, B); 1287 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1288 Helper.narrowScalar(*SADDE, 0, S32)); 1289 1290 const char *CheckStr = R"( 1291 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF 1292 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF 1293 CHECK: [[IMP_DEF2:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF 1294 CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]] 1295 CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]] 1296 CHECK: [[SADDE0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_UADDE [[OP0_0]]:_, [[OP1_0]]:_, [[IMP_DEF2]]:_ 1297 CHECK: [[SADDE1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_UADDE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_ 1298 CHECK: [[SADDE2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_SADDE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_ 1299 CHECK: [[SADDE:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[SADDE0]]:_(s32), [[SADDE1]]:_(s32), [[SADDE2]]:_(s32) 1300 )"; 1301 1302 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1303 } 1304 1305 TEST_F(AArch64GISelMITest, NarrowSSUBE) { 1306 setUp(); 1307 if (!TM) 1308 return; 1309 1310 LLT S1 = LLT::scalar(1); 1311 LLT S32 = LLT::scalar(32); 1312 LLT S96 = LLT::scalar(96); 1313 DefineLegalizerInfo(A, { 1314 getActionDefinitionsBuilder({G_SSUBE, G_USUBE}) 1315 .legalFor({{LLT::scalar(32), LLT::scalar(1)}}); 1316 }); 1317 1318 auto Op0 = B.buildUndef(S96); 1319 auto Op1 = B.buildUndef(S96); 1320 auto Op2 = B.buildUndef(S1); 1321 auto SSUBE = B.buildSSube(S96, S1, Op0, Op1, Op2); 1322 1323 AInfo Info(MF->getSubtarget()); 1324 DummyGISelObserver Observer; 1325 LegalizerHelper Helper(*MF, Info, Observer, B); 1326 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1327 Helper.narrowScalar(*SSUBE, 0, S32)); 1328 1329 const char *CheckStr = R"( 1330 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF 1331 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s96) = G_IMPLICIT_DEF 1332 CHECK: [[IMP_DEF2:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF 1333 CHECK: [[OP0_0:%[0-9]+]]:_(s32), [[OP0_1:%[0-9]+]]:_(s32), [[OP0_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]] 1334 CHECK: [[OP1_0:%[0-9]+]]:_(s32), [[OP1_1:%[0-9]+]]:_(s32), [[OP1_2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]] 1335 CHECK: [[SSUBE0:%[0-9]+]]:_(s32), [[CARRY0:%[0-9]+]]:_(s1) = G_USUBE [[OP0_0]]:_, [[OP1_0]]:_, [[IMP_DEF2]]:_ 1336 CHECK: [[SSUBE1:%[0-9]+]]:_(s32), [[CARRY1:%[0-9]+]]:_(s1) = G_USUBE [[OP0_1]]:_, [[OP1_1]]:_, [[CARRY0]]:_ 1337 CHECK: [[SSUBE2:%[0-9]+]]:_(s32), [[CARRY2:%[0-9]+]]:_(s1) = G_SSUBE [[OP0_2]]:_, [[OP1_2]]:_, [[CARRY1]]:_ 1338 CHECK: [[SSUBE:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[SSUBE0]]:_(s32), [[SSUBE1]]:_(s32), [[SSUBE2]]:_(s32) 1339 )"; 1340 1341 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1342 } 1343 1344 TEST_F(AArch64GISelMITest, FewerElementsAnd) { 1345 setUp(); 1346 if (!TM) 1347 return; 1348 1349 const LLT V2S32 = LLT::fixed_vector(2, 32); 1350 const LLT V5S32 = LLT::fixed_vector(5, 32); 1351 1352 // Declare your legalization info 1353 DefineLegalizerInfo(A, { 1354 getActionDefinitionsBuilder(G_AND) 1355 .legalFor({s32}); 1356 }); 1357 1358 auto Op0 = B.buildUndef(V5S32); 1359 auto Op1 = B.buildUndef(V5S32); 1360 auto And = B.buildAnd(V5S32, Op0, Op1); 1361 1362 AInfo Info(MF->getSubtarget()); 1363 DummyGISelObserver Observer; 1364 LegalizerHelper Helper(*MF, Info, Observer, B); 1365 B.setInstr(*And); 1366 EXPECT_TRUE(Helper.fewerElementsVector(*And, 0, V2S32) == 1367 LegalizerHelper::LegalizeResult::Legalized); 1368 1369 auto CheckStr = R"( 1370 CHECK: [[IMP_DEF0:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF 1371 CHECK: [[IMP_DEF1:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF 1372 CHECK: [[VALUE0:%[0-9]+]]:_(s32), [[VALUE1:%[0-9]+]]:_(s32), [[VALUE2:%[0-9]+]]:_(s32), [[VALUE3:%[0-9]+]]:_(s32), [[VALUE4:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF0]]:_(<5 x s32>) 1373 CHECK: [[VECTOR0:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[VALUE0]]:_(s32), [[VALUE1]]:_(s32) 1374 CHECK: [[VECTOR1:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[VALUE2]]:_(s32), [[VALUE3]]:_(s32) 1375 CHECK: [[VALUE5:%[0-9]+]]:_(s32), [[VALUE6:%[0-9]+]]:_(s32), [[VALUE7:%[0-9]+]]:_(s32), [[VALUE8:%[0-9]+]]:_(s32), [[VALUE9:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[IMP_DEF1]]:_(<5 x s32>) 1376 CHECK: [[VECTOR2:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[VALUE5]]:_(s32), [[VALUE6]]:_(s32) 1377 CHECK: [[VECTOR3:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[VALUE7]]:_(s32), [[VALUE8]]:_(s32) 1378 CHECK: [[AND0:%[0-9]+]]:_(<2 x s32>) = G_AND [[VECTOR0]]:_, [[VECTOR2]]:_ 1379 CHECK: [[AND1:%[0-9]+]]:_(<2 x s32>) = G_AND [[VECTOR1]]:_, [[VECTOR3]]:_ 1380 CHECK: [[AND2:%[0-9]+]]:_(s32) = G_AND [[VALUE4]]:_, [[VALUE9]]:_ 1381 CHECK: [[AND0_E0:%[0-9]+]]:_(s32), [[AND0_E1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[AND0]]:_(<2 x s32>) 1382 CHECK: [[AND1_E0:%[0-9]+]]:_(s32), [[AND1_E1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[AND1]]:_(<2 x s32>) 1383 CHECK: [[RESULT:%[0-9]+]]:_(<5 x s32>) = G_BUILD_VECTOR [[AND0_E0]]:_(s32), [[AND0_E1]]:_(s32), [[AND1_E0]]:_(s32), [[AND1_E1]]:_(s32), [[AND2]]:_(s32) 1384 )"; 1385 1386 // Check 1387 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1388 } 1389 1390 TEST_F(AArch64GISelMITest, MoreElementsAnd) { 1391 setUp(); 1392 if (!TM) 1393 return; 1394 1395 LLT s32 = LLT::scalar(32); 1396 LLT v2s32 = LLT::fixed_vector(2, 32); 1397 LLT v6s32 = LLT::fixed_vector(6, 32); 1398 1399 LegalizerInfo LI; 1400 LI.getActionDefinitionsBuilder(TargetOpcode::G_AND) 1401 .legalFor({v6s32}) 1402 .clampMinNumElements(0, s32, 6); 1403 LI.getLegacyLegalizerInfo().computeTables(); 1404 1405 DummyGISelObserver Observer; 1406 LegalizerHelper Helper(*MF, LI, Observer, B); 1407 1408 B.setInsertPt(*EntryMBB, EntryMBB->end()); 1409 1410 auto Val0 = B.buildBitcast(v2s32, Copies[0]); 1411 auto Val1 = B.buildBitcast(v2s32, Copies[1]); 1412 1413 auto And = B.buildAnd(v2s32, Val0, Val1); 1414 1415 B.setInstr(*And); 1416 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1417 Helper.moreElementsVector(*And, 0, v6s32)); 1418 1419 auto CheckStr = R"( 1420 CHECK: [[BITCAST0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST 1421 CHECK: [[BITCAST1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST 1422 1423 CHECK: [[BITCAST0_E0:%[0-9]+]]:_(s32), [[BITCAST0_E1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[BITCAST0]]:_(<2 x s32>) 1424 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF 1425 CHECK: [[BITCAST0_LARGE:%[0-9]+]]:_(<6 x s32>) = G_BUILD_VECTOR [[BITCAST0_E0]]:_(s32), [[BITCAST0_E1]]:_(s32), [[IMP_DEF0]]:_(s32), [[IMP_DEF0]]:_(s32), [[IMP_DEF0]]:_(s32), [[IMP_DEF0]]:_(s32) 1426 1427 CHECK: [[BITCAST1_E0:%[0-9]+]]:_(s32), [[BITCAST1_E1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[BITCAST1]]:_(<2 x s32>) 1428 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF 1429 CHECK: [[BITCAST1_LARGE:%[0-9]+]]:_(<6 x s32>) = G_BUILD_VECTOR [[BITCAST1_E0]]:_(s32), [[BITCAST1_E1]]:_(s32), [[IMP_DEF1]]:_(s32), [[IMP_DEF1]]:_(s32), [[IMP_DEF1]]:_(s32), [[IMP_DEF1]]:_(s32) 1430 1431 CHECK: [[AND:%[0-9]+]]:_(<6 x s32>) = G_AND [[BITCAST0_LARGE]]:_, [[BITCAST1_LARGE]]:_ 1432 1433 CHECK: [[AND_E0:%[0-9]+]]:_(s32), [[AND_E1:%[0-9]+]]:_(s32), [[AND_E2:%[0-9]+]]:_(s32), [[AND_E3:%[0-9]+]]:_(s32), [[AND_E4:%[0-9]+]]:_(s32), [[AND_E5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[AND]]:_(<6 x s32>) 1434 CHECK: (<2 x s32>) = G_BUILD_VECTOR [[AND_E0]]:_(s32), [[AND_E1]]:_(s32) 1435 )"; 1436 1437 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1438 } 1439 1440 TEST_F(AArch64GISelMITest, FewerElementsPhi) { 1441 setUp(); 1442 if (!TM) 1443 return; 1444 1445 LLT s1 = LLT::scalar(1); 1446 LLT s32 = LLT::scalar(32); 1447 LLT s64 = LLT::scalar(64); 1448 LLT v2s32 = LLT::fixed_vector(2, 32); 1449 LLT v5s32 = LLT::fixed_vector(5, 32); 1450 1451 LegalizerInfo LI; 1452 LI.getActionDefinitionsBuilder(TargetOpcode::G_PHI) 1453 .legalFor({v2s32}) 1454 .clampMinNumElements(0, s32, 2); 1455 LI.getLegacyLegalizerInfo().computeTables(); 1456 1457 LLT PhiTy = v5s32; 1458 DummyGISelObserver Observer; 1459 LegalizerHelper Helper(*MF, LI, Observer, B); 1460 B.setMBB(*EntryMBB); 1461 1462 MachineBasicBlock *MidMBB = MF->CreateMachineBasicBlock(); 1463 MachineBasicBlock *EndMBB = MF->CreateMachineBasicBlock(); 1464 MF->insert(MF->end(), MidMBB); 1465 MF->insert(MF->end(), EndMBB); 1466 1467 EntryMBB->addSuccessor(MidMBB); 1468 EntryMBB->addSuccessor(EndMBB); 1469 MidMBB->addSuccessor(EndMBB); 1470 1471 auto InitVal = B.buildUndef(PhiTy); 1472 auto InitOtherVal = B.buildConstant(s64, 999); 1473 1474 auto ICmp = B.buildICmp(CmpInst::ICMP_EQ, s1, Copies[0], Copies[1]); 1475 B.buildBrCond(ICmp.getReg(0), *MidMBB); 1476 B.buildBr(*EndMBB); 1477 1478 1479 B.setMBB(*MidMBB); 1480 auto MidVal = B.buildUndef(PhiTy); 1481 auto MidOtherVal = B.buildConstant(s64, 345); 1482 B.buildBr(*EndMBB); 1483 1484 B.setMBB(*EndMBB); 1485 auto Phi = B.buildInstr(TargetOpcode::G_PHI) 1486 .addDef(MRI->createGenericVirtualRegister(PhiTy)) 1487 .addUse(InitVal.getReg(0)) 1488 .addMBB(EntryMBB) 1489 .addUse(MidVal.getReg(0)) 1490 .addMBB(MidMBB); 1491 1492 // Insert another irrelevant phi to make sure the rebuild is inserted after 1493 // it. 1494 B.buildInstr(TargetOpcode::G_PHI) 1495 .addDef(MRI->createGenericVirtualRegister(s64)) 1496 .addUse(InitOtherVal.getReg(0)) 1497 .addMBB(EntryMBB) 1498 .addUse(MidOtherVal.getReg(0)) 1499 .addMBB(MidMBB); 1500 1501 // Add some use instruction after the phis. 1502 B.buildAnd(PhiTy, Phi.getReg(0), Phi.getReg(0)); 1503 1504 B.setInstr(*Phi); 1505 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1506 Helper.fewerElementsVector(*Phi, 0, v2s32)); 1507 1508 auto CheckStr = R"( 1509 CHECK: [[INITVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF 1510 CHECK: [[INITVAL_E0:%[0-9]+]]:_(s32), [[INITVAL_E1:%[0-9]+]]:_(s32), [[INITVAL_E2:%[0-9]+]]:_(s32), [[INITVAL_E3:%[0-9]+]]:_(s32), [[INITVAL_E4:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[INITVAL]]:_(<5 x s32>) 1511 CHECK: [[INITVAL_E01:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[INITVAL_E0]]:_(s32), [[INITVAL_E1]]:_(s32) 1512 CHECK: [[INITVAL_E23:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[INITVAL_E2]]:_(s32), [[INITVAL_E3]]:_(s32) 1513 CHECK: G_BRCOND 1514 1515 CHECK: [[MIDVAL:%[0-9]+]]:_(<5 x s32>) = G_IMPLICIT_DEF 1516 CHECK: [[MIDVAL_E0:%[0-9]+]]:_(s32), [[MIDVAL_E1:%[0-9]+]]:_(s32), [[MIDVAL_E2:%[0-9]+]]:_(s32), [[MIDVAL_E3:%[0-9]+]]:_(s32), [[MIDVAL_E4:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[MIDVAL]]:_(<5 x s32>) 1517 CHECK: [[MIDVAL_E01:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[MIDVAL_E0]]:_(s32), [[MIDVAL_E1]]:_(s32) 1518 CHECK: [[MIDVAL_E23:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[MIDVAL_E2]]:_(s32), [[MIDVAL_E3]]:_(s32) 1519 CHECK: G_BR 1520 1521 CHECK: [[PHI0:%[0-9]+]]:_(<2 x s32>) = G_PHI [[INITVAL_E01]]:_(<2 x s32>), %bb.0, [[MIDVAL_E01]]:_(<2 x s32>), %bb.1 1522 CHECK: [[PHI1:%[0-9]+]]:_(<2 x s32>) = G_PHI [[INITVAL_E23]]:_(<2 x s32>), %bb.0, [[MIDVAL_E23]]:_(<2 x s32>), %bb.1 1523 CHECK: [[PHI2:%[0-9]+]]:_(s32) = G_PHI [[INITVAL_E4]]:_(s32), %bb.0, [[MIDVAL_E4]]:_(s32), %bb.1 1524 CHECK: [[UNMERGE0:%[0-9]+]]:_(s32), [[UNMERGE1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[PHI0]]:_(<2 x s32>) 1525 CHECK: [[UNMERGE2:%[0-9]+]]:_(s32), [[UNMERGE3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[PHI1]]:_(<2 x s32>) 1526 CHECK: [[BV:%[0-9]+]]:_(<5 x s32>) = G_BUILD_VECTOR [[UNMERGE0]]:_(s32), [[UNMERGE1]]:_(s32), [[UNMERGE2]]:_(s32), [[UNMERGE3]]:_(s32), [[PHI2]]:_(s32) 1527 1528 CHECK: [[OTHER_PHI:%[0-9]+]]:_(s64) = G_PHI 1529 1530 CHECK: [[USE_OP:%[0-9]+]]:_(<5 x s32>) = G_AND [[BV]]:_, [[BV]]:_ 1531 )"; 1532 1533 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1534 } 1535 1536 // FNEG expansion in terms of XOR 1537 TEST_F(AArch64GISelMITest, LowerFNEG) { 1538 setUp(); 1539 if (!TM) 1540 return; 1541 1542 // Declare your legalization info 1543 DefineLegalizerInfo(A, { 1544 getActionDefinitionsBuilder(G_FSUB).legalFor({s64}); 1545 }); 1546 1547 // Build Instr. Make sure FMF are preserved. 1548 auto FAdd = 1549 B.buildInstr(TargetOpcode::G_FADD, {LLT::scalar(64)}, {Copies[0], Copies[1]}, 1550 MachineInstr::MIFlag::FmNsz); 1551 1552 // Should not propagate the flags of src instruction. 1553 auto FNeg0 = 1554 B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {FAdd.getReg(0)}, 1555 {MachineInstr::MIFlag::FmArcp}); 1556 1557 // Preserve the one flag. 1558 auto FNeg1 = 1559 B.buildInstr(TargetOpcode::G_FNEG, {LLT::scalar(64)}, {Copies[0]}, 1560 MachineInstr::MIFlag::FmNoInfs); 1561 1562 AInfo Info(MF->getSubtarget()); 1563 DummyGISelObserver Observer; 1564 LegalizerHelper Helper(*MF, Info, Observer, B); 1565 // Perform Legalization 1566 B.setInstr(*FNeg0); 1567 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1568 Helper.lower(*FNeg0, 0, LLT::scalar(64))); 1569 B.setInstr(*FNeg1); 1570 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1571 Helper.lower(*FNeg1, 0, LLT::scalar(64))); 1572 1573 auto CheckStr = R"( 1574 CHECK: [[FADD:%[0-9]+]]:_(s64) = nsz G_FADD %0:_, %1:_ 1575 CHECK: [[CONST0:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 1576 CHECK: [[FSUB0:%[0-9]+]]:_(s64) = G_XOR [[FADD]]:_, [[CONST0]]:_ 1577 CHECK: [[CONST1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 1578 CHECK: [[FSUB1:%[0-9]+]]:_(s64) = G_XOR %0:_, [[CONST1]]:_ 1579 )"; 1580 1581 // Check 1582 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1583 } 1584 1585 TEST_F(AArch64GISelMITest, LowerMinMax) { 1586 setUp(); 1587 if (!TM) 1588 return; 1589 1590 LLT s64 = LLT::scalar(64); 1591 LLT v2s32 = LLT::fixed_vector(2, 32); 1592 1593 DefineLegalizerInfo(A, { 1594 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX}) 1595 .lowerFor({s64, LLT::fixed_vector(2, s32)}); 1596 }); 1597 1598 auto SMin = B.buildSMin(s64, Copies[0], Copies[1]); 1599 auto SMax = B.buildSMax(s64, Copies[0], Copies[1]); 1600 auto UMin = B.buildUMin(s64, Copies[0], Copies[1]); 1601 auto UMax = B.buildUMax(s64, Copies[0], Copies[1]); 1602 1603 auto VecVal0 = B.buildBitcast(v2s32, Copies[0]); 1604 auto VecVal1 = B.buildBitcast(v2s32, Copies[1]); 1605 1606 auto SMinV = B.buildSMin(v2s32, VecVal0, VecVal1); 1607 auto SMaxV = B.buildSMax(v2s32, VecVal0, VecVal1); 1608 auto UMinV = B.buildUMin(v2s32, VecVal0, VecVal1); 1609 auto UMaxV = B.buildUMax(v2s32, VecVal0, VecVal1); 1610 1611 AInfo Info(MF->getSubtarget()); 1612 DummyGISelObserver Observer; 1613 LegalizerHelper Helper(*MF, Info, Observer, B); 1614 B.setInstr(*SMin); 1615 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1616 Helper.lower(*SMin, 0, s64)); 1617 B.setInstr(*SMax); 1618 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1619 Helper.lower(*SMax, 0, s64)); 1620 B.setInstr(*UMin); 1621 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1622 Helper.lower(*UMin, 0, s64)); 1623 B.setInstr(*UMax); 1624 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1625 Helper.lower(*UMax, 0, s64)); 1626 1627 B.setInstr(*SMinV); 1628 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1629 Helper.lower(*SMinV, 0, v2s32)); 1630 B.setInstr(*SMaxV); 1631 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1632 Helper.lower(*SMaxV, 0, v2s32)); 1633 B.setInstr(*UMinV); 1634 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1635 Helper.lower(*UMinV, 0, v2s32)); 1636 B.setInstr(*UMaxV); 1637 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1638 Helper.lower(*UMaxV, 0, v2s32)); 1639 1640 auto CheckStr = R"( 1641 CHECK: [[CMP0:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), %0:_(s64), %1:_ 1642 CHECK: [[SMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP0]]:_(s1), %0:_, %1:_ 1643 1644 CHECK: [[CMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), %0:_(s64), %1:_ 1645 CHECK: [[SMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP1]]:_(s1), %0:_, %1:_ 1646 1647 CHECK: [[CMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(ult), %0:_(s64), %1:_ 1648 CHECK: [[UMIN:%[0-9]+]]:_(s64) = G_SELECT [[CMP2]]:_(s1), %0:_, %1:_ 1649 1650 CHECK: [[CMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(ugt), %0:_(s64), %1:_ 1651 CHECK: [[UMAX:%[0-9]+]]:_(s64) = G_SELECT [[CMP3]]:_(s1), %0:_, %1:_ 1652 1653 CHECK: [[VEC0:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %0:_(s64) 1654 CHECK: [[VEC1:%[0-9]+]]:_(<2 x s32>) = G_BITCAST %1:_(s64) 1655 1656 CHECK: [[VCMP0:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(slt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_ 1657 CHECK: [[SMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP0]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_ 1658 1659 CHECK: [[VCMP1:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(sgt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_ 1660 CHECK: [[SMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP1]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_ 1661 1662 CHECK: [[VCMP2:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ult), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_ 1663 CHECK: [[UMINV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP2]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_ 1664 1665 CHECK: [[VCMP3:%[0-9]+]]:_(<2 x s1>) = G_ICMP intpred(ugt), [[VEC0]]:_(<2 x s32>), [[VEC1]]:_ 1666 CHECK: [[UMAXV:%[0-9]+]]:_(<2 x s32>) = G_SELECT [[VCMP3]]:_(<2 x s1>), [[VEC0]]:_, [[VEC1]]:_ 1667 )"; 1668 1669 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1670 } 1671 1672 TEST_F(AArch64GISelMITest, WidenScalarBuildVector) { 1673 setUp(); 1674 if (!TM) 1675 return; 1676 1677 LLT S32 = LLT::scalar(32); 1678 LLT S16 = LLT::scalar(16); 1679 LLT V2S16 = LLT::fixed_vector(2, S16); 1680 LLT V2S32 = LLT::fixed_vector(2, S32); 1681 1682 DefineLegalizerInfo(A, { 1683 getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX}) 1684 .lowerFor({s64, LLT::fixed_vector(2, s32)}); 1685 }); 1686 1687 AInfo Info(MF->getSubtarget()); 1688 DummyGISelObserver Observer; 1689 LegalizerHelper Helper(*MF, Info, Observer, B); 1690 B.setInsertPt(*EntryMBB, EntryMBB->end()); 1691 1692 Register Constant0 = B.buildConstant(S16, 1).getReg(0); 1693 Register Constant1 = B.buildConstant(S16, 2).getReg(0); 1694 auto BV0 = B.buildBuildVector(V2S16, {Constant0, Constant1}); 1695 auto BV1 = B.buildBuildVector(V2S16, {Constant0, Constant1}); 1696 1697 B.setInstr(*BV0); 1698 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1699 Helper.widenScalar(*BV0, 0, V2S32)); 1700 B.setInstr(*BV1); 1701 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1702 Helper.widenScalar(*BV1, 1, S32)); 1703 1704 auto CheckStr = R"( 1705 CHECK: [[K0:%[0-9]+]]:_(s16) = G_CONSTANT i16 1 1706 CHECK-NEXT: [[K1:%[0-9]+]]:_(s16) = G_CONSTANT i16 2 1707 CHECK-NEXT: [[EXT_K0_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]] 1708 CHECK-NEXT: [[EXT_K1_0:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]] 1709 CHECK-NEXT: [[BV0:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[EXT_K0_0]]:_(s32), [[EXT_K1_0]]:_(s32) 1710 CHECK-NEXT: [[BV0_TRUNC:%[0-9]+]]:_(<2 x s16>) = G_TRUNC [[BV0]] 1711 1712 CHECK: [[EXT_K0_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K0]] 1713 CHECK-NEXT: [[EXT_K1_1:%[0-9]+]]:_(s32) = G_ANYEXT [[K1]] 1714 1715 CHECK-NEXT: [[BV1:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR_TRUNC [[EXT_K0_1]]:_(s32), [[EXT_K1_1]]:_(s32) 1716 )"; 1717 1718 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1719 } 1720 1721 TEST_F(AArch64GISelMITest, LowerMergeValues) { 1722 setUp(); 1723 if (!TM) 1724 return; 1725 1726 const LLT S32 = LLT::scalar(32); 1727 const LLT S24 = LLT::scalar(24); 1728 const LLT S21 = LLT::scalar(21); 1729 const LLT S16 = LLT::scalar(16); 1730 const LLT S9 = LLT::scalar(9); 1731 const LLT S8 = LLT::scalar(8); 1732 const LLT S3 = LLT::scalar(3); 1733 1734 DefineLegalizerInfo(A, { 1735 getActionDefinitionsBuilder(G_UNMERGE_VALUES) 1736 .widenScalarIf(typeIs(1, LLT::scalar(3)), changeTo(1, LLT::scalar(9))); 1737 }); 1738 1739 AInfo Info(MF->getSubtarget()); 1740 DummyGISelObserver Observer; 1741 LegalizerHelper Helper(*MF, Info, Observer, B); 1742 B.setInsertPt(*EntryMBB, EntryMBB->end()); 1743 1744 // 24 = 3 3 3 3 3 3 3 3 1745 // => 9 1746 // 1747 // This can do 3 merges, but need an extra implicit_def. 1748 SmallVector<Register, 8> Merge0Ops; 1749 for (int I = 0; I != 8; ++I) 1750 Merge0Ops.push_back(B.buildConstant(S3, I).getReg(0)); 1751 1752 auto Merge0 = B.buildMerge(S24, Merge0Ops); 1753 1754 // 21 = 3 3 3 3 3 3 3 1755 // => 9, 2 extra implicit_def needed 1756 // 1757 SmallVector<Register, 8> Merge1Ops; 1758 for (int I = 0; I != 7; ++I) 1759 Merge1Ops.push_back(B.buildConstant(S3, I).getReg(0)); 1760 1761 auto Merge1 = B.buildMerge(S21, Merge1Ops); 1762 1763 SmallVector<Register, 8> Merge2Ops; 1764 for (int I = 0; I != 2; ++I) 1765 Merge2Ops.push_back(B.buildConstant(S8, I).getReg(0)); 1766 1767 auto Merge2 = B.buildMerge(S16, Merge2Ops); 1768 1769 B.setInstr(*Merge0); 1770 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1771 Helper.widenScalar(*Merge0, 1, S9)); 1772 B.setInstr(*Merge1); 1773 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1774 Helper.widenScalar(*Merge1, 1, S9)); 1775 1776 // Request a source size greater than the original destination size. 1777 B.setInstr(*Merge2); 1778 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1779 Helper.widenScalar(*Merge2, 1, S32)); 1780 1781 auto CheckStr = R"( 1782 CHECK: [[K0:%[0-9]+]]:_(s3) = G_CONSTANT i3 0 1783 CHECK-NEXT: [[K1:%[0-9]+]]:_(s3) = G_CONSTANT i3 1 1784 CHECK-NEXT: [[K2:%[0-9]+]]:_(s3) = G_CONSTANT i3 2 1785 CHECK-NEXT: [[K3:%[0-9]+]]:_(s3) = G_CONSTANT i3 3 1786 CHECK-NEXT: [[K4:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4 1787 CHECK-NEXT: [[K5:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3 1788 CHECK-NEXT: [[K6:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2 1789 CHECK-NEXT: [[K7:%[0-9]+]]:_(s3) = G_CONSTANT i3 -1 1790 CHECK-NEXT: [[IMPDEF0:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF 1791 CHECK-NEXT: [[MERGE0:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K0]]:_(s3), [[K1]]:_(s3), [[K2]]:_(s3) 1792 CHECK-NEXT: [[MERGE1:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K3]]:_(s3), [[K4]]:_(s3), [[K5]]:_(s3) 1793 CHECK-NEXT: [[MERGE2:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K6]]:_(s3), [[K7]]:_(s3), [[IMPDEF0]]:_(s3) 1794 CHECK-NEXT: [[MERGE3:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE0]]:_(s9), [[MERGE1]]:_(s9), [[MERGE2]]:_(s9) 1795 CHECK-NEXT: (s24) = G_TRUNC [[MERGE3]]:_(s27) 1796 1797 1798 CHECK: [[K8:%[0-9]+]]:_(s3) = G_CONSTANT i3 0 1799 CHECK-NEXT: [[K9:%[0-9]+]]:_(s3) = G_CONSTANT i3 1 1800 CHECK-NEXT: [[K10:%[0-9]+]]:_(s3) = G_CONSTANT i3 2 1801 CHECK-NEXT: [[K11:%[0-9]+]]:_(s3) = G_CONSTANT i3 3 1802 CHECK-NEXT: [[K12:%[0-9]+]]:_(s3) = G_CONSTANT i3 -4 1803 CHECK-NEXT: [[K13:%[0-9]+]]:_(s3) = G_CONSTANT i3 -3 1804 CHECK-NEXT: [[K14:%[0-9]+]]:_(s3) = G_CONSTANT i3 -2 1805 CHECK-NEXT: [[IMPDEF1:%[0-9]+]]:_(s3) = G_IMPLICIT_DEF 1806 CHECK-NEXT: [[MERGE4:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K8]]:_(s3), [[K9]]:_(s3), [[K10]]:_(s3) 1807 CHECK-NEXT: [[MERGE5:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K11]]:_(s3), [[K12]]:_(s3), [[K13]]:_(s3) 1808 CHECK-NEXT: [[MERGE6:%[0-9]+]]:_(s9) = G_MERGE_VALUES [[K14]]:_(s3), [[IMPDEF1]]:_(s3), [[IMPDEF1]]:_(s3) 1809 CHECK-NEXT: [[MERGE7:%[0-9]+]]:_(s27) = G_MERGE_VALUES [[MERGE4]]:_(s9), [[MERGE5]]:_(s9), [[MERGE6]]:_(s9) 1810 CHECK-NEXT: (s21) = G_TRUNC [[MERGE7]]:_(s27) 1811 1812 1813 CHECK: [[K15:%[0-9]+]]:_(s8) = G_CONSTANT i8 0 1814 CHECK-NEXT: [[K16:%[0-9]+]]:_(s8) = G_CONSTANT i8 1 1815 CHECK-NEXT: [[ZEXT_K15:[0-9]+]]:_(s32) = G_ZEXT [[K15]]:_(s8) 1816 CHECK-NEXT: [[ZEXT_K16:[0-9]+]]:_(s32) = G_ZEXT [[K16]]:_(s8) 1817 [[K16:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 1818 [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ZEXT_K16]]:_, [[K16]]:_(s32) 1819 [[OR:%[0-9]+]]:_(s32) = G_OR [[ZEXT_K16]]:_, [[SHL]]:_ 1820 (s16) = G_TRUNC [[OR]]:_(s32) 1821 )"; 1822 1823 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1824 } 1825 1826 TEST_F(AArch64GISelMITest, WidenScalarMergeValuesPointer) { 1827 setUp(); 1828 if (!TM) 1829 return; 1830 1831 DefineLegalizerInfo(A, {}); 1832 1833 AInfo Info(MF->getSubtarget()); 1834 DummyGISelObserver Observer; 1835 LegalizerHelper Helper(*MF, Info, Observer, B); 1836 B.setInsertPt(*EntryMBB, EntryMBB->end()); 1837 1838 const LLT S32 = LLT::scalar(32); 1839 const LLT S64 = LLT::scalar(64); 1840 const LLT P0 = LLT::pointer(0, 64); 1841 1842 auto Lo = B.buildTrunc(S32, Copies[0]); 1843 auto Hi = B.buildTrunc(S32, Copies[1]); 1844 1845 auto Merge = B.buildMerge(P0, {Lo, Hi}); 1846 1847 B.setInstr(*Merge); 1848 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 1849 Helper.widenScalar(*Merge, 1, S64)); 1850 1851 auto CheckStr = R"( 1852 CHECK: [[TRUNC0:%[0-9]+]]:_(s32) = G_TRUNC 1853 CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC 1854 CHECK: [[ZEXT_TRUNC0:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC0]] 1855 CHECK: [[ZEXT_TRUNC1:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC1]] 1856 CHECK: [[SHIFT_AMT:%[0-9]+]]:_(s64) = G_CONSTANT i64 32 1857 CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT_TRUNC1]]:_, [[SHIFT_AMT]] 1858 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[ZEXT_TRUNC0]]:_, [[SHL]] 1859 CHECK: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[OR]]:_(s64) 1860 )"; 1861 1862 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1863 } 1864 1865 TEST_F(AArch64GISelMITest, WidenSEXTINREG) { 1866 setUp(); 1867 if (!TM) 1868 return; 1869 1870 // Declare your legalization info 1871 DefineLegalizerInfo(A, { 1872 getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); 1873 }); 1874 // Build Instr 1875 auto MIB = B.buildInstr( 1876 TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)}, 1877 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}), 1878 uint64_t(8)}); 1879 AInfo Info(MF->getSubtarget()); 1880 DummyGISelObserver Observer; 1881 LegalizerHelper Helper(*MF, Info, Observer, B); 1882 // Perform Legalization 1883 B.setInstr(*MIB); 1884 ASSERT_TRUE(Helper.widenScalar(*MIB, 0, LLT::scalar(64)) == 1885 LegalizerHelper::LegalizeResult::Legalized); 1886 1887 auto CheckStr = R"( 1888 CHECK: [[T0:%[0-9]+]]:_(s32) = G_TRUNC 1889 CHECK: [[T1:%[0-9]+]]:_(s64) = G_ANYEXT [[T0]]:_(s32) 1890 CHECK: [[T2:%[0-9]+]]:_(s64) = G_SEXT_INREG [[T1]]:_, 8 1891 CHECK: [[T3:%[0-9]+]]:_(s32) = G_TRUNC [[T2]]:_(s64) 1892 )"; 1893 1894 // Check 1895 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1896 } 1897 1898 TEST_F(AArch64GISelMITest, NarrowSEXTINREG) { 1899 setUp(); 1900 if (!TM) 1901 return; 1902 1903 // Declare your legalization info, these aren't actually relevant to the test. 1904 DefineLegalizerInfo(A, { 1905 getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); 1906 }); 1907 // Build Instr 1908 auto MIB = B.buildInstr( 1909 TargetOpcode::G_SEXT_INREG, {LLT::scalar(16)}, 1910 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(16)}, {Copies[0]}), 1911 uint64_t(8)}); 1912 AInfo Info(MF->getSubtarget()); 1913 DummyGISelObserver Observer; 1914 LegalizerHelper Helper(*MF, Info, Observer, B); 1915 // Perform Legalization 1916 B.setInstr(*MIB); 1917 ASSERT_TRUE(Helper.narrowScalar(*MIB, 0, LLT::scalar(10)) == 1918 LegalizerHelper::LegalizeResult::Legalized); 1919 1920 auto CheckStr = R"( 1921 CHECK: [[T0:%[0-9]+]]:_(s16) = G_TRUNC 1922 CHECK: [[T1:%[0-9]+]]:_(s10) = G_TRUNC [[T0]]:_(s16) 1923 CHECK: [[T2:%[0-9]+]]:_(s10) = G_SEXT_INREG [[T1]]:_, 8 1924 CHECK: [[T3:%[0-9]+]]:_(s16) = G_SEXT [[T2]]:_(s10) 1925 )"; 1926 1927 // Check 1928 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 1929 } 1930 1931 TEST_F(AArch64GISelMITest, NarrowSEXTINREG2) { 1932 setUp(); 1933 if (!TM) 1934 return; 1935 1936 // Declare your legalization info, these aren't actually relevant to the test. 1937 DefineLegalizerInfo( 1938 A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); }); 1939 // Build Instr 1940 auto MIB = B.buildInstr( 1941 TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)}, 1942 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}), 1943 uint64_t(9)}); 1944 AInfo Info(MF->getSubtarget()); 1945 DummyGISelObserver Observer; 1946 LegalizerHelper Helper(*MF, Info, Observer, B); 1947 // Perform Legalization 1948 B.setInstr(*MIB); 1949 ASSERT_TRUE(Helper.narrowScalar(*MIB, 0, LLT::scalar(8)) == 1950 LegalizerHelper::LegalizeResult::Legalized); 1951 1952 auto CheckStr = R"( 1953 CHECK: [[T0:%[0-9]+]]:_(s32) = G_TRUNC 1954 CHECK: [[T1:%[0-9]+]]:_(s8), [[T2:%[0-9]+]]:_(s8), [[T3:%[0-9]+]]:_(s8), [[T4:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[T0]]:_(s32) 1955 CHECK: [[CST2:%[0-9]+]]:_(s8) = G_CONSTANT i8 7 1956 CHECK: [[T5:%[0-9]+]]:_(s8) = G_SEXT_INREG [[T2]]:_, 1 1957 CHECK: [[T6:%[0-9]+]]:_(s8) = G_ASHR [[T5]]:_, [[CST2]]:_ 1958 CHECK: [[T7:%[0-9]+]]:_(s32) = G_MERGE_VALUES [[T1]]:_(s8), [[T5]]:_(s8), [[T6]]:_(s8), [[T6]]:_(s8) 1959 )"; 1960 1961 // Check 1962 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 1963 } 1964 1965 TEST_F(AArch64GISelMITest, LowerSEXTINREG) { 1966 setUp(); 1967 if (!TM) 1968 return; 1969 1970 // Declare your legalization info, these aren't actually relevant to the test. 1971 DefineLegalizerInfo( 1972 A, { getActionDefinitionsBuilder(G_SEXT_INREG).legalForTypeWithAnyImm({s64}); }); 1973 // Build Instr 1974 auto MIB = B.buildInstr( 1975 TargetOpcode::G_SEXT_INREG, {LLT::scalar(32)}, 1976 {B.buildInstr(TargetOpcode::G_TRUNC, {LLT::scalar(32)}, {Copies[0]}), 1977 uint64_t(8)}); 1978 AInfo Info(MF->getSubtarget()); 1979 DummyGISelObserver Observer; 1980 LegalizerHelper Helper(*MF, Info, Observer, B); 1981 // Perform Legalization 1982 B.setInstr(*MIB); 1983 ASSERT_TRUE(Helper.lower(*MIB, 0, LLT()) == 1984 LegalizerHelper::LegalizeResult::Legalized); 1985 1986 auto CheckStr = R"( 1987 CHECK: [[T1:%[0-9]+]]:_(s32) = G_TRUNC 1988 CHECK: [[CST:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 1989 CHECK: [[T2:%[0-9]+]]:_(s32) = G_SHL [[T1]]:_, [[CST]]:_ 1990 CHECK: [[T3:%[0-9]+]]:_(s32) = G_ASHR [[T2]]:_, [[CST]]:_ 1991 )"; 1992 1993 // Check 1994 ASSERT_TRUE(CheckMachineFunction(*MF, CheckStr)); 1995 } 1996 1997 TEST_F(AArch64GISelMITest, LibcallFPExt) { 1998 setUp(); 1999 if (!TM) 2000 return; 2001 2002 // Declare your legalization info 2003 DefineLegalizerInfo(A, { 2004 getActionDefinitionsBuilder(G_FPEXT).libcallFor({{s32, s16}, {s128, s64}}); 2005 }); 2006 2007 LLT S16{LLT::scalar(16)}; 2008 LLT S32{LLT::scalar(32)}; 2009 LLT S128{LLT::scalar(128)}; 2010 auto MIBTrunc = B.buildTrunc(S16, Copies[0]); 2011 auto MIBFPExt1 = 2012 B.buildInstr(TargetOpcode::G_FPEXT, {S32}, {MIBTrunc}); 2013 2014 auto MIBFPExt2 = 2015 B.buildInstr(TargetOpcode::G_FPEXT, {S128}, {Copies[1]}); 2016 AInfo Info(MF->getSubtarget()); 2017 DummyGISelObserver Observer; 2018 LegalizerHelper Helper(*MF, Info, Observer, B); 2019 LostDebugLocObserver DummyLocObserver(""); 2020 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2021 Helper.libcall(*MIBFPExt1, DummyLocObserver)); 2022 2023 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2024 Helper.libcall(*MIBFPExt2, DummyLocObserver)); 2025 auto CheckStr = R"( 2026 CHECK: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC 2027 CHECK: $h0 = COPY [[TRUNC]] 2028 CHECK: BL &__gnu_h2f_ieee 2029 CHECK: $d0 = COPY 2030 CHECK: BL &__extenddftf2 2031 )"; 2032 2033 // Check 2034 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2035 } 2036 2037 TEST_F(AArch64GISelMITest, LibcallFPTrunc) { 2038 setUp(); 2039 if (!TM) 2040 return; 2041 2042 // Declare your legalization info 2043 DefineLegalizerInfo(A, { 2044 getActionDefinitionsBuilder(G_FPTRUNC).libcallFor({{s16, s32}, {s64, s128}}); 2045 }); 2046 2047 LLT S16{LLT::scalar(16)}; 2048 LLT S32{LLT::scalar(32)}; 2049 LLT S64{LLT::scalar(64)}; 2050 LLT S128{LLT::scalar(128)}; 2051 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2052 auto MIBFPTrunc1 = 2053 B.buildInstr(TargetOpcode::G_FPTRUNC, {S16}, {MIBTrunc}); 2054 2055 auto MIBMerge = B.buildMerge(S128, {Copies[1], Copies[2]}); 2056 2057 auto MIBFPTrunc2 = 2058 B.buildInstr(TargetOpcode::G_FPTRUNC, {S64}, {MIBMerge}); 2059 AInfo Info(MF->getSubtarget()); 2060 DummyGISelObserver Observer; 2061 LostDebugLocObserver DummyLocObserver(""); 2062 LegalizerHelper Helper(*MF, Info, Observer, B); 2063 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2064 Helper.libcall(*MIBFPTrunc1, DummyLocObserver)); 2065 2066 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2067 Helper.libcall(*MIBFPTrunc2, DummyLocObserver)); 2068 auto CheckStr = R"( 2069 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2070 CHECK: $s0 = COPY [[TRUNC]] 2071 CHECK: BL &__gnu_f2h_ieee 2072 CHECK: $q0 = COPY 2073 CHECK: BL &__trunctfdf2 2074 )"; 2075 2076 // Check 2077 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2078 } 2079 2080 TEST_F(AArch64GISelMITest, LibcallSimple) { 2081 setUp(); 2082 if (!TM) 2083 return; 2084 2085 // Declare your legalization info 2086 DefineLegalizerInfo(A, { 2087 getActionDefinitionsBuilder(G_FADD).libcallFor({s16}); 2088 }); 2089 2090 LLT S16{LLT::scalar(16)}; 2091 auto MIBTrunc = B.buildTrunc(S16, Copies[0]); 2092 auto MIBFADD = 2093 B.buildInstr(TargetOpcode::G_FADD, {S16}, {MIBTrunc, MIBTrunc}); 2094 2095 AInfo Info(MF->getSubtarget()); 2096 DummyGISelObserver Observer; 2097 LostDebugLocObserver DummyLocObserver(""); 2098 LegalizerHelper Helper(*MF, Info, Observer, B); 2099 // Make sure we do not crash anymore 2100 EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize, 2101 Helper.libcall(*MIBFADD, DummyLocObserver)); 2102 } 2103 2104 TEST_F(AArch64GISelMITest, LibcallSRem) { 2105 setUp(); 2106 if (!TM) 2107 return; 2108 2109 // Declare your legalization info 2110 DefineLegalizerInfo(A, { 2111 getActionDefinitionsBuilder(G_SREM).libcallFor({s32, s64, s128}); 2112 }); 2113 2114 LLT S32{LLT::scalar(32)}; 2115 LLT S64{LLT::scalar(64)}; 2116 LLT S128{LLT::scalar(128)}; 2117 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2118 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2119 2120 auto MIBSRem32 = 2121 B.buildInstr(TargetOpcode::G_SREM, {S32}, {MIBTrunc, MIBTrunc}); 2122 auto MIBSRem64 = 2123 B.buildInstr(TargetOpcode::G_SREM, {S64}, {Copies[0], Copies[0]}); 2124 auto MIBSRem128 = 2125 B.buildInstr(TargetOpcode::G_SREM, {S128}, {MIBExt, MIBExt}); 2126 2127 AInfo Info(MF->getSubtarget()); 2128 DummyGISelObserver Observer; 2129 LostDebugLocObserver DummyLocObserver(""); 2130 LegalizerHelper Helper(*MF, Info, Observer, B); 2131 2132 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2133 Helper.libcall(*MIBSRem32, DummyLocObserver)); 2134 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2135 Helper.libcall(*MIBSRem64, DummyLocObserver)); 2136 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2137 Helper.libcall(*MIBSRem128, DummyLocObserver)); 2138 2139 auto CheckStr = R"( 2140 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 2141 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2142 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 2143 CHECK: $w0 = COPY [[TRUNC]] 2144 CHECK: $w1 = COPY [[TRUNC]] 2145 CHECK: BL &__modsi3 2146 CHECK: $x0 = COPY [[COPY]] 2147 CHECK: $x1 = COPY [[COPY]] 2148 CHECK: BL &__moddi3 2149 CHECK: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]] 2150 CHECK: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]] 2151 CHECK: $x0 = COPY [[UV]] 2152 CHECK: $x1 = COPY [[UV1]] 2153 CHECK: $x2 = COPY [[UV2]] 2154 CHECK: $x3 = COPY [[UV3]] 2155 CHECK: BL &__modti3 2156 )"; 2157 2158 // Check 2159 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2160 } 2161 2162 TEST_F(AArch64GISelMITest, LibcallURem) { 2163 setUp(); 2164 if (!TM) 2165 return; 2166 2167 // Declare your legalization info 2168 DefineLegalizerInfo(A, { 2169 getActionDefinitionsBuilder(G_UREM).libcallFor({s32, s64, s128}); 2170 }); 2171 2172 LLT S32{LLT::scalar(32)}; 2173 LLT S64{LLT::scalar(64)}; 2174 LLT S128{LLT::scalar(128)}; 2175 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2176 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2177 2178 auto MIBURem32 = 2179 B.buildInstr(TargetOpcode::G_UREM, {S32}, {MIBTrunc, MIBTrunc}); 2180 auto MIBURem64 = 2181 B.buildInstr(TargetOpcode::G_UREM, {S64}, {Copies[0], Copies[0]}); 2182 auto MIBURem128 = 2183 B.buildInstr(TargetOpcode::G_UREM, {S128}, {MIBExt, MIBExt}); 2184 2185 AInfo Info(MF->getSubtarget()); 2186 DummyGISelObserver Observer; 2187 LostDebugLocObserver DummyLocObserver(""); 2188 LegalizerHelper Helper(*MF, Info, Observer, B); 2189 2190 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2191 Helper.libcall(*MIBURem32, DummyLocObserver)); 2192 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2193 Helper.libcall(*MIBURem64, DummyLocObserver)); 2194 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2195 Helper.libcall(*MIBURem128, DummyLocObserver)); 2196 2197 const auto *CheckStr = R"( 2198 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 2199 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2200 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 2201 CHECK: $w0 = COPY [[TRUNC]] 2202 CHECK: $w1 = COPY [[TRUNC]] 2203 CHECK: BL &__umodsi3 2204 CHECK: $x0 = COPY [[COPY]] 2205 CHECK: $x1 = COPY [[COPY]] 2206 CHECK: BL &__umoddi3 2207 CHECK: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]] 2208 CHECK: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]] 2209 CHECK: $x0 = COPY [[UV]] 2210 CHECK: $x1 = COPY [[UV1]] 2211 CHECK: $x2 = COPY [[UV2]] 2212 CHECK: $x3 = COPY [[UV3]] 2213 CHECK: BL &__umodti3 2214 )"; 2215 2216 // Check 2217 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2218 } 2219 2220 TEST_F(AArch64GISelMITest, LibcallCtlzZeroUndef) { 2221 setUp(); 2222 if (!TM) 2223 return; 2224 2225 // Declare your legalization info 2226 DefineLegalizerInfo(A, { 2227 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF) 2228 .libcallFor({{s32, s32}, {s64, s64}, {s128, s128}}); 2229 }); 2230 2231 LLT S32{LLT::scalar(32)}; 2232 LLT S64{LLT::scalar(64)}; 2233 LLT S128{LLT::scalar(128)}; 2234 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2235 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2236 2237 auto MIBCtlz32 = 2238 B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {S32}, {MIBTrunc}); 2239 auto MIBCtlz64 = 2240 B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {S64}, {Copies[0]}); 2241 auto MIBCtlz128 = 2242 B.buildInstr(TargetOpcode::G_CTLZ_ZERO_UNDEF, {S128}, {MIBExt}); 2243 2244 AInfo Info(MF->getSubtarget()); 2245 DummyGISelObserver Observer; 2246 LostDebugLocObserver DummyLocObserver(""); 2247 LegalizerHelper Helper(*MF, Info, Observer, B); 2248 2249 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2250 Helper.libcall(*MIBCtlz32, DummyLocObserver)); 2251 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2252 Helper.libcall(*MIBCtlz64, DummyLocObserver)); 2253 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2254 Helper.libcall(*MIBCtlz128, DummyLocObserver)); 2255 2256 const auto *CheckStr = R"( 2257 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 2258 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2259 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 2260 CHECK: $w0 = COPY [[TRUNC]] 2261 CHECK: BL &__clzsi2 2262 CHECK: $x0 = COPY [[COPY]] 2263 CHECK: BL &__clzdi2 2264 CHECK: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT]] 2265 CHECK: $x0 = COPY [[UV]] 2266 CHECK: $x1 = COPY [[UV1]] 2267 CHECK: BL &__clzti2 2268 )"; 2269 2270 // Check 2271 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2272 } 2273 2274 TEST_F(AArch64GISelMITest, LibcallFAdd) { 2275 setUp(); 2276 if (!TM) 2277 return; 2278 2279 // Declare your legalization info 2280 DefineLegalizerInfo(A, { 2281 getActionDefinitionsBuilder(G_FADD).libcallFor({s32, s64, s128}); 2282 }); 2283 2284 LLT S32{LLT::scalar(32)}; 2285 LLT S64{LLT::scalar(64)}; 2286 LLT S128{LLT::scalar(128)}; 2287 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2288 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2289 2290 auto MIBAdd32 = 2291 B.buildInstr(TargetOpcode::G_FADD, {S32}, {MIBTrunc, MIBTrunc}); 2292 auto MIBAdd64 = 2293 B.buildInstr(TargetOpcode::G_FADD, {S64}, {Copies[0], Copies[0]}); 2294 auto MIBAdd128 = B.buildInstr(TargetOpcode::G_FADD, {S128}, {MIBExt, MIBExt}); 2295 2296 AInfo Info(MF->getSubtarget()); 2297 DummyGISelObserver Observer; 2298 LostDebugLocObserver DummyLocObserver(""); 2299 LegalizerHelper Helper(*MF, Info, Observer, B); 2300 2301 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2302 Helper.libcall(*MIBAdd32, DummyLocObserver)); 2303 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2304 Helper.libcall(*MIBAdd64, DummyLocObserver)); 2305 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2306 Helper.libcall(*MIBAdd128, DummyLocObserver)); 2307 2308 const auto *CheckStr = R"( 2309 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 2310 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2311 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 2312 CHECK: $s0 = COPY [[TRUNC]] 2313 CHECK: $s1 = COPY [[TRUNC]] 2314 CHECK: BL &__addsf3 2315 CHECK: $d0 = COPY [[COPY]] 2316 CHECK: $d1 = COPY [[COPY]] 2317 CHECK: BL &__adddf3 2318 CHECK: $q0 = COPY [[ANYEXT]] 2319 CHECK: $q1 = COPY [[ANYEXT]] 2320 CHECK: BL &__addtf3 2321 )"; 2322 2323 // Check 2324 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2325 } 2326 2327 TEST_F(AArch64GISelMITest, LibcallFSub) { 2328 setUp(); 2329 if (!TM) 2330 return; 2331 2332 // Declare your legalization info 2333 DefineLegalizerInfo(A, { 2334 getActionDefinitionsBuilder(G_FSUB).libcallFor({s32, s64, s128}); 2335 }); 2336 2337 LLT S32{LLT::scalar(32)}; 2338 LLT S64{LLT::scalar(64)}; 2339 LLT S128{LLT::scalar(128)}; 2340 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2341 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2342 2343 auto MIBSub32 = 2344 B.buildInstr(TargetOpcode::G_FSUB, {S32}, {MIBTrunc, MIBTrunc}); 2345 auto MIBSub64 = 2346 B.buildInstr(TargetOpcode::G_FSUB, {S64}, {Copies[0], Copies[0]}); 2347 auto MIBSub128 = B.buildInstr(TargetOpcode::G_FSUB, {S128}, {MIBExt, MIBExt}); 2348 2349 AInfo Info(MF->getSubtarget()); 2350 DummyGISelObserver Observer; 2351 LostDebugLocObserver DummyLocObserver(""); 2352 LegalizerHelper Helper(*MF, Info, Observer, B); 2353 2354 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2355 Helper.libcall(*MIBSub32, DummyLocObserver)); 2356 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2357 Helper.libcall(*MIBSub64, DummyLocObserver)); 2358 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2359 Helper.libcall(*MIBSub128, DummyLocObserver)); 2360 2361 const auto *CheckStr = R"( 2362 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 2363 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2364 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 2365 CHECK: $s0 = COPY [[TRUNC]] 2366 CHECK: $s1 = COPY [[TRUNC]] 2367 CHECK: BL &__subsf3 2368 CHECK: $d0 = COPY [[COPY]] 2369 CHECK: $d1 = COPY [[COPY]] 2370 CHECK: BL &__subdf3 2371 CHECK: $q0 = COPY [[ANYEXT]] 2372 CHECK: $q1 = COPY [[ANYEXT]] 2373 CHECK: BL &__subtf3 2374 )"; 2375 2376 // Check 2377 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2378 } 2379 2380 TEST_F(AArch64GISelMITest, LibcallFMul) { 2381 setUp(); 2382 if (!TM) 2383 return; 2384 2385 // Declare your legalization info 2386 DefineLegalizerInfo(A, { 2387 getActionDefinitionsBuilder(G_FMUL).libcallFor({s32, s64, s128}); 2388 }); 2389 2390 LLT S32{LLT::scalar(32)}; 2391 LLT S64{LLT::scalar(64)}; 2392 LLT S128{LLT::scalar(128)}; 2393 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2394 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2395 2396 auto MIBMul32 = 2397 B.buildInstr(TargetOpcode::G_FMUL, {S32}, {MIBTrunc, MIBTrunc}); 2398 auto MIBMul64 = 2399 B.buildInstr(TargetOpcode::G_FMUL, {S64}, {Copies[0], Copies[0]}); 2400 auto MIBMul128 = B.buildInstr(TargetOpcode::G_FMUL, {S128}, {MIBExt, MIBExt}); 2401 2402 AInfo Info(MF->getSubtarget()); 2403 DummyGISelObserver Observer; 2404 LegalizerHelper Helper(*MF, Info, Observer, B); 2405 LostDebugLocObserver DummyLocObserver(""); 2406 2407 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2408 Helper.libcall(*MIBMul32, DummyLocObserver)); 2409 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2410 Helper.libcall(*MIBMul64, DummyLocObserver)); 2411 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2412 Helper.libcall(*MIBMul128, DummyLocObserver)); 2413 2414 const auto *CheckStr = R"( 2415 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 2416 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2417 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 2418 CHECK: $s0 = COPY [[TRUNC]] 2419 CHECK: $s1 = COPY [[TRUNC]] 2420 CHECK: BL &__mulsf3 2421 CHECK: $d0 = COPY [[COPY]] 2422 CHECK: $d1 = COPY [[COPY]] 2423 CHECK: BL &__muldf3 2424 CHECK: $q0 = COPY [[ANYEXT]] 2425 CHECK: $q1 = COPY [[ANYEXT]] 2426 CHECK: BL &__multf3 2427 )"; 2428 2429 // Check 2430 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2431 } 2432 2433 TEST_F(AArch64GISelMITest, LibcallFDiv) { 2434 setUp(); 2435 if (!TM) 2436 return; 2437 2438 // Declare your legalization info 2439 DefineLegalizerInfo(A, { 2440 getActionDefinitionsBuilder(G_FDIV).libcallFor({s32, s64, s128}); 2441 }); 2442 2443 LLT S32{LLT::scalar(32)}; 2444 LLT S64{LLT::scalar(64)}; 2445 LLT S128{LLT::scalar(128)}; 2446 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2447 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2448 2449 auto MIBDiv32 = 2450 B.buildInstr(TargetOpcode::G_FDIV, {S32}, {MIBTrunc, MIBTrunc}); 2451 auto MIBDiv64 = 2452 B.buildInstr(TargetOpcode::G_FDIV, {S64}, {Copies[0], Copies[0]}); 2453 auto MIBDiv128 = B.buildInstr(TargetOpcode::G_FDIV, {S128}, {MIBExt, MIBExt}); 2454 2455 AInfo Info(MF->getSubtarget()); 2456 DummyGISelObserver Observer; 2457 LostDebugLocObserver DummyLocObserver(""); 2458 LegalizerHelper Helper(*MF, Info, Observer, B); 2459 2460 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2461 Helper.libcall(*MIBDiv32, DummyLocObserver)); 2462 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2463 Helper.libcall(*MIBDiv64, DummyLocObserver)); 2464 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2465 Helper.libcall(*MIBDiv128, DummyLocObserver)); 2466 2467 const auto *CheckStr = R"( 2468 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 2469 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2470 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 2471 CHECK: $s0 = COPY [[TRUNC]] 2472 CHECK: $s1 = COPY [[TRUNC]] 2473 CHECK: BL &__divsf3 2474 CHECK: $d0 = COPY [[COPY]] 2475 CHECK: $d1 = COPY [[COPY]] 2476 CHECK: BL &__divdf3 2477 CHECK: $q0 = COPY [[ANYEXT]] 2478 CHECK: $q1 = COPY [[ANYEXT]] 2479 CHECK: BL &__divtf3 2480 )"; 2481 2482 // Check 2483 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2484 } 2485 2486 TEST_F(AArch64GISelMITest, LibcallFExp) { 2487 setUp(); 2488 if (!TM) 2489 return; 2490 2491 // Declare your legalization info 2492 DefineLegalizerInfo(A, { 2493 getActionDefinitionsBuilder(G_FEXP).libcallFor({s32, s64, s128}); 2494 }); 2495 2496 LLT S32{LLT::scalar(32)}; 2497 LLT S64{LLT::scalar(64)}; 2498 LLT S128{LLT::scalar(128)}; 2499 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2500 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2501 2502 auto MIBExp32 = B.buildInstr(TargetOpcode::G_FEXP, {S32}, {MIBTrunc}); 2503 auto MIBExp64 = B.buildInstr(TargetOpcode::G_FEXP, {S64}, {Copies[0]}); 2504 auto MIBExp128 = B.buildInstr(TargetOpcode::G_FEXP, {S128}, {MIBExt}); 2505 2506 AInfo Info(MF->getSubtarget()); 2507 DummyGISelObserver Observer; 2508 LostDebugLocObserver DummyLocObserver(""); 2509 LegalizerHelper Helper(*MF, Info, Observer, B); 2510 2511 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2512 Helper.libcall(*MIBExp32, DummyLocObserver)); 2513 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2514 Helper.libcall(*MIBExp64, DummyLocObserver)); 2515 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2516 Helper.libcall(*MIBExp128, DummyLocObserver)); 2517 2518 const auto *CheckStr = R"( 2519 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 2520 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2521 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 2522 CHECK: $s0 = COPY [[TRUNC]] 2523 CHECK: BL &expf 2524 CHECK: $d0 = COPY [[COPY]] 2525 CHECK: BL &exp 2526 CHECK: $q0 = COPY [[ANYEXT]] 2527 CHECK: BL &expl 2528 )"; 2529 2530 // Check 2531 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2532 } 2533 2534 TEST_F(AArch64GISelMITest, LibcallFExp2) { 2535 setUp(); 2536 if (!TM) 2537 return; 2538 2539 // Declare your legalization info 2540 DefineLegalizerInfo(A, { 2541 getActionDefinitionsBuilder(G_FEXP2).libcallFor({s32, s64, s128}); 2542 }); 2543 2544 LLT S32{LLT::scalar(32)}; 2545 LLT S64{LLT::scalar(64)}; 2546 LLT S128{LLT::scalar(128)}; 2547 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2548 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2549 2550 auto MIBExp232 = B.buildInstr(TargetOpcode::G_FEXP2, {S32}, {MIBTrunc}); 2551 auto MIBExp264 = B.buildInstr(TargetOpcode::G_FEXP2, {S64}, {Copies[0]}); 2552 auto MIBExp2128 = B.buildInstr(TargetOpcode::G_FEXP2, {S128}, {MIBExt}); 2553 2554 AInfo Info(MF->getSubtarget()); 2555 DummyGISelObserver Observer; 2556 LostDebugLocObserver DummyLocObserver(""); 2557 LegalizerHelper Helper(*MF, Info, Observer, B); 2558 2559 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2560 Helper.libcall(*MIBExp232, DummyLocObserver)); 2561 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2562 Helper.libcall(*MIBExp264, DummyLocObserver)); 2563 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2564 Helper.libcall(*MIBExp2128, DummyLocObserver)); 2565 2566 const auto *CheckStr = R"( 2567 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 2568 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2569 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 2570 CHECK: $s0 = COPY [[TRUNC]] 2571 CHECK: BL &exp2f 2572 CHECK: $d0 = COPY [[COPY]] 2573 CHECK: BL &exp2 2574 CHECK: $q0 = COPY [[ANYEXT]] 2575 CHECK: BL &exp2l 2576 )"; 2577 2578 // Check 2579 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2580 } 2581 2582 TEST_F(AArch64GISelMITest, LibcallFRem) { 2583 setUp(); 2584 if (!TM) 2585 return; 2586 2587 // Declare your legalization info 2588 DefineLegalizerInfo(A, { 2589 getActionDefinitionsBuilder(G_FREM).libcallFor({s32, s64, s128}); 2590 }); 2591 2592 LLT S32{LLT::scalar(32)}; 2593 LLT S64{LLT::scalar(64)}; 2594 LLT S128{LLT::scalar(128)}; 2595 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2596 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2597 2598 auto MIBFRem32 = B.buildInstr(TargetOpcode::G_FREM, {S32}, {MIBTrunc}); 2599 auto MIBFRem64 = B.buildInstr(TargetOpcode::G_FREM, {S64}, {Copies[0]}); 2600 auto MIBFRem128 = B.buildInstr(TargetOpcode::G_FREM, {S128}, {MIBExt}); 2601 2602 AInfo Info(MF->getSubtarget()); 2603 DummyGISelObserver Observer; 2604 LostDebugLocObserver DummyLocObserver(""); 2605 LegalizerHelper Helper(*MF, Info, Observer, B); 2606 2607 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2608 Helper.libcall(*MIBFRem32, DummyLocObserver)); 2609 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2610 Helper.libcall(*MIBFRem64, DummyLocObserver)); 2611 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2612 Helper.libcall(*MIBFRem128, DummyLocObserver)); 2613 2614 const auto *CheckStr = R"( 2615 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 2616 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2617 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 2618 CHECK: $s0 = COPY [[TRUNC]] 2619 CHECK: BL &fmodf 2620 CHECK: $d0 = COPY [[COPY]] 2621 CHECK: BL &fmod 2622 CHECK: $q0 = COPY [[ANYEXT]] 2623 CHECK: BL &fmodl 2624 )"; 2625 2626 // Check 2627 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2628 } 2629 2630 TEST_F(AArch64GISelMITest, LibcallFPow) { 2631 setUp(); 2632 if (!TM) 2633 return; 2634 2635 // Declare your legalization info 2636 DefineLegalizerInfo(A, { 2637 getActionDefinitionsBuilder(G_FPOW).libcallFor({s32, s64, s128}); 2638 }); 2639 2640 LLT S32{LLT::scalar(32)}; 2641 LLT S64{LLT::scalar(64)}; 2642 LLT S128{LLT::scalar(128)}; 2643 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2644 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2645 2646 auto MIBPow32 = B.buildInstr(TargetOpcode::G_FPOW, {S32}, {MIBTrunc}); 2647 auto MIBPow64 = B.buildInstr(TargetOpcode::G_FPOW, {S64}, {Copies[0]}); 2648 auto MIBPow128 = B.buildInstr(TargetOpcode::G_FPOW, {S128}, {MIBExt}); 2649 2650 AInfo Info(MF->getSubtarget()); 2651 DummyGISelObserver Observer; 2652 LostDebugLocObserver DummyLocObserver(""); 2653 LegalizerHelper Helper(*MF, Info, Observer, B); 2654 2655 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2656 Helper.libcall(*MIBPow32, DummyLocObserver)); 2657 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2658 Helper.libcall(*MIBPow64, DummyLocObserver)); 2659 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2660 Helper.libcall(*MIBPow128, DummyLocObserver)); 2661 2662 const auto *CheckStr = R"( 2663 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 2664 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2665 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 2666 CHECK: $s0 = COPY [[TRUNC]] 2667 CHECK: BL &powf 2668 CHECK: $d0 = COPY [[COPY]] 2669 CHECK: BL &pow 2670 CHECK: $q0 = COPY [[ANYEXT]] 2671 CHECK: BL &powl 2672 )"; 2673 2674 // Check 2675 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2676 } 2677 2678 TEST_F(AArch64GISelMITest, LibcallFMa) { 2679 setUp(); 2680 if (!TM) 2681 return; 2682 2683 // Declare your legalization info 2684 DefineLegalizerInfo(A, { 2685 getActionDefinitionsBuilder(G_FMA).libcallFor({s32, s64, s128}); 2686 }); 2687 2688 LLT S32{LLT::scalar(32)}; 2689 LLT S64{LLT::scalar(64)}; 2690 LLT S128{LLT::scalar(128)}; 2691 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2692 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2693 2694 auto MIBMa32 = B.buildInstr(TargetOpcode::G_FMA, {S32}, {MIBTrunc, MIBTrunc}); 2695 auto MIBMa64 = 2696 B.buildInstr(TargetOpcode::G_FMA, {S64}, {Copies[0], Copies[0]}); 2697 auto MIBMa128 = B.buildInstr(TargetOpcode::G_FMA, {S128}, {MIBExt, MIBExt}); 2698 2699 AInfo Info(MF->getSubtarget()); 2700 DummyGISelObserver Observer; 2701 LostDebugLocObserver DummyLocObserver(""); 2702 LegalizerHelper Helper(*MF, Info, Observer, B); 2703 2704 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2705 Helper.libcall(*MIBMa32, DummyLocObserver)); 2706 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2707 Helper.libcall(*MIBMa64, DummyLocObserver)); 2708 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2709 Helper.libcall(*MIBMa128, DummyLocObserver)); 2710 2711 const auto *CheckStr = R"( 2712 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 2713 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2714 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 2715 CHECK: $s0 = COPY [[TRUNC]] 2716 CHECK: BL &fmaf 2717 CHECK: $d0 = COPY [[COPY]] 2718 CHECK: BL &fma 2719 CHECK: $q0 = COPY [[ANYEXT]] 2720 CHECK: BL &fmal 2721 )"; 2722 2723 // Check 2724 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2725 } 2726 2727 TEST_F(AArch64GISelMITest, LibcallFCeil) { 2728 setUp(); 2729 if (!TM) 2730 return; 2731 2732 // Declare your legalization info 2733 DefineLegalizerInfo(A, { 2734 getActionDefinitionsBuilder(G_FCEIL).libcallFor({s32, s64, s128}); 2735 }); 2736 2737 LLT S32{LLT::scalar(32)}; 2738 LLT S64{LLT::scalar(64)}; 2739 LLT S128{LLT::scalar(128)}; 2740 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2741 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2742 2743 auto MIBCeil32 = B.buildInstr(TargetOpcode::G_FCEIL, {S32}, {MIBTrunc}); 2744 auto MIBCeil64 = B.buildInstr(TargetOpcode::G_FCEIL, {S64}, {Copies[0]}); 2745 auto MIBCeil128 = B.buildInstr(TargetOpcode::G_FCEIL, {S128}, {MIBExt}); 2746 2747 AInfo Info(MF->getSubtarget()); 2748 DummyGISelObserver Observer; 2749 LegalizerHelper Helper(*MF, Info, Observer, B); 2750 LostDebugLocObserver DummyLocObserver(""); 2751 2752 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2753 Helper.libcall(*MIBCeil32, DummyLocObserver)); 2754 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2755 Helper.libcall(*MIBCeil64, DummyLocObserver)); 2756 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2757 Helper.libcall(*MIBCeil128, DummyLocObserver)); 2758 2759 const auto *CheckStr = R"( 2760 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 2761 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2762 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 2763 CHECK: $s0 = COPY [[TRUNC]] 2764 CHECK: BL &ceilf 2765 CHECK: $d0 = COPY [[COPY]] 2766 CHECK: BL &ceil 2767 CHECK: $q0 = COPY [[ANYEXT]] 2768 CHECK: BL &ceill 2769 )"; 2770 2771 // Check 2772 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2773 } 2774 2775 TEST_F(AArch64GISelMITest, LibcallFFloor) { 2776 setUp(); 2777 if (!TM) 2778 return; 2779 2780 // Declare your legalization info 2781 DefineLegalizerInfo(A, { 2782 getActionDefinitionsBuilder(G_FFLOOR).libcallFor({s32, s64, s128}); 2783 }); 2784 2785 LLT S32{LLT::scalar(32)}; 2786 LLT S64{LLT::scalar(64)}; 2787 LLT S128{LLT::scalar(128)}; 2788 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2789 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2790 2791 auto MIBFloor32 = B.buildInstr(TargetOpcode::G_FFLOOR, {S32}, {MIBTrunc}); 2792 auto MIBFloor64 = B.buildInstr(TargetOpcode::G_FFLOOR, {S64}, {Copies[0]}); 2793 auto MIBFloor128 = B.buildInstr(TargetOpcode::G_FFLOOR, {S128}, {MIBExt}); 2794 2795 AInfo Info(MF->getSubtarget()); 2796 DummyGISelObserver Observer; 2797 LegalizerHelper Helper(*MF, Info, Observer, B); 2798 LostDebugLocObserver DummyLocObserver(""); 2799 2800 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2801 Helper.libcall(*MIBFloor32, DummyLocObserver)); 2802 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2803 Helper.libcall(*MIBFloor64, DummyLocObserver)); 2804 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2805 Helper.libcall(*MIBFloor128, DummyLocObserver)); 2806 2807 const auto *CheckStr = R"( 2808 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 2809 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2810 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 2811 CHECK: $s0 = COPY [[TRUNC]] 2812 CHECK: BL &floorf 2813 CHECK: $d0 = COPY [[COPY]] 2814 CHECK: BL &floor 2815 CHECK: $q0 = COPY [[ANYEXT]] 2816 CHECK: BL &floorl 2817 )"; 2818 2819 // Check 2820 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2821 } 2822 2823 TEST_F(AArch64GISelMITest, LibcallFMinNum) { 2824 setUp(); 2825 if (!TM) 2826 return; 2827 2828 // Declare your legalization info 2829 DefineLegalizerInfo(A, { 2830 getActionDefinitionsBuilder(G_FMINNUM).libcallFor({s32, s64, s128}); 2831 }); 2832 2833 LLT S32{LLT::scalar(32)}; 2834 LLT S64{LLT::scalar(64)}; 2835 LLT S128{LLT::scalar(128)}; 2836 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2837 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2838 2839 auto MIBMin32 = B.buildFMinNum(S32, MIBTrunc, MIBTrunc); 2840 auto MIBMin64 = B.buildFMinNum(S64, Copies[0], Copies[0]); 2841 auto MIBMin128 = B.buildFMinNum(S128, MIBExt, MIBExt); 2842 2843 AInfo Info(MF->getSubtarget()); 2844 DummyGISelObserver Observer; 2845 LegalizerHelper Helper(*MF, Info, Observer, B); 2846 LostDebugLocObserver DummyLocObserver(""); 2847 2848 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2849 Helper.libcall(*MIBMin32, DummyLocObserver)); 2850 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2851 Helper.libcall(*MIBMin64, DummyLocObserver)); 2852 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2853 Helper.libcall(*MIBMin128, DummyLocObserver)); 2854 2855 const auto *CheckStr = R"( 2856 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 2857 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2858 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 2859 CHECK: $s0 = COPY [[TRUNC]] 2860 CHECK: $s1 = COPY [[TRUNC]] 2861 CHECK: BL &fminf 2862 CHECK: $d0 = COPY [[COPY]] 2863 CHECK: $d1 = COPY [[COPY]] 2864 CHECK: BL &fmin 2865 CHECK: $q0 = COPY [[ANYEXT]] 2866 CHECK: $q1 = COPY [[ANYEXT]] 2867 CHECK: BL &fminl 2868 )"; 2869 2870 // Check 2871 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2872 } 2873 2874 TEST_F(AArch64GISelMITest, LibcallFMaxNum) { 2875 setUp(); 2876 if (!TM) 2877 return; 2878 2879 // Declare your legalization info 2880 DefineLegalizerInfo(A, { 2881 getActionDefinitionsBuilder(G_FMAXNUM).libcallFor({s32, s64, s128}); 2882 }); 2883 2884 LLT S32{LLT::scalar(32)}; 2885 LLT S64{LLT::scalar(64)}; 2886 LLT S128{LLT::scalar(128)}; 2887 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2888 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2889 2890 auto MIBMax32 = B.buildFMaxNum(S32, MIBTrunc, MIBTrunc); 2891 auto MIBMax64 = B.buildFMaxNum(S64, Copies[0], Copies[0]); 2892 auto MIBMax128 = B.buildFMaxNum(S128, MIBExt, MIBExt); 2893 2894 AInfo Info(MF->getSubtarget()); 2895 DummyGISelObserver Observer; 2896 LegalizerHelper Helper(*MF, Info, Observer, B); 2897 LostDebugLocObserver DummyLocObserver(""); 2898 2899 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2900 Helper.libcall(*MIBMax32, DummyLocObserver)); 2901 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2902 Helper.libcall(*MIBMax64, DummyLocObserver)); 2903 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2904 Helper.libcall(*MIBMax128, DummyLocObserver)); 2905 2906 const auto *CheckStr = R"( 2907 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 2908 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2909 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 2910 CHECK: $s0 = COPY [[TRUNC]] 2911 CHECK: $s1 = COPY [[TRUNC]] 2912 CHECK: BL &fmaxf 2913 CHECK: $d0 = COPY [[COPY]] 2914 CHECK: $d1 = COPY [[COPY]] 2915 CHECK: BL &fmax 2916 CHECK: $q0 = COPY [[ANYEXT]] 2917 CHECK: $q1 = COPY [[ANYEXT]] 2918 CHECK: BL &fmaxl 2919 )"; 2920 2921 // Check 2922 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2923 } 2924 2925 TEST_F(AArch64GISelMITest, LibcallFSqrt) { 2926 setUp(); 2927 if (!TM) 2928 return; 2929 2930 // Declare your legalization info 2931 DefineLegalizerInfo(A, { 2932 getActionDefinitionsBuilder(G_FSQRT).libcallFor({s32, s64, s128}); 2933 }); 2934 2935 LLT S32{LLT::scalar(32)}; 2936 LLT S64{LLT::scalar(64)}; 2937 LLT S128{LLT::scalar(128)}; 2938 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2939 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2940 2941 auto MIBSqrt32 = B.buildInstr(TargetOpcode::G_FSQRT, {S32}, {MIBTrunc}); 2942 auto MIBSqrt64 = B.buildInstr(TargetOpcode::G_FSQRT, {S64}, {Copies[0]}); 2943 auto MIBSqrt128 = B.buildInstr(TargetOpcode::G_FSQRT, {S128}, {MIBExt}); 2944 2945 AInfo Info(MF->getSubtarget()); 2946 DummyGISelObserver Observer; 2947 LegalizerHelper Helper(*MF, Info, Observer, B); 2948 LostDebugLocObserver DummyLocObserver(""); 2949 2950 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2951 Helper.libcall(*MIBSqrt32, DummyLocObserver)); 2952 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2953 Helper.libcall(*MIBSqrt64, DummyLocObserver)); 2954 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2955 Helper.libcall(*MIBSqrt128, DummyLocObserver)); 2956 2957 const auto *CheckStr = R"( 2958 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 2959 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 2960 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 2961 CHECK: $s0 = COPY [[TRUNC]] 2962 CHECK: BL &sqrtf 2963 CHECK: $d0 = COPY [[COPY]] 2964 CHECK: BL &sqrt 2965 CHECK: $q0 = COPY [[ANYEXT]] 2966 CHECK: BL &sqrtl 2967 )"; 2968 2969 // Check 2970 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 2971 } 2972 2973 TEST_F(AArch64GISelMITest, LibcallFRint) { 2974 setUp(); 2975 if (!TM) 2976 return; 2977 2978 // Declare your legalization info 2979 DefineLegalizerInfo(A, { 2980 getActionDefinitionsBuilder(G_FRINT).libcallFor({s32, s64, s128}); 2981 }); 2982 2983 LLT S32{LLT::scalar(32)}; 2984 LLT S64{LLT::scalar(64)}; 2985 LLT S128{LLT::scalar(128)}; 2986 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 2987 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 2988 2989 auto MIBRint32 = B.buildInstr(TargetOpcode::G_FRINT, {S32}, {MIBTrunc}); 2990 auto MIBRint64 = B.buildInstr(TargetOpcode::G_FRINT, {S64}, {Copies[0]}); 2991 auto MIBRint128 = B.buildInstr(TargetOpcode::G_FRINT, {S128}, {MIBExt}); 2992 2993 AInfo Info(MF->getSubtarget()); 2994 DummyGISelObserver Observer; 2995 LegalizerHelper Helper(*MF, Info, Observer, B); 2996 LostDebugLocObserver DummyLocObserver(""); 2997 2998 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 2999 Helper.libcall(*MIBRint32, DummyLocObserver)); 3000 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3001 Helper.libcall(*MIBRint64, DummyLocObserver)); 3002 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3003 Helper.libcall(*MIBRint128, DummyLocObserver)); 3004 3005 const auto *CheckStr = R"( 3006 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 3007 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 3008 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 3009 CHECK: $s0 = COPY [[TRUNC]] 3010 CHECK: BL &rintf 3011 CHECK: $d0 = COPY [[COPY]] 3012 CHECK: BL &rint 3013 CHECK: $q0 = COPY [[ANYEXT]] 3014 CHECK: BL &rintl 3015 )"; 3016 3017 // Check 3018 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3019 } 3020 3021 TEST_F(AArch64GISelMITest, LibcallFNearbyInt) { 3022 setUp(); 3023 if (!TM) 3024 return; 3025 3026 // Declare your legalization info 3027 DefineLegalizerInfo(A, { 3028 getActionDefinitionsBuilder(G_FNEARBYINT).libcallFor({s32, s64, s128}); 3029 }); 3030 3031 LLT S32{LLT::scalar(32)}; 3032 LLT S64{LLT::scalar(64)}; 3033 LLT S128{LLT::scalar(128)}; 3034 auto MIBTrunc = B.buildTrunc(S32, Copies[0]); 3035 auto MIBExt = B.buildAnyExt(S128, Copies[0]); 3036 3037 auto MIBNearbyInt32 = 3038 B.buildInstr(TargetOpcode::G_FNEARBYINT, {S32}, {MIBTrunc}); 3039 auto MIBNearbyInt64 = 3040 B.buildInstr(TargetOpcode::G_FNEARBYINT, {S64}, {Copies[0]}); 3041 auto MIBNearbyInt128 = 3042 B.buildInstr(TargetOpcode::G_FNEARBYINT, {S128}, {MIBExt}); 3043 3044 AInfo Info(MF->getSubtarget()); 3045 DummyGISelObserver Observer; 3046 LegalizerHelper Helper(*MF, Info, Observer, B); 3047 LostDebugLocObserver DummyLocObserver(""); 3048 3049 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3050 Helper.libcall(*MIBNearbyInt32, DummyLocObserver)); 3051 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3052 Helper.libcall(*MIBNearbyInt64, DummyLocObserver)); 3053 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3054 Helper.libcall(*MIBNearbyInt128, DummyLocObserver)); 3055 3056 const auto *CheckStr = R"( 3057 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 3058 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC 3059 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT 3060 CHECK: $s0 = COPY [[TRUNC]] 3061 CHECK: BL &nearbyintf 3062 CHECK: $d0 = COPY [[COPY]] 3063 CHECK: BL &nearbyint 3064 CHECK: $q0 = COPY [[ANYEXT]] 3065 CHECK: BL &nearbyintl 3066 )"; 3067 3068 // Check 3069 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3070 } 3071 3072 TEST_F(AArch64GISelMITest, NarrowScalarExtract) { 3073 setUp(); 3074 if (!TM) 3075 return; 3076 3077 // Declare your legalization info 3078 DefineLegalizerInfo(A, { 3079 getActionDefinitionsBuilder(G_UNMERGE_VALUES).legalFor({{s32, s64}}); 3080 getActionDefinitionsBuilder(G_EXTRACT).legalForTypeWithAnyImm({{s16, s32}}); 3081 }); 3082 3083 LLT S16{LLT::scalar(16)}; 3084 LLT S32{LLT::scalar(32)}; 3085 3086 auto MIBExtractS32 = B.buildExtract(S32, Copies[1], 32); 3087 auto MIBExtractS16 = B.buildExtract(S16, Copies[1], 0); 3088 3089 AInfo Info(MF->getSubtarget()); 3090 DummyGISelObserver Observer; 3091 LegalizerHelper Helper(*MF, Info, Observer, B); 3092 3093 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3094 Helper.narrowScalar(*MIBExtractS32, 1, S32)); 3095 3096 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3097 Helper.narrowScalar(*MIBExtractS16, 1, S32)); 3098 3099 const auto *CheckStr = R"( 3100 CHECK: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES 3101 CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY [[UV1]] 3102 CHECK: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES 3103 CHECK: [[EXTR:%[0-9]+]]:_(s16) = G_EXTRACT [[UV3]]:_(s32), 0 3104 CHECK: [[COPY:%[0-9]+]]:_(s16) = COPY [[EXTR]] 3105 )"; 3106 3107 // Check 3108 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3109 } 3110 3111 TEST_F(AArch64GISelMITest, LowerInsert) { 3112 setUp(); 3113 if (!TM) 3114 return; 3115 3116 // Declare your legalization info 3117 DefineLegalizerInfo(A, { getActionDefinitionsBuilder(G_INSERT).lower(); }); 3118 3119 LLT S32{LLT::scalar(32)}; 3120 LLT S64{LLT::scalar(64)}; 3121 LLT P0{LLT::pointer(0, 64)}; 3122 LLT P1{LLT::pointer(1, 32)}; 3123 LLT V2S32{LLT::fixed_vector(2, 32)}; 3124 3125 auto TruncS32 = B.buildTrunc(S32, Copies[0]); 3126 auto IntToPtrP0 = B.buildIntToPtr(P0, Copies[0]); 3127 auto IntToPtrP1 = B.buildIntToPtr(P1, TruncS32); 3128 auto BitcastV2S32 = B.buildBitcast(V2S32, Copies[0]); 3129 3130 auto InsertS64S32 = B.buildInsert(S64, Copies[0], TruncS32, 0); 3131 auto InsertS64P1 = B.buildInsert(S64, Copies[0], IntToPtrP1, 8); 3132 auto InsertP0S32 = B.buildInsert(P0, IntToPtrP0, TruncS32, 16); 3133 auto InsertP0P1 = B.buildInsert(P0, IntToPtrP0, IntToPtrP1, 4); 3134 auto InsertV2S32S32 = B.buildInsert(V2S32, BitcastV2S32, TruncS32, 32); 3135 auto InsertV2S32P1 = B.buildInsert(V2S32, BitcastV2S32, IntToPtrP1, 0); 3136 3137 AInfo Info(MF->getSubtarget()); 3138 DummyGISelObserver Observer; 3139 LegalizerHelper Helper(*MF, Info, Observer, B); 3140 3141 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3142 Helper.lower(*InsertS64S32, 0, LLT{})); 3143 3144 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3145 Helper.lower(*InsertS64P1, 0, LLT{})); 3146 3147 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3148 Helper.lower(*InsertP0S32, 0, LLT{})); 3149 3150 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3151 Helper.lower(*InsertP0P1, 0, LLT{})); 3152 3153 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3154 Helper.lower(*InsertV2S32S32, 0, LLT{})); 3155 3156 EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize, 3157 Helper.lower(*InsertV2S32P1, 0, LLT{})); 3158 3159 const auto *CheckStr = R"( 3160 CHECK: [[S64:%[0-9]+]]:_(s64) = COPY 3161 CHECK: [[S32:%[0-9]+]]:_(s32) = G_TRUNC [[S64]] 3162 CHECK: [[P0:%[0-9]+]]:_(p0) = G_INTTOPTR [[S64]] 3163 CHECK: [[P1:%[0-9]+]]:_(p1) = G_INTTOPTR [[S32]] 3164 CHECK: [[V2S32:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[S64]] 3165 CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[S32]] 3166 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT 3167 CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[S64]]:_, [[C]]:_ 3168 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[ZEXT]]:_ 3169 3170 CHECK: [[PTRTOINT:%[0-9]+]]:_(s32) = G_PTRTOINT [[P1]] 3171 CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[PTRTOINT]] 3172 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT 3173 CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT]]:_, [[C]]:_(s64) 3174 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT 3175 CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[S64]]:_, [[C]]:_ 3176 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[SHL]]:_ 3177 3178 CHECK: [[PTRTOINT:%[0-9]+]]:_(s64) = G_PTRTOINT [[P0]] 3179 CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[S32]] 3180 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT 3181 CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT]]:_, [[C]]:_(s64) 3182 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT 3183 CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[PTRTOINT]]:_, [[C]]:_ 3184 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[SHL]]:_ 3185 CHECK: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[OR]] 3186 3187 CHECK: [[PTRTOINT:%[0-9]+]]:_(s64) = G_PTRTOINT [[P0]] 3188 CHECK: [[PTRTOINT1:%[0-9]+]]:_(s32) = G_PTRTOINT [[P1]] 3189 CHECK: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[PTRTOINT1]] 3190 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT 3191 CHECK: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ZEXT]]:_, [[C]]:_(s64) 3192 CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT 3193 CHECK: [[AND:%[0-9]+]]:_(s64) = G_AND [[PTRTOINT]]:_, [[C]]:_ 3194 CHECK: [[OR:%[0-9]+]]:_(s64) = G_OR [[AND]]:_, [[SHL]]:_ 3195 CHECK: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[OR]] 3196 3197 CHECK: [[V2S32_E0:%[0-9]+]]:_(s32), [[V2S32_E1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[V2S32]] 3198 CHECK: [[BV:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[V2S32_E0]]:_(s32), [[S32]]:_(s32) 3199 )"; 3200 3201 // Check 3202 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3203 } 3204 3205 // Test lowering of G_FFLOOR 3206 TEST_F(AArch64GISelMITest, LowerFFloor) { 3207 setUp(); 3208 if (!TM) 3209 return; 3210 3211 // Declare your legalization info 3212 DefineLegalizerInfo(A, {}); 3213 // Build Instr 3214 auto Floor = B.buildFFloor(LLT::scalar(64), Copies[0], MachineInstr::MIFlag::FmNoInfs); 3215 AInfo Info(MF->getSubtarget()); 3216 DummyGISelObserver Observer; 3217 LegalizerHelper Helper(*MF, Info, Observer, B); 3218 // Perform Legalization 3219 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3220 Helper.lower(*Floor, 0, LLT())); 3221 3222 auto CheckStr = R"( 3223 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 3224 CHECK: [[TRUNC:%[0-9]+]]:_(s64) = ninf G_INTRINSIC_TRUNC [[COPY]] 3225 CHECK: [[ZERO:%[0-9]+]]:_(s64) = G_FCONSTANT double 0.000000e+00 3226 CHECK: [[CMP0:%[0-9]+]]:_(s1) = ninf G_FCMP floatpred(olt), [[COPY]]:_(s64), [[ZERO]]:_ 3227 CHECK: [[CMP1:%[0-9]+]]:_(s1) = ninf G_FCMP floatpred(one), [[COPY]]:_(s64), [[TRUNC]]:_ 3228 CHECK: [[AND:%[0-9]+]]:_(s1) = G_AND [[CMP0]]:_, [[CMP1]]:_ 3229 CHECK: [[ITOFP:%[0-9]+]]:_(s64) = G_SITOFP [[AND]] 3230 = ninf G_FADD [[TRUNC]]:_, [[ITOFP]]:_ 3231 )"; 3232 3233 // Check 3234 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3235 } 3236 3237 // Test lowering of G_BSWAP 3238 TEST_F(AArch64GISelMITest, LowerBSWAP) { 3239 setUp(); 3240 if (!TM) 3241 return; 3242 3243 DefineLegalizerInfo(A, {}); 3244 3245 // Make sure vector lowering doesn't assert. 3246 auto Cast = B.buildBitcast(LLT::fixed_vector(2, 32), Copies[0]); 3247 auto BSwap = B.buildBSwap(LLT::fixed_vector(2, 32), Cast); 3248 AInfo Info(MF->getSubtarget()); 3249 DummyGISelObserver Observer; 3250 LegalizerHelper Helper(*MF, Info, Observer, B); 3251 // Perform Legalization 3252 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3253 Helper.lower(*BSwap, 0, LLT())); 3254 3255 auto CheckStr = R"( 3256 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 3257 CHECK: [[VEC:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]] 3258 CHECK: [[K24:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 3259 CHECK: [[SPLAT24:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[K24]]:_(s32), [[K24]]:_(s32) 3260 CHECK: [[SHL0:%[0-9]+]]:_(<2 x s32>) = G_SHL [[VEC]]:_, [[SPLAT24]] 3261 CHECK: [[SHR0:%[0-9]+]]:_(<2 x s32>) = G_LSHR [[VEC]]:_, [[SPLAT24]] 3262 CHECK: [[OR0:%[0-9]+]]:_(<2 x s32>) = G_OR [[SHR0]]:_, [[SHL0]]:_ 3263 CHECK: [[KMASK:%[0-9]+]]:_(s32) = G_CONSTANT i32 65280 3264 CHECK: [[SPLATMASK:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[KMASK]]:_(s32), [[KMASK]]:_(s32) 3265 CHECK: [[K8:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 3266 CHECK: [[SPLAT8:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[K8]]:_(s32), [[K8]]:_(s32) 3267 CHECK: [[AND0:%[0-9]+]]:_(<2 x s32>) = G_AND [[VEC]]:_, [[SPLATMASK]]:_ 3268 CHECK: [[SHL1:%[0-9]+]]:_(<2 x s32>) = G_SHL [[AND0]]:_, [[SPLAT8]] 3269 CHECK: [[OR1:%[0-9]+]]:_(<2 x s32>) = G_OR [[OR0]]:_, [[SHL1]]:_ 3270 CHECK: [[SHR1:%[0-9]+]]:_(<2 x s32>) = G_LSHR [[VEC]]:_, [[SPLAT8]] 3271 CHECK: [[AND1:%[0-9]+]]:_(<2 x s32>) = G_AND [[SHR1]]:_, [[SPLATMASK]]:_ 3272 CHECK: [[BSWAP:%[0-9]+]]:_(<2 x s32>) = G_OR [[OR1]]:_, [[AND1]]:_ 3273 )"; 3274 3275 // Check 3276 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3277 } 3278 3279 // Test lowering of G_SDIVREM into G_SDIV and G_SREM 3280 TEST_F(AArch64GISelMITest, LowerSDIVREM) { 3281 setUp(); 3282 if (!TM) 3283 return; 3284 3285 // Declare your legalization info 3286 DefineLegalizerInfo( 3287 A, { getActionDefinitionsBuilder(G_SDIVREM).lowerFor({s64}); }); 3288 3289 LLT S64{LLT::scalar(64)}; 3290 3291 // Build Instr 3292 auto SDivrem = 3293 B.buildInstr(TargetOpcode::G_SDIVREM, {S64, S64}, {Copies[0], Copies[1]}); 3294 AInfo Info(MF->getSubtarget()); 3295 DummyGISelObserver Observer; 3296 LegalizerHelper Helper(*MF, Info, Observer, B); 3297 // Perform Legalization 3298 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3299 Helper.lower(*SDivrem, 0, S64)); 3300 3301 const auto *CheckStr = R"( 3302 CHECK: [[DIV:%[0-9]+]]:_(s64) = G_SDIV %0:_, %1:_ 3303 CHECK: [[REM:%[0-9]+]]:_(s64) = G_SREM %0:_, %1:_ 3304 )"; 3305 3306 // Check 3307 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3308 } 3309 3310 // Test lowering of G_UDIVREM into G_UDIV and G_UREM 3311 TEST_F(AArch64GISelMITest, LowerUDIVREM) { 3312 setUp(); 3313 if (!TM) 3314 return; 3315 3316 // Declare your legalization info 3317 DefineLegalizerInfo( 3318 A, { getActionDefinitionsBuilder(G_UDIVREM).lowerFor({s64}); }); 3319 3320 LLT S64{LLT::scalar(64)}; 3321 3322 // Build Instr 3323 auto UDivrem = 3324 B.buildInstr(TargetOpcode::G_UDIVREM, {S64, S64}, {Copies[0], Copies[1]}); 3325 AInfo Info(MF->getSubtarget()); 3326 DummyGISelObserver Observer; 3327 LegalizerHelper Helper(*MF, Info, Observer, B); 3328 // Perform Legalization 3329 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3330 Helper.lower(*UDivrem, 0, S64)); 3331 3332 const auto *CheckStr = R"( 3333 CHECK: [[DIV:%[0-9]+]]:_(s64) = G_UDIV %0:_, %1:_ 3334 CHECK: [[REM:%[0-9]+]]:_(s64) = G_UREM %0:_, %1:_ 3335 )"; 3336 3337 // Check 3338 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3339 } 3340 3341 // Test widening of G_UNMERGE_VALUES 3342 TEST_F(AArch64GISelMITest, WidenUnmerge) { 3343 setUp(); 3344 if (!TM) 3345 return; 3346 3347 DefineLegalizerInfo(A, {}); 3348 3349 // Check that widening G_UNMERGE_VALUES to a larger type than the source type 3350 // works as expected 3351 LLT P0{LLT::pointer(0, 64)}; 3352 LLT S32{LLT::scalar(32)}; 3353 LLT S96{LLT::scalar(96)}; 3354 3355 auto IntToPtr = B.buildIntToPtr(P0, Copies[0]); 3356 auto UnmergePtr = B.buildUnmerge(S32, IntToPtr); 3357 auto UnmergeScalar = B.buildUnmerge(S32, Copies[0]); 3358 3359 AInfo Info(MF->getSubtarget()); 3360 DummyGISelObserver Observer; 3361 LegalizerHelper Helper(*MF, Info, Observer, B); 3362 3363 // Perform Legalization 3364 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3365 Helper.widenScalar(*UnmergePtr, 0, S96)); 3366 3367 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3368 Helper.widenScalar(*UnmergeScalar, 0, S96)); 3369 3370 const auto *CheckStr = R"( 3371 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 3372 CHECK: [[PTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[COPY]] 3373 CHECK: [[INT:%[0-9]+]]:_(s64) = G_PTRTOINT [[PTR]] 3374 CHECK: [[ANYEXT:%[0-9]+]]:_(s96) = G_ANYEXT [[INT]] 3375 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[ANYEXT]] 3376 CHECK: [[C:%[0-9]+]]:_(s96) = G_CONSTANT i96 32 3377 CHECK: [[LSHR:%[0-9]+]]:_(s96) = G_LSHR [[ANYEXT]]:_, [[C]] 3378 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[LSHR]] 3379 CHECK: [[ANYEXT:%[0-9]+]]:_(s96) = G_ANYEXT [[COPY]] 3380 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[ANYEXT]] 3381 CHECK: [[C:%[0-9]+]]:_(s96) = G_CONSTANT i96 32 3382 CHECK: [[LSHR:%[0-9]+]]:_(s96) = G_LSHR [[ANYEXT]]:_, [[C]] 3383 CHECK: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[LSHR]] 3384 )"; 3385 3386 // Check 3387 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3388 } 3389 3390 TEST_F(AArch64GISelMITest, BitcastLoad) { 3391 setUp(); 3392 if (!TM) 3393 return; 3394 3395 LLT P0 = LLT::pointer(0, 64); 3396 LLT S32 = LLT::scalar(32); 3397 LLT V4S8 = LLT::fixed_vector(4, 8); 3398 auto Ptr = B.buildUndef(P0); 3399 3400 DefineLegalizerInfo(A, {}); 3401 3402 MachineMemOperand *MMO = B.getMF().getMachineMemOperand( 3403 MachinePointerInfo(), MachineMemOperand::MOLoad, 4, Align(4)); 3404 auto Load = B.buildLoad(V4S8, Ptr, *MMO); 3405 3406 AInfo Info(MF->getSubtarget()); 3407 DummyGISelObserver Observer; 3408 B.setInsertPt(*EntryMBB, Load->getIterator()); 3409 LegalizerHelper Helper(*MF, Info, Observer, B); 3410 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3411 Helper.bitcast(*Load, 0, S32)); 3412 3413 auto CheckStr = R"( 3414 CHECK: [[PTR:%[0-9]+]]:_(p0) = G_IMPLICIT_DEF 3415 CHECK: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD 3416 CHECK: [[CAST:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[LOAD]] 3417 3418 )"; 3419 3420 // Check 3421 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3422 } 3423 3424 TEST_F(AArch64GISelMITest, BitcastStore) { 3425 setUp(); 3426 if (!TM) 3427 return; 3428 3429 LLT P0 = LLT::pointer(0, 64); 3430 LLT S32 = LLT::scalar(32); 3431 LLT V4S8 = LLT::fixed_vector(4, 8); 3432 auto Ptr = B.buildUndef(P0); 3433 3434 DefineLegalizerInfo(A, {}); 3435 3436 MachineMemOperand *MMO = B.getMF().getMachineMemOperand( 3437 MachinePointerInfo(), MachineMemOperand::MOStore, 4, Align(4)); 3438 auto Val = B.buildUndef(V4S8); 3439 auto Store = B.buildStore(Val, Ptr, *MMO); 3440 3441 AInfo Info(MF->getSubtarget()); 3442 DummyGISelObserver Observer; 3443 LegalizerHelper Helper(*MF, Info, Observer, B); 3444 B.setInsertPt(*EntryMBB, Store->getIterator()); 3445 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3446 Helper.bitcast(*Store, 0, S32)); 3447 3448 auto CheckStr = R"( 3449 CHECK: [[VAL:%[0-9]+]]:_(<4 x s8>) = G_IMPLICIT_DEF 3450 CHECK: [[CAST:%[0-9]+]]:_(s32) = G_BITCAST [[VAL]] 3451 CHECK: G_STORE [[CAST]] 3452 )"; 3453 3454 // Check 3455 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3456 } 3457 3458 TEST_F(AArch64GISelMITest, BitcastSelect) { 3459 setUp(); 3460 if (!TM) 3461 return; 3462 3463 LLT S1 = LLT::scalar(1); 3464 LLT S32 = LLT::scalar(32); 3465 LLT V4S8 = LLT::fixed_vector(4, 8); 3466 3467 DefineLegalizerInfo(A, {}); 3468 3469 auto Cond = B.buildUndef(S1); 3470 auto Val0 = B.buildConstant(V4S8, 123); 3471 auto Val1 = B.buildConstant(V4S8, 99); 3472 3473 auto Select = B.buildSelect(V4S8, Cond, Val0, Val1); 3474 3475 AInfo Info(MF->getSubtarget()); 3476 DummyGISelObserver Observer; 3477 LegalizerHelper Helper(*MF, Info, Observer, B); 3478 B.setInsertPt(*EntryMBB, Select->getIterator()); 3479 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3480 Helper.bitcast(*Select, 0, S32)); 3481 3482 auto CheckStr = R"( 3483 CHECK: [[VAL0:%[0-9]+]]:_(<4 x s8>) = G_BUILD_VECTOR 3484 CHECK: [[VAL1:%[0-9]+]]:_(<4 x s8>) = G_BUILD_VECTOR 3485 CHECK: [[CAST0:%[0-9]+]]:_(s32) = G_BITCAST [[VAL0]] 3486 CHECK: [[CAST1:%[0-9]+]]:_(s32) = G_BITCAST [[VAL1]] 3487 CHECK: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT %{{[0-9]+}}:_(s1), [[CAST0]]:_, [[CAST1]]:_ 3488 CHECK: [[CAST2:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[SELECT]] 3489 )"; 3490 3491 // Check 3492 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3493 3494 // Doesn't make sense 3495 auto VCond = B.buildUndef(LLT::fixed_vector(4, 1)); 3496 auto VSelect = B.buildSelect(V4S8, VCond, Val0, Val1); 3497 3498 B.setInsertPt(*EntryMBB, VSelect->getIterator()); 3499 EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize, 3500 Helper.bitcast(*VSelect, 0, S32)); 3501 EXPECT_EQ(LegalizerHelper::LegalizeResult::UnableToLegalize, 3502 Helper.bitcast(*VSelect, 1, LLT::scalar(4))); 3503 } 3504 3505 TEST_F(AArch64GISelMITest, BitcastBitOps) { 3506 setUp(); 3507 if (!TM) 3508 return; 3509 3510 LLT S32 = LLT::scalar(32); 3511 LLT V4S8 = LLT::fixed_vector(4, 8); 3512 3513 DefineLegalizerInfo(A, {}); 3514 3515 auto Val0 = B.buildConstant(V4S8, 123); 3516 auto Val1 = B.buildConstant(V4S8, 99); 3517 auto And = B.buildAnd(V4S8, Val0, Val1); 3518 auto Or = B.buildOr(V4S8, Val0, Val1); 3519 auto Xor = B.buildXor(V4S8, Val0, Val1); 3520 3521 AInfo Info(MF->getSubtarget()); 3522 DummyGISelObserver Observer; 3523 LegalizerHelper Helper(*MF, Info, Observer, B); 3524 B.setInsertPt(*EntryMBB, And->getIterator()); 3525 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3526 Helper.bitcast(*And, 0, S32)); 3527 3528 B.setInsertPt(*EntryMBB, Or->getIterator()); 3529 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3530 Helper.bitcast(*Or, 0, S32)); 3531 3532 B.setInsertPt(*EntryMBB, Xor->getIterator()); 3533 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3534 Helper.bitcast(*Xor, 0, S32)); 3535 3536 auto CheckStr = R"( 3537 CHECK: [[VAL0:%[0-9]+]]:_(<4 x s8>) = G_BUILD_VECTOR 3538 CHECK: [[VAL1:%[0-9]+]]:_(<4 x s8>) = G_BUILD_VECTOR 3539 CHECK: [[CAST0:%[0-9]+]]:_(s32) = G_BITCAST [[VAL0]] 3540 CHECK: [[CAST1:%[0-9]+]]:_(s32) = G_BITCAST [[VAL1]] 3541 CHECK: [[AND:%[0-9]+]]:_(s32) = G_AND [[CAST0]]:_, [[CAST1]]:_ 3542 CHECK: [[CAST_AND:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[AND]] 3543 CHECK: [[CAST2:%[0-9]+]]:_(s32) = G_BITCAST [[VAL0]] 3544 CHECK: [[CAST3:%[0-9]+]]:_(s32) = G_BITCAST [[VAL1]] 3545 CHECK: [[OR:%[0-9]+]]:_(s32) = G_OR [[CAST2]]:_, [[CAST3]]:_ 3546 CHECK: [[CAST_OR:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[OR]] 3547 CHECK: [[CAST4:%[0-9]+]]:_(s32) = G_BITCAST [[VAL0]] 3548 CHECK: [[CAST5:%[0-9]+]]:_(s32) = G_BITCAST [[VAL1]] 3549 CHECK: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[CAST4]]:_, [[CAST5]]:_ 3550 CHECK: [[CAST_XOR:%[0-9]+]]:_(<4 x s8>) = G_BITCAST [[XOR]] 3551 )"; 3552 3553 // Check 3554 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3555 } 3556 3557 TEST_F(AArch64GISelMITest, CreateLibcall) { 3558 setUp(); 3559 if (!TM) 3560 return; 3561 3562 DefineLegalizerInfo(A, {}); 3563 3564 AInfo Info(MF->getSubtarget()); 3565 DummyGISelObserver Observer; 3566 3567 LLVMContext &Ctx = MF->getFunction().getContext(); 3568 auto *RetTy = Type::getVoidTy(Ctx); 3569 3570 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3571 createLibcall(B, "abort", {{}, RetTy, 0}, {}, CallingConv::C)); 3572 3573 auto CheckStr = R"( 3574 CHECK: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp 3575 CHECK: BL &abort 3576 CHECK: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp 3577 )"; 3578 3579 // Check 3580 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3581 } 3582 3583 // Test narrowing of G_IMPLICIT_DEF 3584 TEST_F(AArch64GISelMITest, NarrowImplicitDef) { 3585 setUp(); 3586 if (!TM) 3587 return; 3588 3589 DefineLegalizerInfo(A, {}); 3590 3591 // Make sure that G_IMPLICIT_DEF can be narrowed if the original size is not a 3592 // multiple of narrow size 3593 LLT S32{LLT::scalar(32)}; 3594 LLT S48{LLT::scalar(48)}; 3595 LLT S64{LLT::scalar(64)}; 3596 LLT V2S64{{LLT::fixed_vector(2, 64)}}; 3597 3598 auto Implicit1 = B.buildUndef(S64); 3599 auto Implicit2 = B.buildUndef(S64); 3600 auto Implicit3 = B.buildUndef(V2S64); 3601 auto Implicit4 = B.buildUndef(V2S64); 3602 3603 AInfo Info(MF->getSubtarget()); 3604 DummyGISelObserver Observer; 3605 LegalizerHelper Helper(*MF, Info, Observer, B); 3606 3607 // Perform Legalization 3608 3609 B.setInsertPt(*EntryMBB, Implicit1->getIterator()); 3610 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3611 Helper.narrowScalar(*Implicit1, 0, S48)); 3612 3613 B.setInsertPt(*EntryMBB, Implicit2->getIterator()); 3614 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3615 Helper.narrowScalar(*Implicit2, 0, S32)); 3616 3617 B.setInsertPt(*EntryMBB, Implicit3->getIterator()); 3618 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3619 Helper.narrowScalar(*Implicit3, 0, S48)); 3620 3621 B.setInsertPt(*EntryMBB, Implicit4->getIterator()); 3622 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3623 Helper.narrowScalar(*Implicit4, 0, S32)); 3624 3625 const auto *CheckStr = R"( 3626 CHECK: [[DEF:%[0-9]+]]:_(s48) = G_IMPLICIT_DEF 3627 CHECK: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[DEF]] 3628 3629 CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF 3630 CHECK: [[DEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF 3631 CHECK: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[DEF]]:_(s32), [[DEF1]] 3632 3633 CHECK: [[DEF:%[0-9]+]]:_(<2 x s48>) = G_IMPLICIT_DEF 3634 CHECK: [[ANYEXT:%[0-9]+]]:_(<2 x s64>) = G_ANYEXT [[DEF]] 3635 3636 CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF 3637 CHECK: [[DEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF 3638 CHECK: [[DEF2:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF 3639 CHECK: [[DEF3:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF 3640 CHECK: [[BV:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[DEF]]:_(s32), [[DEF1]]:_(s32), [[DEF2]]:_(s32), [[DEF3]]:_(s32) 3641 )"; 3642 3643 // Check 3644 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3645 } 3646 3647 // Test widening of G_FREEZE 3648 TEST_F(AArch64GISelMITest, WidenFreeze) { 3649 setUp(); 3650 if (!TM) 3651 return; 3652 3653 DefineLegalizerInfo(A, {}); 3654 3655 // Make sure that G_FREEZE is widened with anyext 3656 LLT S64{LLT::scalar(64)}; 3657 LLT S128{LLT::scalar(128)}; 3658 LLT V2S32{LLT::fixed_vector(2, 32)}; 3659 LLT V2S64{LLT::fixed_vector(2, 64)}; 3660 3661 auto Vector = B.buildBitcast(V2S32, Copies[0]); 3662 3663 auto FreezeScalar = B.buildInstr(TargetOpcode::G_FREEZE, {S64}, {Copies[0]}); 3664 auto FreezeVector = B.buildInstr(TargetOpcode::G_FREEZE, {V2S32}, {Vector}); 3665 3666 AInfo Info(MF->getSubtarget()); 3667 DummyGISelObserver Observer; 3668 LegalizerHelper Helper(*MF, Info, Observer, B); 3669 3670 // Perform Legalization 3671 3672 B.setInsertPt(*EntryMBB, FreezeScalar->getIterator()); 3673 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3674 Helper.widenScalar(*FreezeScalar, 0, S128)); 3675 3676 B.setInsertPt(*EntryMBB, FreezeVector->getIterator()); 3677 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3678 Helper.widenScalar(*FreezeVector, 0, V2S64)); 3679 3680 const auto *CheckStr = R"( 3681 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 3682 CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]] 3683 3684 CHECK: [[ANYEXT:%[0-9]+]]:_(s128) = G_ANYEXT [[COPY]] 3685 CHECK: [[FREEZE:%[0-9]+]]:_(s128) = G_FREEZE [[ANYEXT]] 3686 CHECK: [[TRUNC:%[0-9]+]]:_(s64) = G_TRUNC [[FREEZE]] 3687 3688 CHECK: [[ANYEXT1:%[0-9]+]]:_(<2 x s64>) = G_ANYEXT [[BITCAST]] 3689 CHECK: [[FREEZE1:%[0-9]+]]:_(<2 x s64>) = G_FREEZE [[ANYEXT1]] 3690 CHECK: [[TRUNC1:%[0-9]+]]:_(<2 x s32>) = G_TRUNC [[FREEZE1]] 3691 )"; 3692 3693 // Check 3694 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3695 } 3696 3697 // Test narrowing of G_FREEZE 3698 TEST_F(AArch64GISelMITest, NarrowFreeze) { 3699 setUp(); 3700 if (!TM) 3701 return; 3702 3703 DefineLegalizerInfo(A, {}); 3704 3705 // Make sure that G_FREEZE is narrowed using unmerge/extract 3706 LLT S32{LLT::scalar(32)}; 3707 LLT S33{LLT::scalar(33)}; 3708 LLT S48{LLT::scalar(48)}; 3709 LLT S64{LLT::scalar(64)}; 3710 LLT V2S16{LLT::fixed_vector(2, 16)}; 3711 LLT V3S16{LLT::fixed_vector(3, 16)}; 3712 LLT V4S16{LLT::fixed_vector(4, 16)}; 3713 3714 auto Trunc = B.buildTrunc(S33, {Copies[0]}); 3715 auto Trunc1 = B.buildTrunc(S48, {Copies[0]}); 3716 auto Vector = B.buildBitcast(V3S16, Trunc1); 3717 3718 auto FreezeScalar = B.buildInstr(TargetOpcode::G_FREEZE, {S64}, {Copies[0]}); 3719 auto FreezeOdd = B.buildInstr(TargetOpcode::G_FREEZE, {S33}, {Trunc}); 3720 auto FreezeVector = B.buildInstr(TargetOpcode::G_FREEZE, {V3S16}, {Vector}); 3721 auto FreezeVector1 = B.buildInstr(TargetOpcode::G_FREEZE, {V3S16}, {Vector}); 3722 3723 AInfo Info(MF->getSubtarget()); 3724 DummyGISelObserver Observer; 3725 LegalizerHelper Helper(*MF, Info, Observer, B); 3726 3727 // Perform Legalization 3728 3729 B.setInsertPt(*EntryMBB, FreezeScalar->getIterator()); 3730 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3731 Helper.narrowScalar(*FreezeScalar, 0, S32)); 3732 3733 // This should be followed by narrowScalar to S32. 3734 B.setInsertPt(*EntryMBB, FreezeOdd->getIterator()); 3735 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3736 Helper.widenScalar(*FreezeOdd, 0, S64)); 3737 3738 B.setInsertPt(*EntryMBB, FreezeVector->getIterator()); 3739 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3740 Helper.fewerElementsVector(*FreezeVector, 0, V2S16)); 3741 3742 // This should be followed by fewerElements to V2S16. 3743 B.setInsertPt(*EntryMBB, FreezeVector1->getIterator()); 3744 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3745 Helper.moreElementsVector(*FreezeVector1, 0, V4S16)); 3746 3747 const auto *CheckStr = R"( 3748 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 3749 CHECK: [[TRUNC:%[0-9]+]]:_(s33) = G_TRUNC [[COPY]] 3750 CHECK: [[TRUNC1:%[0-9]+]]:_(s48) = G_TRUNC [[COPY]] 3751 CHECK: [[BITCAST:%[0-9]+]]:_(<3 x s16>) = G_BITCAST [[TRUNC1]] 3752 3753 CHECK: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]] 3754 CHECK: [[FREEZE:%[0-9]+]]:_(s32) = G_FREEZE [[UV]] 3755 CHECK: [[FREEZE1:%[0-9]+]]:_(s32) = G_FREEZE [[UV1]] 3756 CHECK: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[FREEZE]]:_(s32), [[FREEZE1]] 3757 3758 CHECK: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[TRUNC]] 3759 CHECK: [[FREEZE2:%[0-9]+]]:_(s64) = G_FREEZE [[ANYEXT]] 3760 CHECK: [[TRUNC1:%[0-9]+]]:_(s33) = G_TRUNC [[FREEZE2]] 3761 3762 CHECK: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[BITCAST]] 3763 CHECK: [[BV:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[UV2]]:_(s16), [[UV3]]:_(s16) 3764 CHECK: [[FREEZE3:%[0-9]+]]:_(<2 x s16>) = G_FREEZE [[BV]] 3765 CHECK: [[FREEZE4:%[0-9]+]]:_(s16) = G_FREEZE [[UV4]] 3766 CHECK: [[FREEZE3_E0:%[0-9]+]]:_(s16), [[FREEZE3_E1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[FREEZE3]] 3767 CHECK: [[BV1:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[FREEZE3_E0]]:_(s16), [[FREEZE3_E1]]:_(s16), [[FREEZE4]]:_(s16) 3768 3769 CHECK: [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[BITCAST]] 3770 CHECK: [[IMP_DEF:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF 3771 CHECK: [[BV1:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[UV5]]:_(s16), [[UV6]]:_(s16), [[UV7]]:_(s16), [[IMP_DEF]]:_(s16) 3772 CHECK: [[FREEZE5:%[0-9]+]]:_(<4 x s16>) = G_FREEZE [[BV1]] 3773 CHECK: [[FREEZE5_E0:%[0-9]+]]:_(s16), [[FREEZE5_E1:%[0-9]+]]:_(s16), [[FREEZE5_E2:%[0-9]+]]:_(s16), [[FREEZE5_E3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[FREEZE5]] 3774 CHECK: [[BV2:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[FREEZE5_E0]]:_(s16), [[FREEZE5_E1]]:_(s16), [[FREEZE5_E2]]:_(s16) 3775 )"; 3776 3777 // Check 3778 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3779 } 3780 3781 // Test fewer elements of G_FREEZE 3782 TEST_F(AArch64GISelMITest, FewerElementsFreeze) { 3783 setUp(); 3784 if (!TM) 3785 return; 3786 3787 DefineLegalizerInfo(A, {}); 3788 3789 LLT S32{LLT::scalar(32)}; 3790 LLT V2S16{LLT::fixed_vector(2, 16)}; 3791 LLT V2S32{LLT::fixed_vector(2, 32)}; 3792 LLT V4S16{LLT::fixed_vector(4, 16)}; 3793 3794 auto Vector1 = B.buildBitcast(V2S32, Copies[0]); 3795 auto Vector2 = B.buildBitcast(V4S16, Copies[0]); 3796 3797 auto FreezeVector1 = B.buildInstr(TargetOpcode::G_FREEZE, {V2S32}, {Vector1}); 3798 auto FreezeVector2 = B.buildInstr(TargetOpcode::G_FREEZE, {V4S16}, {Vector2}); 3799 3800 AInfo Info(MF->getSubtarget()); 3801 DummyGISelObserver Observer; 3802 LegalizerHelper Helper(*MF, Info, Observer, B); 3803 3804 // Perform Legalization 3805 3806 B.setInsertPt(*EntryMBB, FreezeVector1->getIterator()); 3807 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3808 Helper.fewerElementsVector(*FreezeVector1, 0, S32)); 3809 3810 B.setInsertPt(*EntryMBB, FreezeVector2->getIterator()); 3811 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3812 Helper.fewerElementsVector(*FreezeVector2, 0, V2S16)); 3813 3814 const auto *CheckStr = R"( 3815 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 3816 CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]] 3817 CHECK: [[BITCAST1:%[0-9]+]]:_(<4 x s16>) = G_BITCAST [[COPY]] 3818 3819 CHECK: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[BITCAST]] 3820 CHECK: [[FREEZE:%[0-9]+]]:_(s32) = G_FREEZE [[UV]] 3821 CHECK: [[FREEZE1:%[0-9]+]]:_(s32) = G_FREEZE [[UV1]] 3822 CHECK: [[MV:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[FREEZE]]:_(s32), [[FREEZE1]] 3823 3824 CHECK: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[BITCAST1]] 3825 CHECK: [[FREEZE2:%[0-9]+]]:_(<2 x s16>) = G_FREEZE [[UV]] 3826 CHECK: [[FREEZE3:%[0-9]+]]:_(<2 x s16>) = G_FREEZE [[UV1]] 3827 CHECK: [[MV:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[FREEZE2]]:_(<2 x s16>), [[FREEZE3]] 3828 )"; 3829 3830 // Check 3831 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3832 } 3833 3834 // Test more elements of G_FREEZE 3835 TEST_F(AArch64GISelMITest, MoreElementsFreeze) { 3836 setUp(); 3837 if (!TM) 3838 return; 3839 3840 DefineLegalizerInfo(A, {}); 3841 3842 LLT V2S32{LLT::fixed_vector(2, 32)}; 3843 LLT V4S32{LLT::fixed_vector(4, 32)}; 3844 3845 auto Vector1 = B.buildBitcast(V2S32, Copies[0]); 3846 auto FreezeVector1 = B.buildInstr(TargetOpcode::G_FREEZE, {V2S32}, {Vector1}); 3847 3848 AInfo Info(MF->getSubtarget()); 3849 DummyGISelObserver Observer; 3850 LegalizerHelper Helper(*MF, Info, Observer, B); 3851 3852 // Perform Legalization 3853 B.setInsertPt(*EntryMBB, FreezeVector1->getIterator()); 3854 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3855 Helper.moreElementsVector(*FreezeVector1, 0, V4S32)); 3856 3857 const auto *CheckStr = R"( 3858 CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY 3859 CHECK: [[BITCAST:%[0-9]+]]:_(<2 x s32>) = G_BITCAST [[COPY]] 3860 CHECK: [[BITCAST_E0:%[0-9]+]]:_(s32), [[BITCAST_E1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[BITCAST]]:_(<2 x s32>) 3861 CHECK: [[IMP_DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF 3862 CHECK: [[BITCAST_LARGE:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[BITCAST_E0]]:_(s32), [[BITCAST_E1]]:_(s32), [[IMP_DEF]]:_(s32), [[IMP_DEF]]:_(s32) 3863 CHECK: [[FREEZE:%[0-9]+]]:_(<4 x s32>) = G_FREEZE [[BITCAST_LARGE]] 3864 CHECK: [[FREEZE_E0:%[0-9]+]]:_(s32), [[FREEZE_E1:%[0-9]+]]:_(s32), [[FREEZE_E2:%[0-9]+]]:_(s32), [[FREEZE_E3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[FREEZE]]:_(<4 x s32>) 3865 CHECK: (<2 x s32>) = G_BUILD_VECTOR [[FREEZE_E0]]:_(s32), [[FREEZE_E1]]:_(s32) 3866 )"; 3867 3868 // Check 3869 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3870 } 3871 3872 // Test fewer elements of G_INSERT_VECTOR_ELEMENT 3873 TEST_F(AArch64GISelMITest, FewerElementsInsertVectorElt) { 3874 setUp(); 3875 if (!TM) 3876 return; 3877 3878 DefineLegalizerInfo(A, {}); 3879 3880 LLT P0{LLT::pointer(0, 64)}; 3881 LLT S64{LLT::scalar(64)}; 3882 LLT S16{LLT::scalar(16)}; 3883 LLT V2S16{LLT::fixed_vector(2, 16)}; 3884 LLT V3S16{LLT::fixed_vector(3, 16)}; 3885 LLT V8S16{LLT::fixed_vector(8, 16)}; 3886 3887 auto Ptr0 = B.buildIntToPtr(P0, Copies[0]); 3888 auto VectorV8 = B.buildLoad(V8S16, Ptr0, MachinePointerInfo(), Align(8)); 3889 auto Value = B.buildTrunc(S16, Copies[1]); 3890 3891 auto Seven = B.buildConstant(S64, 7); 3892 auto InsertV8Constant7_0 = 3893 B.buildInsertVectorElement(V8S16, VectorV8, Value, Seven); 3894 auto InsertV8Constant7_1 = 3895 B.buildInsertVectorElement(V8S16, VectorV8, Value, Seven); 3896 3897 B.buildStore(InsertV8Constant7_0, Ptr0, MachinePointerInfo(), Align(8), 3898 MachineMemOperand::MOVolatile); 3899 B.buildStore(InsertV8Constant7_1, Ptr0, MachinePointerInfo(), Align(8), 3900 MachineMemOperand::MOVolatile); 3901 3902 AInfo Info(MF->getSubtarget()); 3903 DummyGISelObserver Observer; 3904 LegalizerHelper Helper(*MF, Info, Observer, B); 3905 3906 // Perform Legalization 3907 B.setInsertPt(*EntryMBB, InsertV8Constant7_0->getIterator()); 3908 3909 // This should index the high element of the 4th piece of an unmerge. 3910 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3911 Helper.fewerElementsVector(*InsertV8Constant7_0, 0, V2S16)); 3912 3913 // This case requires extracting an intermediate vector type into the target 3914 // v4s16. 3915 B.setInsertPt(*EntryMBB, InsertV8Constant7_1->getIterator()); 3916 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3917 Helper.fewerElementsVector(*InsertV8Constant7_1, 0, V3S16)); 3918 3919 const auto *CheckStr = R"( 3920 CHECK: [[COPY0:%[0-9]+]]:_(s64) = COPY 3921 CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY 3922 CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY 3923 CHECK: [[PTR0:%[0-9]+]]:_(p0) = G_INTTOPTR [[COPY0]] 3924 CHECK: [[VEC8:%[0-9]+]]:_(<8 x s16>) = G_LOAD [[PTR0]]:_(p0) :: (load (<8 x s16>), align 8) 3925 CHECK: [[INSERT_VAL:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]] 3926 3927 3928 CHECK: [[UNMERGE0:%[0-9]+]]:_(<2 x s16>), [[UNMERGE1:%[0-9]+]]:_(<2 x s16>), [[UNMERGE2:%[0-9]+]]:_(<2 x s16>), [[UNMERGE3:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[VEC8]] 3929 CHECK: [[ONE:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 3930 CHECK: [[SUB_INSERT_7:%[0-9]+]]:_(<2 x s16>) = G_INSERT_VECTOR_ELT [[UNMERGE3]]:_, [[INSERT_VAL]]:_(s16), [[ONE]] 3931 CHECK: [[INSERT_V8_7_0:%[0-9]+]]:_(<8 x s16>) = G_CONCAT_VECTORS [[UNMERGE0]]:_(<2 x s16>), [[UNMERGE1]]:_(<2 x s16>), [[UNMERGE2]]:_(<2 x s16>), [[SUB_INSERT_7]]:_(<2 x s16>) 3932 3933 3934 CHECK: [[UNMERGE1_0:%[0-9]+]]:_(s16), [[UNMERGE1_1:%[0-9]+]]:_(s16), [[UNMERGE1_2:%[0-9]+]]:_(s16), [[UNMERGE1_3:%[0-9]+]]:_(s16), [[UNMERGE1_4:%[0-9]+]]:_(s16), [[UNMERGE1_5:%[0-9]+]]:_(s16), [[UNMERGE1_6:%[0-9]+]]:_(s16), [[UNMERGE1_7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[VEC8]]:_(<8 x s16>) 3935 CHECK: [[IMPDEF_S16:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF 3936 CHECK: [[BUILD0:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[UNMERGE1_0]]:_(s16), [[UNMERGE1_1]]:_(s16), [[UNMERGE1_2]]:_(s16) 3937 CHECK: [[BUILD1:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[UNMERGE1_3]]:_(s16), [[UNMERGE1_4]]:_(s16), [[UNMERGE1_5]]:_(s16) 3938 CHECK: [[BUILD2:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[UNMERGE1_6]]:_(s16), [[UNMERGE1_7]]:_(s16), [[IMPDEF_S16]]:_(s16) 3939 CHECK: [[IMPDEF_V3S16:%[0-9]+]]:_(<3 x s16>) = G_IMPLICIT_DEF 3940 CHECK: [[ONE_1:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 3941 CHECK: [[SUB_INSERT_7_V3S16:%[0-9]+]]:_(<3 x s16>) = G_INSERT_VECTOR_ELT [[BUILD2]]:_, [[INSERT_VAL]]:_(s16), [[ONE_1]] 3942 3943 CHECK: [[WIDE_CONCAT_DEAD:%[0-9]+]]:_(<24 x s16>) = G_CONCAT_VECTORS [[BUILD0]]:_(<3 x s16>), [[BUILD1]]:_(<3 x s16>), [[SUB_INSERT_7_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>) 3944 CHECK: [[WIDE_CONCAT:%[0-9]+]]:_(<24 x s16>) = G_CONCAT_VECTORS [[BUILD0]]:_(<3 x s16>), [[BUILD1]]:_(<3 x s16>), [[SUB_INSERT_7_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>), [[IMPDEF_V3S16]]:_(<3 x s16>) 3945 CHECK: [[INSERT_V8_7_1:%[0-9]+]]:_(<8 x s16>), %{{[0-9]+}}:_(<8 x s16>), %{{[0-9]+}}:_(<8 x s16>) = G_UNMERGE_VALUES [[WIDE_CONCAT]]:_(<24 x s16>) 3946 3947 3948 CHECK: G_STORE [[INSERT_V8_7_0]] 3949 CHECK: G_STORE [[INSERT_V8_7_1]] 3950 )"; 3951 3952 // Check 3953 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3954 } 3955 3956 // Test widen scalar of G_UNMERGE_VALUES 3957 TEST_F(AArch64GISelMITest, widenScalarUnmerge) { 3958 setUp(); 3959 if (!TM) 3960 return; 3961 3962 DefineLegalizerInfo(A, {}); 3963 3964 LLT S96{LLT::scalar(96)}; 3965 LLT S64{LLT::scalar(64)}; 3966 LLT S48{LLT::scalar(48)}; 3967 3968 auto Src = B.buildAnyExt(S96, Copies[0]); 3969 auto Unmerge = B.buildUnmerge(S48, Src); 3970 3971 AInfo Info(MF->getSubtarget()); 3972 DummyGISelObserver Observer; 3973 LegalizerHelper Helper(*MF, Info, Observer, B); 3974 3975 // Perform Legalization 3976 B.setInsertPt(*EntryMBB, Unmerge->getIterator()); 3977 3978 // This should create unmerges to a GCD type (S16), then remerge to S48 3979 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 3980 Helper.widenScalar(*Unmerge, 0, S64)); 3981 3982 const auto *CheckStr = R"( 3983 CHECK: [[COPY0:%[0-9]+]]:_(s64) = COPY 3984 CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY 3985 CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY 3986 CHECK: [[ANYEXT:%[0-9]+]]:_(s96) = G_ANYEXT [[COPY0]] 3987 CHECK: [[ANYEXT1:%[0-9]+]]:_(s192) = G_ANYEXT [[ANYEXT]] 3988 CHECK: [[UNMERGE:%[0-9]+]]:_(s64), [[UNMERGE1:%[0-9]+]]:_(s64), [[UNMERGE2:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[ANYEXT1]] 3989 CHECK: [[UNMERGE3:%[0-9]+]]:_(s16), [[UNMERGE4:%[0-9]+]]:_(s16), [[UNMERGE5:%[0-9]+]]:_(s16), [[UNMERGE6:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UNMERGE]] 3990 CHECK: [[UNMERGE7:%[0-9]+]]:_(s16), [[UNMERGE8:%[0-9]+]]:_(s16), [[UNMERGE9:%[0-9]+]]:_(s16), [[UNMERGE10:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UNMERGE1]] 3991 CHECK: [[UNMERGE11:%[0-9]+]]:_(s16), [[UNMERGE12:%[0-9]+]]:_(s16), [[UNMERGE13:%[0-9]+]]:_(s16), [[UNMERGE14:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UNMERGE2]] 3992 CHECK: [[MERGE:%[0-9]+]]:_(s48) = G_MERGE_VALUES [[UNMERGE3]]:_(s16), [[UNMERGE4]]:_(s16), [[UNMERGE5]]:_(s16) 3993 CHECK: [[MERGE1:%[0-9]+]]:_(s48) = G_MERGE_VALUES [[UNMERGE6]]:_(s16), [[UNMERGE7]]:_(s16), [[UNMERGE8]]:_(s16) 3994 )"; 3995 3996 // Check 3997 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 3998 } 3999 4000 // Test moreElements of G_SHUFFLE_VECTOR. 4001 TEST_F(AArch64GISelMITest, moreElementsShuffle) { 4002 setUp(); 4003 if (!TM) 4004 return; 4005 4006 DefineLegalizerInfo(A, {}); 4007 4008 LLT S64{LLT::scalar(64)}; 4009 LLT V6S64 = LLT::fixed_vector(6, S64); 4010 4011 auto V1 = B.buildBuildVector(V6S64, {Copies[0], Copies[1], Copies[0], 4012 Copies[1], Copies[0], Copies[1]}); 4013 auto V2 = B.buildBuildVector(V6S64, {Copies[0], Copies[1], Copies[0], 4014 Copies[1], Copies[0], Copies[1]}); 4015 auto Shuffle = B.buildShuffleVector(V6S64, V1, V2, {3, 4, 7, 0, 1, 11}); 4016 4017 AInfo Info(MF->getSubtarget()); 4018 DummyGISelObserver Observer; 4019 LegalizerHelper Helper(*MF, Info, Observer, B); 4020 4021 // Perform Legalization 4022 B.setInsertPt(*EntryMBB, Shuffle->getIterator()); 4023 4024 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 4025 Helper.moreElementsVector(*Shuffle, 0, LLT::fixed_vector(8, S64))); 4026 4027 const auto *CheckStr = R"( 4028 CHECK: [[COPY0:%[0-9]+]]:_(s64) = COPY 4029 CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY 4030 CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY 4031 CHECK: [[BV1:%[0-9]+]]:_(<6 x s64>) = G_BUILD_VECTOR 4032 CHECK: [[BV2:%[0-9]+]]:_(<6 x s64>) = G_BUILD_VECTOR 4033 4034 CHECK: [[BV1_E0:%[0-9]+]]:_(s64), [[BV1_E1:%[0-9]+]]:_(s64), [[BV1_E2:%[0-9]+]]:_(s64), [[BV1_E3:%[0-9]+]]:_(s64), [[BV1_E4:%[0-9]+]]:_(s64), [[BV1_E5:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[BV1]]:_(<6 x s64>) 4035 CHECK: [[IMP_DEF0:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF 4036 CHECK: [[BV1_LARGE:%[0-9]+]]:_(<8 x s64>) = G_BUILD_VECTOR [[BV1_E0]]:_(s64), [[BV1_E1]]:_(s64), [[BV1_E2]]:_(s64), [[BV1_E3]]:_(s64), [[BV1_E4]]:_(s64), [[BV1_E5]]:_(s64), [[IMP_DEF0]]:_(s64), [[IMP_DEF0]]:_(s64) 4037 4038 CHECK: [[BV2_E0:%[0-9]+]]:_(s64), [[BV2_E1:%[0-9]+]]:_(s64), [[BV2_E2:%[0-9]+]]:_(s64), [[BV2_E3:%[0-9]+]]:_(s64), [[BV2_E4:%[0-9]+]]:_(s64), [[BV2_E5:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[BV2]]:_(<6 x s64>) 4039 CHECK: [[IMP_DEF1:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF 4040 CHECK: [[BV2_LARGE:%[0-9]+]]:_(<8 x s64>) = G_BUILD_VECTOR [[BV2_E0]]:_(s64), [[BV2_E1]]:_(s64), [[BV2_E2]]:_(s64), [[BV2_E3]]:_(s64), [[BV2_E4]]:_(s64), [[BV2_E5]]:_(s64), [[IMP_DEF1]]:_(s64), [[IMP_DEF1]]:_(s64) 4041 4042 CHECK: [[SHUF:%[0-9]+]]:_(<8 x s64>) = G_SHUFFLE_VECTOR [[BV1_LARGE]]:_(<8 x s64>), [[BV2_LARGE]]:_, shufflemask(3, 4, 9, 0, 1, 13, undef, undef) 4043 4044 CHECK: [[SHUF_E0:%[0-9]+]]:_(s64), [[SHUF_E1:%[0-9]+]]:_(s64), [[SHUF_E2:%[0-9]+]]:_(s64), [[SHUF_E3:%[0-9]+]]:_(s64), [[SHUF_E4:%[0-9]+]]:_(s64), [[SHUF_E5:%[0-9]+]]:_(s64), [[SHUF_E6:%[0-9]+]]:_(s64), [[SHUF_E7:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[SHUF]]:_(<8 x s64>) 4045 CHECK: (<6 x s64>) = G_BUILD_VECTOR [[SHUF_E0]]:_(s64), [[SHUF_E1]]:_(s64), [[SHUF_E2]]:_(s64), [[SHUF_E3]]:_(s64), [[SHUF_E4]]:_(s64), [[SHUF_E5]]:_(s64) 4046 )"; 4047 4048 // Check 4049 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 4050 } 4051 4052 // Test narror scalar of G_SHL with constant shift amount 4053 TEST_F(AArch64GISelMITest, narrowScalarShiftByConstant) { 4054 setUp(); 4055 if (!TM) 4056 return; 4057 4058 DefineLegalizerInfo(A, {}); 4059 4060 LLT S64{LLT::scalar(64)}; 4061 LLT S32{LLT::scalar(32)}; 4062 4063 auto Constant = B.buildConstant(S64, 33); 4064 auto Trunc = B.buildTrunc(S32, Constant); 4065 auto Shift = B.buildShl(S64, Copies[0], Trunc); 4066 4067 AInfo Info(MF->getSubtarget()); 4068 DummyGISelObserver Observer; 4069 LegalizerHelper Helper(*MF, Info, Observer, B); 4070 4071 // Perform Legalization 4072 B.setInsertPt(*EntryMBB, Shift->getIterator()); 4073 4074 // This should detect the G_CONSTANT feeding the G_SHL through a G_TRUNC 4075 EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized, 4076 Helper.narrowScalarShift(*Shift, 0, S32)); 4077 4078 const auto *CheckStr = R"( 4079 CHECK: [[COPY0:%[0-9]+]]:_(s64) = COPY 4080 CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY 4081 CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY 4082 CHECK: [[THIRTY3:%[0-9]+]]:_(s64) = G_CONSTANT i64 33 4083 CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC %4:_(s64) 4084 CHECK: [[UNMERGE:%[0-9]+]]:_(s32), [[UNMERGE2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY0]] 4085 CHECK: [[ZERO:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 4086 CHECK: [[ONE:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 4087 CHECK: [[SHIFT:%[0-9]+]]:_(s32) = G_SHL [[UNMERGE]]:_, [[ONE]]:_(s32) 4088 CHECK: [[MERGE:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[ZERO]]:_(s32), [[SHIFT]]:_(s32) 4089 )"; 4090 4091 // Check 4092 EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; 4093 } 4094 4095 } // namespace 4096