Skip to content

Conversation

@AZero13
Copy link
Contributor

@AZero13 AZero13 commented Jul 1, 2025

They work on ARM too.

@llvmbot
Copy link
Member

llvmbot commented Jul 1, 2025

@llvm/pr-subscribers-backend-arm

Author: AZero13 (AZero13)

Changes

They work on ARM too.


Full diff: https://github.com/llvm/llvm-project/pull/146565.diff

2 Files Affected:

  • (modified) llvm/lib/Target/ARM/ARMISelLowering.cpp (+20)
  • (added) llvm/test/CodeGen/ARM/min-max-combine.ll (+150)
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 2f89e23993385..c520bfa5d2468 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -5510,6 +5510,26 @@ SDValue ARMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
   SDValue FalseVal = Op.getOperand(3);
   ConstantSDNode *CFVal = dyn_cast<ConstantSDNode>(FalseVal);
   ConstantSDNode *CTVal = dyn_cast<ConstantSDNode>(TrueVal);
+  ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS);
+  if (Op.getValueType().isInteger()) {
+    // Check for SMAX(lhs, 0) and SMIN(lhs, 0) patterns.
+    // (SELECT_CC setgt, lhs, 0, lhs, 0) -> (BIC lhs, (SRA lhs, typesize-1))
+    // (SELECT_CC setlt, lhs, 0, lhs, 0) -> (AND lhs, (SRA lhs, typesize-1))
+    // Both require less instructions than compare and conditional select.
+    if ((CC == ISD::SETGT || CC == ISD::SETLT) && LHS == TrueVal && RHSC &&
+        RHSC->isZero() && CFVal && CFVal->isZero() &&
+        LHS.getValueType() == RHS.getValueType()) {
+      EVT VT = LHS.getValueType();
+      SDValue Shift =
+          DAG.getNode(ISD::SRA, dl, VT, LHS,
+                      DAG.getConstant(VT.getSizeInBits() - 1, dl, VT));
+
+      if (CC == ISD::SETGT)
+        Shift = DAG.getNOT(dl, Shift, VT);
+
+      return DAG.getNode(ISD::AND, dl, VT, LHS, Shift);
+    }
+  }
 
   if (Subtarget->hasV8_1MMainlineOps() && CFVal && CTVal &&
       LHS.getValueType() == MVT::i32 && RHS.getValueType() == MVT::i32) {
diff --git a/llvm/test/CodeGen/ARM/min-max-combine.ll b/llvm/test/CodeGen/ARM/min-max-combine.ll
new file mode 100644
index 0000000000000..b9a7690009337
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/min-max-combine.ll
@@ -0,0 +1,150 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=armv7a < %s | FileCheck %s --check-prefix=ARM
+; RUN: llc -mtriple=armv6m < %s | FileCheck %s --check-prefix=THUMB
+; RUN: llc -mtriple=armv7m < %s | FileCheck %s --check-prefix=THUMB2
+
+declare i8 @llvm.smax.i8(i8 %a, i8 %b) readnone
+
+define i8 @smaxi8_zero(i8 %a) {
+; ARM-LABEL: smaxi8_zero:
+; ARM:       @ %bb.0:
+; ARM-NEXT:    sxtb r0, r0
+; ARM-NEXT:    bic r0, r0, r0, asr #31
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: smaxi8_zero:
+; THUMB:       @ %bb.0:
+; THUMB-NEXT:    sxtb r0, r0
+; THUMB-NEXT:    asrs r1, r0, #31
+; THUMB-NEXT:    bics r0, r1
+; THUMB-NEXT:    bx lr
+;
+; THUMB2-LABEL: smaxi8_zero:
+; THUMB2:       @ %bb.0:
+; THUMB2-NEXT:    sxtb r0, r0
+; THUMB2-NEXT:    bic.w r0, r0, r0, asr #31
+; THUMB2-NEXT:    bx lr
+  %c = call i8 @llvm.smax.i8(i8 %a, i8 0)
+  ret i8 %c
+}
+
+declare i16 @llvm.smax.i16(i16 %a, i16 %b) readnone
+
+define i16 @smaxi16_zero(i16 %a) {
+; ARM-LABEL: smaxi16_zero:
+; ARM:       @ %bb.0:
+; ARM-NEXT:    sxth r0, r0
+; ARM-NEXT:    bic r0, r0, r0, asr #31
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: smaxi16_zero:
+; THUMB:       @ %bb.0:
+; THUMB-NEXT:    sxth r0, r0
+; THUMB-NEXT:    asrs r1, r0, #31
+; THUMB-NEXT:    bics r0, r1
+; THUMB-NEXT:    bx lr
+;
+; THUMB2-LABEL: smaxi16_zero:
+; THUMB2:       @ %bb.0:
+; THUMB2-NEXT:    sxth r0, r0
+; THUMB2-NEXT:    bic.w r0, r0, r0, asr #31
+; THUMB2-NEXT:    bx lr
+  %c = call i16 @llvm.smax.i16(i16 %a, i16 0)
+  ret i16 %c
+}
+
+declare i32 @llvm.smax.i32(i32 %a, i32 %b) readnone
+
+define i32 @smaxi32_zero(i32 %a) {
+; ARM-LABEL: smaxi32_zero:
+; ARM:       @ %bb.0:
+; ARM-NEXT:    bic r0, r0, r0, asr #31
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: smaxi32_zero:
+; THUMB:       @ %bb.0:
+; THUMB-NEXT:    asrs r1, r0, #31
+; THUMB-NEXT:    bics r0, r1
+; THUMB-NEXT:    bx lr
+;
+; THUMB2-LABEL: smaxi32_zero:
+; THUMB2:       @ %bb.0:
+; THUMB2-NEXT:    bic.w r0, r0, r0, asr #31
+; THUMB2-NEXT:    bx lr
+  %c = call i32 @llvm.smax.i32(i32 %a, i32 0)
+  ret i32 %c
+}
+
+; SMIN
+
+declare i8 @llvm.smin.i8(i8 %a, i8 %b) readnone
+
+define i8 @smini8_zero(i8 %a) {
+; ARM-LABEL: smini8_zero:
+; ARM:       @ %bb.0:
+; ARM-NEXT:    sxtb r0, r0
+; ARM-NEXT:    and r0, r0, r0, asr #31
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: smini8_zero:
+; THUMB:       @ %bb.0:
+; THUMB-NEXT:    sxtb r1, r0
+; THUMB-NEXT:    asrs r0, r1, #31
+; THUMB-NEXT:    ands r0, r1
+; THUMB-NEXT:    bx lr
+;
+; THUMB2-LABEL: smini8_zero:
+; THUMB2:       @ %bb.0:
+; THUMB2-NEXT:    sxtb r0, r0
+; THUMB2-NEXT:    and.w r0, r0, r0, asr #31
+; THUMB2-NEXT:    bx lr
+  %c = call i8 @llvm.smin.i8(i8 %a, i8 0)
+  ret i8 %c
+}
+
+declare i16 @llvm.smin.i16(i16 %a, i16 %b) readnone
+
+define i16 @smini16_zero(i16 %a) {
+; ARM-LABEL: smini16_zero:
+; ARM:       @ %bb.0:
+; ARM-NEXT:    sxth r0, r0
+; ARM-NEXT:    and r0, r0, r0, asr #31
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: smini16_zero:
+; THUMB:       @ %bb.0:
+; THUMB-NEXT:    sxth r1, r0
+; THUMB-NEXT:    asrs r0, r1, #31
+; THUMB-NEXT:    ands r0, r1
+; THUMB-NEXT:    bx lr
+;
+; THUMB2-LABEL: smini16_zero:
+; THUMB2:       @ %bb.0:
+; THUMB2-NEXT:    sxth r0, r0
+; THUMB2-NEXT:    and.w r0, r0, r0, asr #31
+; THUMB2-NEXT:    bx lr
+  %c = call i16 @llvm.smin.i16(i16 %a, i16 0)
+  ret i16 %c
+}
+
+declare i32 @llvm.smin.i32(i32 %a, i32 %b) readnone
+
+define i32 @smini32_zero(i32 %a) {
+; ARM-LABEL: smini32_zero:
+; ARM:       @ %bb.0:
+; ARM-NEXT:    and r0, r0, r0, asr #31
+; ARM-NEXT:    bx lr
+;
+; THUMB-LABEL: smini32_zero:
+; THUMB:       @ %bb.0:
+; THUMB-NEXT:    asrs r1, r0, #31
+; THUMB-NEXT:    ands r0, r1
+; THUMB-NEXT:    bx lr
+;
+; THUMB2-LABEL: smini32_zero:
+; THUMB2:       @ %bb.0:
+; THUMB2-NEXT:    and.w r0, r0, r0, asr #31
+; THUMB2-NEXT:    bx lr
+  %c = call i32 @llvm.smin.i32(i32 %a, i32 0)
+  ret i32 %c
+}

@AZero13
Copy link
Contributor Author

AZero13 commented Jul 8, 2025

@davemgreen

@AZero13 AZero13 requested a review from davemgreen July 10, 2025 16:39
Copy link
Collaborator

@davemgreen davemgreen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks.

@AZero13
Copy link
Contributor Author

AZero13 commented Jul 10, 2025

Thank you. Can you please merge?

@AZero13 AZero13 requested a review from davemgreen July 10, 2025 18:20
@davemgreen davemgreen merged commit 0edc98c into llvm:main Jul 10, 2025
9 checks passed
@AZero13 AZero13 deleted the king-2 branch July 10, 2025 20:11
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jul 10, 2025

LLVM Buildbot has detected a new failure on builder llvm-clang-aarch64-darwin running on doug-worker-4 while building llvm at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/190/builds/23244

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'LLVM :: tools/llvm-mt/xml_error.test' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
not /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/llvm-mt /manifest /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/tools/llvm-mt/Inputs/bad.manifest 2>&1 >/dev/null | /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck    /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/tools/llvm-mt/xml_error.test # RUN: at line 4
+ not /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/llvm-mt /manifest /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/tools/llvm-mt/Inputs/bad.manifest
+ /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/tools/llvm-mt/xml_error.test
not /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/llvm-mt /manifest /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/tools/llvm-mt/Inputs/empty.manifest 2>&1 >/dev/null |    /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/tools/llvm-mt/xml_error.test -check-prefix=EMPTY # RUN: at line 9
+ not /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/llvm-mt /manifest /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/tools/llvm-mt/Inputs/empty.manifest
+ /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/tools/llvm-mt/xml_error.test -check-prefix=EMPTY
/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/llvm-mt /inputresource:foo.res    /manifest /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/tools/llvm-mt/Inputs/test_manifest.manifest    /out:/Users/buildbot/buildbot-root/aarch64-darwin/build/test/tools/llvm-mt/Output/xml_error.test.tmp | /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/tools/llvm-mt/xml_error.test -check-prefix=NOT_SUPPORTED # RUN: at line 14
+ /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/llvm-mt /inputresource:foo.res /manifest /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/tools/llvm-mt/Inputs/test_manifest.manifest /out:/Users/buildbot/buildbot-root/aarch64-darwin/build/test/tools/llvm-mt/Output/xml_error.test.tmp
+ /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/tools/llvm-mt/xml_error.test -check-prefix=NOT_SUPPORTED
llvm-mt: error: /Users/buildbot/buildbot-root/aarch64-darwin/build/test/tools/llvm-mt/Output/xml_error.test.tmp: No space left on device

--

********************


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants