diff options
author | David Green <david.green@arm.com> | 2022-08-05 07:48:42 +0100 |
---|---|---|
committer | David Green <david.green@arm.com> | 2022-08-05 07:48:42 +0100 |
commit | 38c2366b3ffcc11da178b8d52814ef609e08d40f (patch) | |
tree | cc24206d76caca104548c28280a6c5abaa145cb8 | |
parent | b2c9ff727379992ef472e32620635b7e5d561d60 (diff) |
[AArch64][GlobalISel] Recognise some CCMPri
This is a simple addition to emitConditionalComparison, to match CCMP
with immediates using getIConstantVRegValWithLookThrough, letting it
select the CCMPri variants of the instructions.
Differential Revision: https://reviews.llvm.org/D131073
-rw-r--r-- | llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp | 14 | ||||
-rw-r--r-- | llvm/test/CodeGen/AArch64/arm64-ccmp.ll | 132 |
2 files changed, 53 insertions, 93 deletions
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp index eb8d0552173d..1b1c2c4690d6 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -4821,8 +4821,13 @@ MachineInstr *AArch64InstructionSelector::emitConditionalComparison( LLT OpTy = MRI.getType(LHS); assert(OpTy.getSizeInBits() == 32 || OpTy.getSizeInBits() == 64); unsigned CCmpOpc; + Optional<ValueAndVReg> C; if (CmpInst::isIntPredicate(CC)) { - CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMPWr : AArch64::CCMPXr; + C = getIConstantVRegValWithLookThrough(RHS, MRI); + if (C && C->Value.ult(32)) + CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMPWi : AArch64::CCMPXi; + else + CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMPWr : AArch64::CCMPXr; } else { switch (OpTy.getSizeInBits()) { case 16: @@ -4841,7 +4846,12 @@ MachineInstr *AArch64InstructionSelector::emitConditionalComparison( AArch64CC::CondCode InvOutCC = AArch64CC::getInvertedCondCode(OutCC); unsigned NZCV = AArch64CC::getNZCVToSatisfyCondCode(InvOutCC); auto CCmp = - MIB.buildInstr(CCmpOpc, {}, {LHS, RHS}).addImm(NZCV).addImm(Predicate); + MIB.buildInstr(CCmpOpc, {}, {LHS}); + if (C) + CCmp.addImm(C->Value.getZExtValue()); + else + CCmp.addReg(RHS); + CCmp.addImm(NZCV).addImm(Predicate); constrainSelectedInstRegOperands(*CCmp, TII, TRI, RBI); return &*CCmp; } diff --git a/llvm/test/CodeGen/AArch64/arm64-ccmp.ll b/llvm/test/CodeGen/AArch64/arm64-ccmp.ll index 163cf55d4d74..eff39ed7a6da 100644 --- a/llvm/test/CodeGen/AArch64/arm64-ccmp.ll +++ b/llvm/test/CodeGen/AArch64/arm64-ccmp.ll @@ -536,10 +536,9 @@ define i64 @gccbug(i64 %x0, i64 %x1) { ; GISEL-LABEL: gccbug: ; GISEL: ; %bb.0: ; GISEL-NEXT: mov w8, #2 -; GISEL-NEXT: mov w9, #4 ; GISEL-NEXT: cmp x0, #2 -; GISEL-NEXT: ccmp x0, x9, #4, ne -; GISEL-NEXT: ccmp x1, xzr, #0, eq +; GISEL-NEXT: ccmp x0, #4, #4, ne +; GISEL-NEXT: ccmp x1, #0, #0, eq ; GISEL-NEXT: csinc x0, x8, xzr, eq ; GISEL-NEXT: ret %cmp0 = icmp eq i64 %x1, 0 @@ -554,25 +553,14 @@ define i64 @gccbug(i64 %x0, i64 %x1) { } define i32 @select_ororand(i32 %w0, i32 %w1, i32 %w2, i32 %w3) { -; SDISEL-LABEL: select_ororand: -; SDISEL: ; %bb.0: -; SDISEL-NEXT: cmp w3, #4 -; SDISEL-NEXT: ccmp w2, #2, #0, gt -; SDISEL-NEXT: ccmp w1, #13, #2, ge -; SDISEL-NEXT: ccmp w0, #0, #4, ls -; SDISEL-NEXT: csel w0, w3, wzr, eq -; SDISEL-NEXT: ret -; -; GISEL-LABEL: select_ororand: -; GISEL: ; %bb.0: -; GISEL-NEXT: mov w8, #13 -; GISEL-NEXT: mov w9, #2 -; GISEL-NEXT: cmp w3, #4 -; GISEL-NEXT: ccmp w2, w9, #0, gt -; GISEL-NEXT: ccmp w1, w8, #2, ge -; GISEL-NEXT: ccmp w0, wzr, #4, ls -; GISEL-NEXT: csel w0, w3, wzr, eq -; GISEL-NEXT: ret +; CHECK-LABEL: select_ororand: +; CHECK: ; %bb.0: +; CHECK-NEXT: cmp w3, #4 +; CHECK-NEXT: ccmp w2, #2, #0, gt +; CHECK-NEXT: ccmp w1, #13, #2, ge +; CHECK-NEXT: ccmp w0, #0, #4, ls +; CHECK-NEXT: csel w0, w3, wzr, eq +; CHECK-NEXT: ret %c0 = icmp eq i32 %w0, 0 %c1 = icmp ugt i32 %w1, 13 %c2 = icmp slt i32 %w2, 2 @@ -585,21 +573,13 @@ define i32 @select_ororand(i32 %w0, i32 %w1, i32 %w2, i32 %w3) { } define i32 @select_andor(i32 %v1, i32 %v2, i32 %v3) { -; SDISEL-LABEL: select_andor: -; SDISEL: ; %bb.0: -; SDISEL-NEXT: cmp w1, w2 -; SDISEL-NEXT: ccmp w0, #0, #4, lt -; SDISEL-NEXT: ccmp w0, w1, #0, eq -; SDISEL-NEXT: csel w0, w0, w1, eq -; SDISEL-NEXT: ret -; -; GISEL-LABEL: select_andor: -; GISEL: ; %bb.0: -; GISEL-NEXT: cmp w1, w2 -; GISEL-NEXT: ccmp w0, wzr, #4, lt -; GISEL-NEXT: ccmp w0, w1, #0, eq -; GISEL-NEXT: csel w0, w0, w1, eq -; GISEL-NEXT: ret +; CHECK-LABEL: select_andor: +; CHECK: ; %bb.0: +; CHECK-NEXT: cmp w1, w2 +; CHECK-NEXT: ccmp w0, #0, #4, lt +; CHECK-NEXT: ccmp w0, w1, #0, eq +; CHECK-NEXT: csel w0, w0, w1, eq +; CHECK-NEXT: ret %c0 = icmp eq i32 %v1, %v2 %c1 = icmp sge i32 %v2, %v3 %c2 = icmp eq i32 %v1, 0 @@ -1001,24 +981,14 @@ define i32 @f128_select_and_olt_oge(fp128 %v0, fp128 %v1, fp128 %v2, fp128 %v3, ; This testcase resembles the core problem of http://llvm.org/PR39550 ; (an OR operation is 2 levels deep but needs to be implemented first) define i32 @deep_or(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) { -; SDISEL-LABEL: deep_or: -; SDISEL: ; %bb.0: -; SDISEL-NEXT: cmp w2, #20 -; SDISEL-NEXT: ccmp w2, #15, #4, ne -; SDISEL-NEXT: ccmp w1, #0, #4, eq -; SDISEL-NEXT: ccmp w0, #0, #4, ne -; SDISEL-NEXT: csel w0, w4, w5, ne -; SDISEL-NEXT: ret -; -; GISEL-LABEL: deep_or: -; GISEL: ; %bb.0: -; GISEL-NEXT: mov w8, #15 -; GISEL-NEXT: cmp w2, #20 -; GISEL-NEXT: ccmp w2, w8, #4, ne -; GISEL-NEXT: ccmp w1, wzr, #4, eq -; GISEL-NEXT: ccmp w0, wzr, #4, ne -; GISEL-NEXT: csel w0, w4, w5, ne -; GISEL-NEXT: ret +; CHECK-LABEL: deep_or: +; CHECK: ; %bb.0: +; CHECK-NEXT: cmp w2, #20 +; CHECK-NEXT: ccmp w2, #15, #4, ne +; CHECK-NEXT: ccmp w1, #0, #4, eq +; CHECK-NEXT: ccmp w0, #0, #4, ne +; CHECK-NEXT: csel w0, w4, w5, ne +; CHECK-NEXT: ret %c0 = icmp ne i32 %a0, 0 %c1 = icmp ne i32 %a1, 0 %c2 = icmp eq i32 %a2, 15 @@ -1033,24 +1003,14 @@ define i32 @deep_or(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) { ; Variation of deep_or, we still need to implement the OR first though. define i32 @deep_or1(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) { -; SDISEL-LABEL: deep_or1: -; SDISEL: ; %bb.0: -; SDISEL-NEXT: cmp w2, #20 -; SDISEL-NEXT: ccmp w2, #15, #4, ne -; SDISEL-NEXT: ccmp w0, #0, #4, eq -; SDISEL-NEXT: ccmp w1, #0, #4, ne -; SDISEL-NEXT: csel w0, w4, w5, ne -; SDISEL-NEXT: ret -; -; GISEL-LABEL: deep_or1: -; GISEL: ; %bb.0: -; GISEL-NEXT: mov w8, #15 -; GISEL-NEXT: cmp w2, #20 -; GISEL-NEXT: ccmp w2, w8, #4, ne -; GISEL-NEXT: ccmp w0, wzr, #4, eq -; GISEL-NEXT: ccmp w1, wzr, #4, ne -; GISEL-NEXT: csel w0, w4, w5, ne -; GISEL-NEXT: ret +; CHECK-LABEL: deep_or1: +; CHECK: ; %bb.0: +; CHECK-NEXT: cmp w2, #20 +; CHECK-NEXT: ccmp w2, #15, #4, ne +; CHECK-NEXT: ccmp w0, #0, #4, eq +; CHECK-NEXT: ccmp w1, #0, #4, ne +; CHECK-NEXT: csel w0, w4, w5, ne +; CHECK-NEXT: ret %c0 = icmp ne i32 %a0, 0 %c1 = icmp ne i32 %a1, 0 %c2 = icmp eq i32 %a2, 15 @@ -1065,24 +1025,14 @@ define i32 @deep_or1(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) { ; Variation of deep_or, we still need to implement the OR first though. define i32 @deep_or2(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) { -; SDISEL-LABEL: deep_or2: -; SDISEL: ; %bb.0: -; SDISEL-NEXT: cmp w2, #20 -; SDISEL-NEXT: ccmp w2, #15, #4, ne -; SDISEL-NEXT: ccmp w1, #0, #4, eq -; SDISEL-NEXT: ccmp w0, #0, #4, ne -; SDISEL-NEXT: csel w0, w4, w5, ne -; SDISEL-NEXT: ret -; -; GISEL-LABEL: deep_or2: -; GISEL: ; %bb.0: -; GISEL-NEXT: mov w8, #15 -; GISEL-NEXT: cmp w2, #20 -; GISEL-NEXT: ccmp w2, w8, #4, ne -; GISEL-NEXT: ccmp w1, wzr, #4, eq -; GISEL-NEXT: ccmp w0, wzr, #4, ne -; GISEL-NEXT: csel w0, w4, w5, ne -; GISEL-NEXT: ret +; CHECK-LABEL: deep_or2: +; CHECK: ; %bb.0: +; CHECK-NEXT: cmp w2, #20 +; CHECK-NEXT: ccmp w2, #15, #4, ne +; CHECK-NEXT: ccmp w1, #0, #4, eq +; CHECK-NEXT: ccmp w0, #0, #4, ne +; CHECK-NEXT: csel w0, w4, w5, ne +; CHECK-NEXT: ret %c0 = icmp ne i32 %a0, 0 %c1 = icmp ne i32 %a1, 0 %c2 = icmp eq i32 %a2, 15 |