[llvm] [AArch64] Use ccmn to compare negative imm constants (PR #95825)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 17 11:31:14 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
Author: AtariDreams (AtariDreams)
<details>
<summary>Changes</summary>
Because ccmn is like a + b, it works when using cmp but with values that when negated are in the range of 1 through 31
---
Full diff: https://github.com/llvm/llvm-project/pull/95825.diff
2 Files Affected:
- (modified) llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp (+8-2)
- (modified) llvm/test/CodeGen/AArch64/cmp-chains.ll (+24)
``````````diff
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 4a7c82b393c10..e59caf1b37316 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -4668,8 +4668,12 @@ MachineInstr *AArch64InstructionSelector::emitConditionalComparison(
if (CmpInst::isIntPredicate(CC)) {
assert(OpTy.getSizeInBits() == 32 || OpTy.getSizeInBits() == 64);
C = getIConstantVRegValWithLookThrough(RHS, MRI);
- if (C && C->Value.ult(32))
- CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMPWi : AArch64::CCMPXi;
+ if (C && (C->Value.ult(32) || (C->Value.sgt(-32) && C->Value.isNegative()))) {
+ if (C->Value.ult(32))
+ CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMPWi : AArch64::CCMPXi;
+ else
+ CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMNWi : AArch64::CCMNXi;
+ }
else
CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMPWr : AArch64::CCMPXr;
} else {
@@ -4696,6 +4700,8 @@ MachineInstr *AArch64InstructionSelector::emitConditionalComparison(
MIB.buildInstr(CCmpOpc, {}, {LHS});
if (CCmpOpc == AArch64::CCMPWi || CCmpOpc == AArch64::CCMPXi)
CCmp.addImm(C->Value.getZExtValue());
+ else if (CCmpOpc == AArch64::CCMNWi || CCmpOpc == AArch64::CCMNXi)
+ CCmp.addImm(-C->Value.getSExtValue());
else
CCmp.addReg(RHS);
CCmp.addImm(NZCV).addImm(Predicate);
diff --git a/llvm/test/CodeGen/AArch64/cmp-chains.ll b/llvm/test/CodeGen/AArch64/cmp-chains.ll
index 1d9f39e518593..7ca24f3eabdd0 100644
--- a/llvm/test/CodeGen/AArch64/cmp-chains.ll
+++ b/llvm/test/CodeGen/AArch64/cmp-chains.ll
@@ -242,5 +242,29 @@ define i32 @true_or3(i32 %0, i32 %1, i32 %2) {
%9 = zext i1 %8 to i32
ret i32 %9
}
+
+; (b > -3 && a < c)
+define i32 @neg_range_int(i32 %a, i32 %b, i32 %c) {
+; SDISEL-LABEL: neg_range_int:
+; SDISEL: // %bb.0:
+; SDISEL-NEXT: cmp w0, w2
+; SDISEL-NEXT: mov w8, #-3 // =0xfffffffd
+; SDISEL-NEXT: ccmp w1, w8, #4, lt
+; SDISEL-NEXT: csel w0, w1, w0, gt
+; SDISEL-NEXT: ret
+;
+; GISEL-LABEL: neg_range_int:
+; GISEL: // %bb.0:
+; GISEL-NEXT: cmp w0, w2
+; GISEL-NEXT: ccmn w1, #3, #4, lt
+; GISEL-NEXT: csel w0, w1, w0, gt
+; GISEL-NEXT: ret
+ %cmp = icmp sgt i32 %b, -3
+ %cmp1 = icmp slt i32 %a, %c
+ %or.cond = and i1 %cmp, %cmp1
+ %retval.0 = select i1 %or.cond, i32 %b, i32 %a
+ ret i32 %retval.0
+}
+
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; CHECK: {{.*}}
``````````
</details>
https://github.com/llvm/llvm-project/pull/95825
More information about the llvm-commits
mailing list