]> granicus.if.org Git - llvm/commitdiff
[AArch64][GlobalISel] Optimize compare and branch cases with G_INTTOPTR and unknown...
authorAmara Emerson <aemerson@apple.com>
Wed, 10 Jul 2019 19:21:43 +0000 (19:21 +0000)
committerAmara Emerson <aemerson@apple.com>
Wed, 10 Jul 2019 19:21:43 +0000 (19:21 +0000)
Since we have distinct types for pointers and scalars, G_INTTOPTRs can sometimes
obstruct attempts to find constant source values. These usually come about when
try to do some kind of null pointer check. Teaching getConstantVRegValWithLookThrough
about this operation allows the CBZ/CBNZ optimization to catch more cases.

This change also improves the case where we can't find a constant source at all.
Previously we would emit a cmp, cset and tbnz for that. Now we try to just emit
a cmp and conditional branch, saving an instruction.

The cumulative code size improvement of this change plus D64354 is 5.5% geomean
on arm64 CTMark -O0.

Differential Revision: https://reviews.llvm.org/D64377

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@365690 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/GlobalISel/Utils.cpp
lib/Target/AArch64/AArch64InstructionSelector.cpp
test/CodeGen/AArch64/GlobalISel/select-cbz.mir
test/CodeGen/AArch64/GlobalISel/select-jump-table-brjt.mir
test/CodeGen/AArch64/GlobalISel/swifterror.ll

index deccdc6c7500726c9b5b90c62911eb8bdb155199..766ea1d60bace02083928c132f2b6624bf84182f 100644 (file)
@@ -238,6 +238,9 @@ Optional<ValueAndVReg> llvm::getConstantVRegValWithLookThrough(
       if (TargetRegisterInfo::isPhysicalRegister(VReg))
         return None;
       break;
+    case TargetOpcode::G_INTTOPTR:
+      VReg = MI->getOperand(1).getReg();
+      break;
     default:
       return None;
     }
index 41b58504daf1bc0243f121d9916f1bdfea8f6330..4e13fb8e202743ff37fafb6d4e4f6dbe0e8c1f60 100644 (file)
@@ -899,12 +899,23 @@ bool AArch64InstructionSelector::selectCompareBranch(
 
   Register LHS = CCMI->getOperand(2).getReg();
   Register RHS = CCMI->getOperand(3).getReg();
-  if (!getConstantVRegVal(RHS, MRI))
+  auto VRegAndVal = getConstantVRegValWithLookThrough(RHS, MRI);
+  if (!VRegAndVal)
     std::swap(RHS, LHS);
 
-  const auto RHSImm = getConstantVRegVal(RHS, MRI);
-  if (!RHSImm || *RHSImm != 0)
-    return false;
+  VRegAndVal = getConstantVRegValWithLookThrough(RHS, MRI);
+  if (!VRegAndVal || VRegAndVal->Value != 0) {
+    MachineIRBuilder MIB(I);
+    // If we can't select a CBZ then emit a cmp + Bcc.
+    if (!emitIntegerCompare(CCMI->getOperand(2), CCMI->getOperand(3),
+                            CCMI->getOperand(1), MIB))
+      return false;
+    const AArch64CC::CondCode CC = changeICMPPredToAArch64CC(
+        (CmpInst::Predicate)CCMI->getOperand(1).getPredicate());
+    MIB.buildInstr(AArch64::Bcc, {}, {}).addImm(CC).addMBB(DestMBB);
+    I.eraseFromParent();
+    return true;
+  }
 
   const RegisterBank &RB = *RBI.getRegBank(LHS, MRI, TRI);
   if (RB.getID() != AArch64::GPRRegBankID)
index 4075ba279c75723e2839c9d16a2e22c3f093ffdf..c8fd3069d7388a19a8df5db7b3ce6a41dc84859d 100644 (file)
@@ -1,3 +1,4 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
 # RUN: llc -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
 
 --- |
@@ -5,20 +6,23 @@
   define void @cbz_s64() { ret void }
   define void @cbnz_s32() { ret void }
   define void @cbnz_s64() { ret void }
+  define hidden void @test_rhs_inttoptr(i64* %p) { ret void }
+  define hidden void @test_rhs_unknown(i64* %p) { ret void }
 ...
 
 ---
-# CHECK-LABEL: name: cbz_s32
 name:            cbz_s32
 legalized:       true
 regBankSelected: true
 
-# CHECK:  body:
-# CHECK:   bb.0:
-# CHECK:    %0:gpr32 = COPY $w0
-# CHECK:    CBZW %0, %bb.1
-# CHECK:    B %bb.0
 body:             |
+  ; CHECK-LABEL: name: cbz_s32
+  ; CHECK: bb.0:
+  ; CHECK:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
+  ; CHECK:   [[COPY:%[0-9]+]]:gpr32 = COPY $w0
+  ; CHECK:   CBZW [[COPY]], %bb.1
+  ; CHECK:   B %bb.0
+  ; CHECK: bb.1:
   bb.0:
     liveins: $w0
     successors: %bb.0, %bb.1
@@ -34,17 +38,18 @@ body:             |
 ...
 
 ---
-# CHECK-LABEL: name: cbz_s64
 name:            cbz_s64
 legalized:       true
 regBankSelected: true
 
-# CHECK:  body:
-# CHECK:   bb.0:
-# CHECK:    %0:gpr64 = COPY $x0
-# CHECK:    CBZX %0, %bb.1
-# CHECK:    B %bb.0
 body:             |
+  ; CHECK-LABEL: name: cbz_s64
+  ; CHECK: bb.0:
+  ; CHECK:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
+  ; CHECK:   [[COPY:%[0-9]+]]:gpr64 = COPY $x0
+  ; CHECK:   CBZX [[COPY]], %bb.1
+  ; CHECK:   B %bb.0
+  ; CHECK: bb.1:
   bb.0:
     liveins: $x0
     successors: %bb.0, %bb.1
@@ -60,17 +65,18 @@ body:             |
 ...
 
 ---
-# CHECK-LABEL: name: cbnz_s32
 name:            cbnz_s32
 legalized:       true
 regBankSelected: true
 
-# CHECK:  body:
-# CHECK:   bb.0:
-# CHECK:    %0:gpr32 = COPY $w0
-# CHECK:    CBNZW %0, %bb.1
-# CHECK:    B %bb.0
 body:             |
+  ; CHECK-LABEL: name: cbnz_s32
+  ; CHECK: bb.0:
+  ; CHECK:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
+  ; CHECK:   [[COPY:%[0-9]+]]:gpr32 = COPY $w0
+  ; CHECK:   CBNZW [[COPY]], %bb.1
+  ; CHECK:   B %bb.0
+  ; CHECK: bb.1:
   bb.0:
     liveins: $w0
     successors: %bb.0, %bb.1
@@ -86,17 +92,18 @@ body:             |
 ...
 
 ---
-# CHECK-LABEL: name: cbnz_s64
 name:            cbnz_s64
 legalized:       true
 regBankSelected: true
 
-# CHECK:  body:
-# CHECK:   bb.0:
-# CHECK:    %0:gpr64 = COPY $x0
-# CHECK:    CBNZX %0, %bb.1
-# CHECK:    B %bb.0
 body:             |
+  ; CHECK-LABEL: name: cbnz_s64
+  ; CHECK: bb.0:
+  ; CHECK:   successors: %bb.0(0x40000000), %bb.1(0x40000000)
+  ; CHECK:   [[COPY:%[0-9]+]]:gpr64 = COPY $x0
+  ; CHECK:   CBNZX [[COPY]], %bb.1
+  ; CHECK:   B %bb.0
+  ; CHECK: bb.1:
   bb.0:
     liveins: $x0
     successors: %bb.0, %bb.1
@@ -110,3 +117,80 @@ body:             |
 
   bb.1:
 ...
+---
+name:            test_rhs_inttoptr
+alignment:       2
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  ; CHECK-LABEL: name: test_rhs_inttoptr
+  ; CHECK: bb.0:
+  ; CHECK:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; CHECK:   liveins: $x0
+  ; CHECK:   [[COPY:%[0-9]+]]:gpr64common = COPY $x0
+  ; CHECK:   CBZX [[COPY]], %bb.2
+  ; CHECK: bb.1:
+  ; CHECK:   successors: %bb.2(0x80000000)
+  ; CHECK:   STRXui $xzr, [[COPY]], 0 :: (store 8 into %ir.p)
+  ; CHECK: bb.2:
+  ; CHECK:   RET_ReallyLR
+  bb.1:
+    successors: %bb.2, %bb.3
+    liveins: $x0
+
+    %0:gpr(p0) = COPY $x0
+    %2:gpr(s64) = G_CONSTANT i64 0
+    %1:gpr(p0) = G_INTTOPTR %2(s64)
+    %4:gpr(s32) = G_ICMP intpred(eq), %0(p0), %1
+    %3:gpr(s1) = G_TRUNC %4(s32)
+    G_BRCOND %3(s1), %bb.3
+
+  bb.2:
+    %5:gpr(s64) = G_CONSTANT i64 0
+    G_STORE %5(s64), %0(p0) :: (store 8 into %ir.p)
+
+  bb.3:
+    RET_ReallyLR
+
+...
+---
+name:            test_rhs_unknown
+alignment:       2
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  ; CHECK-LABEL: name: test_rhs_unknown
+  ; CHECK: bb.0:
+  ; CHECK:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; CHECK:   liveins: $x0
+  ; CHECK:   [[COPY:%[0-9]+]]:gpr64sp = COPY $x0
+  ; CHECK:   [[LDRXui:%[0-9]+]]:gpr64common = LDRXui [[COPY]], 0 :: (load 8 from %ir.p)
+  ; CHECK:   $xzr = SUBSXri [[LDRXui]], 42, 0, implicit-def $nzcv
+  ; CHECK:   Bcc 0, %bb.2, implicit $nzcv
+  ; CHECK: bb.1:
+  ; CHECK:   successors: %bb.2(0x80000000)
+  ; CHECK:   STRXui $xzr, [[COPY]], 0 :: (store 8 into %ir.p)
+  ; CHECK: bb.2:
+  ; CHECK:   RET_ReallyLR
+  bb.1:
+    successors: %bb.2, %bb.3
+    liveins: $x0
+
+    %0:gpr(p0) = COPY $x0
+    %2:gpr(s64) = G_CONSTANT i64 42
+    %4:gpr(s64) = G_CONSTANT i64 0
+    %1:gpr(s64) = G_LOAD %0(p0) :: (load 8 from %ir.p)
+    %5:gpr(s32) = G_ICMP intpred(eq), %1(s64), %2
+    %3:gpr(s1) = G_TRUNC %5(s32)
+    G_BRCOND %3(s1), %bb.3
+
+  bb.2:
+    %6:gpr(s64) = G_CONSTANT i64 0
+    G_STORE %6(s64), %0(p0) :: (store 8 into %ir.p)
+
+  bb.3:
+    RET_ReallyLR
+
+...
index 85b32e129037db0c01d16eaa8586fdc4e538f80b..bf71804af34395d6b3fe99d8caa13e6c33c5c689 100644 (file)
@@ -62,8 +62,7 @@ body:             |
   ; CHECK:   [[SUBREG_TO_REG:%[0-9]+]]:gpr64 = SUBREG_TO_REG 0, [[SUBSWri]], %subreg.sub_32
   ; CHECK:   [[UBFMXri:%[0-9]+]]:gpr64common = UBFMXri [[SUBREG_TO_REG]], 0, 31
   ; CHECK:   $xzr = SUBSXri [[UBFMXri]], 71, 0, implicit-def $nzcv
-  ; CHECK:   [[CSINCWr:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 9, implicit $nzcv
-  ; CHECK:   TBNZW [[CSINCWr]], 0, %bb.4
+  ; CHECK:   Bcc 8, %bb.4, implicit $nzcv
   ; CHECK: bb.1.entry:
   ; CHECK:   successors: %bb.3(0x2aaaaaab), %bb.4(0x2aaaaaab), %bb.2(0x2aaaaaab)
   ; CHECK:   [[MOVi32imm1:%[0-9]+]]:gpr32 = MOVi32imm 0
index 83e48a6a504c7ca9da533420119d5d1cf660e7a7..386771fa94f1f0fc136a6d2bf62b24e9c09fdca1 100644 (file)
@@ -28,12 +28,9 @@ entry:
 define float @caller(i8* %error_ref) {
 ; CHECK-LABEL: caller:
 ; CHECK: mov [[ID:x[0-9]+]], x0
-; CHECK: mov [[ZERO:x[0-9]+]], #0
-; CHECK: mov x21, #0
 ; CHECK: bl {{.*}}foo
 ; CHECK: mov x0, x21
-; CHECK: cmp x21, [[ZERO]]
-; CHECK: b.ne
+; CHECK: cbnz x21
 ; Access part of the error object and save it to error_ref
 ; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8]
 ; CHECK: strb [[CODE]], [{{.*}}[[ID]]]
@@ -61,12 +58,10 @@ handler:
 define float @caller2(i8* %error_ref) {
 ; CHECK-LABEL: caller2:
 ; CHECK: mov [[ID:x[0-9]+]], x0
-; CHECK: mov [[ZERO:x[0-9]+]], #0
 ; CHECK: fmov [[CMP:s[0-9]+]], #1.0
 ; CHECK: mov x21, #0
 ; CHECK: bl {{.*}}foo
-; CHECK: cmp x21, [[ZERO]]
-; CHECK: b.ne
+; CHECK: cbnz x21
 ; CHECK: fcmp s0, [[CMP]]
 ; CHECK: b.le
 ; Access part of the error object and save it to error_ref
@@ -193,11 +188,9 @@ define float @caller3(i8* %error_ref) {
 ; CHECK-LABEL: caller3:
 ; CHECK: mov [[ID:x[0-9]+]], x0
 ; CHECK: mov [[ZERO:x[0-9]+]], #0
-; CHECK: mov x21, #0
 ; CHECK: bl {{.*}}foo_sret
 ; CHECK: mov x0, x21
-; CHECK: cmp x21, [[ZERO]]
-; CHECK: b.ne
+; CHECK: cbnz x21
 ; Access part of the error object and save it to error_ref
 ; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8]
 ; CHECK: strb [[CODE]], [{{.*}}[[ID]]]
@@ -272,15 +265,13 @@ define float @caller4(i8* %error_ref) {
 ; CHECK-LABEL: caller4:
 
 ; CHECK: mov [[ID:x[0-9]+]], x0
-; CHECK: mov [[ZERO:x[0-9]+]], #0
 ; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp]
 ; CHECK: mov x21, #0
 ; CHECK: str {{x[0-9]+}}, [sp, #16]
 
 ; CHECK: bl {{.*}}foo_vararg
 ; CHECK: mov x0, x21
-; CHECK: cmp x21, [[ZERO]]
-; CHECK: b.ne
+; CHECK: cbnz x21
 ; Access part of the error object and save it to error_ref
 ; CHECK: ldrb [[CODE:w[0-9]+]], [x0, #8]
 ; CHECK: strb [[CODE]], [{{.*}}[[ID]]]