llvm.org GIT mirror llvm / ce31d93
[AArch64] Spot SBFX-compatbile code expressed with sign_extend_inreg. We were assuming all SBFX-like operations would have the shl/asr form, but often when the field being extracted is an i8 or i16, we end up with a SIGN_EXTEND_INREG acting on a shift instead. This is a port of r213754 from ARM to AArch64. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271677 91177308-0d34-0410-b5e6-96231b3b80d8 Chad Rosier 4 years ago
2 changed file(s) with 125 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
15011501 MSB = MSB > 31 ? 31 : MSB;
15021502
15031503 Opc = VT == MVT::i32 ? AArch64::UBFMWri : AArch64::UBFMXri;
1504 return true;
1505 }
1506
1507 static bool isBitfieldExtractOpFromSExtInReg(SDNode *N, unsigned &Opc,
1508 SDValue &Opd0, unsigned &Immr,
1509 unsigned &Imms) {
1510 assert(N->getOpcode() == ISD::SIGN_EXTEND_INREG);
1511
1512 EVT VT = N->getValueType(0);
1513 unsigned BitWidth = VT.getSizeInBits();
1514 assert((VT == MVT::i32 || VT == MVT::i64) &&
1515 "Type checking must have been done before calling this function");
1516
1517 SDValue Op = N->getOperand(0);
1518 if (Op->getOpcode() == ISD::TRUNCATE) {
1519 Op = Op->getOperand(0);
1520 VT = Op->getValueType(0);
1521 BitWidth = VT.getSizeInBits();
1522 }
1523
1524 uint64_t ShiftImm;
1525 if (!isOpcWithIntImmediate(Op.getNode(), ISD::SRL, ShiftImm) &&
1526 !isOpcWithIntImmediate(Op.getNode(), ISD::SRA, ShiftImm))
1527 return false;
1528
1529 unsigned Width = cast(N->getOperand(1))->getVT().getSizeInBits();
1530 if (ShiftImm + Width > BitWidth)
1531 return false;
1532
1533 Opc = (VT == MVT::i32) ? AArch64::SBFMWri : AArch64::SBFMXri;
1534 Opd0 = Op.getOperand(0);
1535 Immr = ShiftImm;
1536 Imms = ShiftImm + Width - 1;
15041537 return true;
15051538 }
15061539
16341667 case ISD::SRL:
16351668 case ISD::SRA:
16361669 return isBitfieldExtractOpFromShr(N, Opc, Opd0, Immr, Imms, BiggerPattern);
1670
1671 case ISD::SIGN_EXTEND_INREG:
1672 return isBitfieldExtractOpFromSExtInReg(N, Opc, Opd0, Immr, Imms);
16371673 }
16381674
16391675 unsigned NOpc = N->getMachineOpcode();
25442580 case ISD::SRL:
25452581 case ISD::AND:
25462582 case ISD::SRA:
2583 case ISD::SIGN_EXTEND_INREG:
25472584 if (tryBitfieldExtractOp(Node))
25482585 return;
25492586 if (tryBitfieldInsertInZeroOp(Node))
462462 %2 = or i64 %1, 157601565442048 ; 0x00008f5679530000
463463 ret i64 %2
464464 }
465
466 ; CHECK-LABEL: @test9
467 ; CHECK: sbfx w0, w0, #23, #8
468 define signext i8 @test9(i32 %a) {
469 %tmp = ashr i32 %a, 23
470 %res = trunc i32 %tmp to i8
471 ret i8 %res
472 }
473
474 ; CHECK-LABEL: @test10
475 ; CHECK: sbfx w0, w0, #23, #8
476 define signext i8 @test10(i32 %a) {
477 %tmp = lshr i32 %a, 23
478 %res = trunc i32 %tmp to i8
479 ret i8 %res
480 }
481
482 ; CHECK-LABEL: @test11
483 ; CHECK: sbfx w0, w0, #15, #16
484 define signext i16 @test11(i32 %a) {
485 %tmp = lshr i32 %a, 15
486 %res = trunc i32 %tmp to i16
487 ret i16 %res
488 }
489
490 ; CHECK-LABEL: @test12
491 ; CHECK: sbfx w0, w0, #16, #8
492 define signext i8 @test12(i64 %a) {
493 %tmp = lshr i64 %a, 16
494 %res = trunc i64 %tmp to i8
495 ret i8 %res
496 }
497
498 ; CHECK-LABEL: @test13
499 ; CHECK: sbfx x0, x0, #30, #8
500 define signext i8 @test13(i64 %a) {
501 %tmp = lshr i64 %a, 30
502 %res = trunc i64 %tmp to i8
503 ret i8 %res
504 }
505
506 ; CHECK-LABEL: @test14
507 ; CHECK: sbfx x0, x0, #23, #16
508 define signext i16 @test14(i64 %a) {
509 %tmp = lshr i64 %a, 23
510 %res = trunc i64 %tmp to i16
511 ret i16 %res
512 }
513
514 ; CHECK-LABEL: @test15
515 ; CHECK: asr w0, w0, #25
516 define signext i8 @test15(i32 %a) {
517 %tmp = ashr i32 %a, 25
518 %res = trunc i32 %tmp to i8
519 ret i8 %res
520 }
521
522 ; CHECK-LABEL: @test16
523 ; CHECK: lsr w0, w0, #25
524 define signext i8 @test16(i32 %a) {
525 %tmp = lshr i32 %a, 25
526 %res = trunc i32 %tmp to i8
527 ret i8 %res
528 }
529
530 ; CHECK-LABEL: @test17
531 ; CHECK: lsr x0, x0, #49
532 define signext i16 @test17(i64 %a) {
533 %tmp = lshr i64 %a, 49
534 %res = trunc i64 %tmp to i16
535 ret i16 %res
536 }
537
538 ; SHR with multiple uses is fine as SXTH and SBFX are both aliases of SBFM.
539 ; However, allowing the transformation means the SHR and SBFX can execute in
540 ; parallel.
541 ;
542 ; CHECK-LABEL: @test18
543 ; CHECK: lsr x1, x0, #23
544 ; CHECK: sbfx x0, x0, #23, #16
545 define void @test18(i64 %a) {
546 %tmp = lshr i64 %a, 23
547 %res = trunc i64 %tmp to i16
548 call void @use(i16 %res, i64 %tmp)
549 ret void
550 }
551
552 declare void @use(i16 signext, i64)