if (TargetRegisterInfo::isPhysicalRegister(VReg))
return None;
break;
+ case TargetOpcode::G_INTTOPTR:
+ VReg = MI->getOperand(1).getReg();
+ break;
default:
return None;
}
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)
+# 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
--- |
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
...
---
-# 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
...
---
-# 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
...
---
-# 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
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
+
+...
; 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
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]]]
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
; 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]]]
; 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]]]