diff options
author | Amara Emerson <aemerson@apple.com> | 2019-07-10 19:21:43 +0000 |
---|---|---|
committer | Amara Emerson <aemerson@apple.com> | 2019-07-10 19:21:43 +0000 |
commit | 7a4d2df04a932fcc859d7f25c5a60253b99380f7 (patch) | |
tree | eb1d5f49c63746376f65d6730bc440ce5c25404b | |
parent | 5f5237c2764b504ce764af17ab06eec71073a653 (diff) | |
download | bcm5719-llvm-7a4d2df04a932fcc859d7f25c5a60253b99380f7.tar.gz bcm5719-llvm-7a4d2df04a932fcc859d7f25c5a60253b99380f7.zip |
[AArch64][GlobalISel] Optimize compare and branch cases with G_INTTOPTR and unknown values.
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
llvm-svn: 365690
5 files changed, 131 insertions, 43 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp index deccdc6c750..766ea1d60ba 100644 --- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp +++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp @@ -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; } diff --git a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp index 41b58504daf..4e13fb8e202 100644 --- a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -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) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-cbz.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-cbz.mir index 4075ba279c7..c8fd3069d73 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/select-cbz.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-cbz.mir @@ -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 + +... diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-jump-table-brjt.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-jump-table-brjt.mir index 85b32e12903..bf71804af34 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/select-jump-table-brjt.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-jump-table-brjt.mir @@ -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 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/swifterror.ll b/llvm/test/CodeGen/AArch64/GlobalISel/swifterror.ll index 83e48a6a504..386771fa94f 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/swifterror.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/swifterror.ll @@ -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]]] |