Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LLVM][CodeGen][AArch64] while_le(#,max_int) -> all_active #111183

Merged

Conversation

paulwalker-arm
Copy link
Collaborator

When the second operand of an incrementing while instruction is the maximum value, comparisons that include equality can never fail.

When the second operand of an incrementing while instruction is the
maximum value, comparisons that include equality can never fail.
@llvmbot
Copy link
Collaborator

llvmbot commented Oct 4, 2024

@llvm/pr-subscribers-backend-aarch64

Author: Paul Walker (paulwalker-arm)

Changes

When the second operand of an incrementing while instruction is the maximum value, comparisons that include equality can never fail.


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

2 Files Affected:

  • (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (+7)
  • (modified) llvm/test/CodeGen/AArch64/sve-intrinsics-while.ll (+8-10)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 48e1b96d841efb..2646db3d64b1d2 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -5530,6 +5530,13 @@ static SDValue optimizeIncrementingWhile(SDValue Op, SelectionDAG &DAG,
   SDLoc dl(Op);
   APInt X = Op.getConstantOperandAPInt(1);
   APInt Y = Op.getConstantOperandAPInt(2);
+
+  // When the second operand is the maximum value, comparisons that include
+  // equality can never fail and thus we can return an all active predicate.
+  if (IsEqual)
+    if (IsSigned ? Y.isMaxSignedValue() : Y.isMaxValue())
+      return DAG.getConstant(1, dl, Op.getValueType());
+
   bool Overflow;
   APInt NumActiveElems =
       IsSigned ? Y.ssub_ov(X, Overflow) : Y.usub_ov(X, Overflow);
diff --git a/llvm/test/CodeGen/AArch64/sve-intrinsics-while.ll b/llvm/test/CodeGen/AArch64/sve-intrinsics-while.ll
index 8380d5ca55cf29..ab4554428be450 100644
--- a/llvm/test/CodeGen/AArch64/sve-intrinsics-while.ll
+++ b/llvm/test/CodeGen/AArch64/sve-intrinsics-while.ll
@@ -128,13 +128,12 @@ define <vscale x 16 x i1> @whilele_b_ii_dont_fold_to_ptrue_overflow() {
   ret <vscale x 16 x i1> %out
 }
 
-define <vscale x 16 x i1> @whilele_b_ii_dont_fold_to_ptrue_increment_overflow() {
-; CHECK-LABEL: whilele_b_ii_dont_fold_to_ptrue_increment_overflow:
+define <vscale x 16 x i1> @whilele_b_ii_known_always_true() {
+; CHECK-LABEL: whilele_b_ii_known_always_true:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    mov w8, #2147483647 // =0x7fffffff
-; CHECK-NEXT:    whilele p0.b, wzr, w8
+; CHECK-NEXT:    ptrue p0.b
 ; CHECK-NEXT:    ret
-  %out = call <vscale x 16 x i1> @llvm.aarch64.sve.whilele.nxv16i1.i32(i32 0, i32 2147483647)
+  %out = call <vscale x 16 x i1> @llvm.aarch64.sve.whilele.nxv16i1.i32(i32 2147483646, i32 2147483647)
   ret <vscale x 16 x i1> %out
 }
 
@@ -388,13 +387,12 @@ define <vscale x 16 x i1> @whilels_b_ii_dont_fold_to_ptrue_overflow() {
   ret <vscale x 16 x i1> %out
 }
 
-define <vscale x 16 x i1> @whilels_b_ii_dont_fold_to_ptrue_increment_overflow() {
-; CHECK-LABEL: whilels_b_ii_dont_fold_to_ptrue_increment_overflow:
+define <vscale x 16 x i1> @whilels_b_ii_known_always_true() {
+; CHECK-LABEL: whilels_b_ii_known_always_true:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    mov w8, #-1 // =0xffffffff
-; CHECK-NEXT:    whilels p0.b, wzr, w8
+; CHECK-NEXT:    ptrue p0.b
 ; CHECK-NEXT:    ret
-  %out = call <vscale x 16 x i1> @llvm.aarch64.sve.whilels.nxv16i1.i32(i32 0, i32 4294967295)
+  %out = call <vscale x 16 x i1> @llvm.aarch64.sve.whilels.nxv16i1.i32(i32 4294967294, i32 4294967295)
   ret <vscale x 16 x i1> %out
 }
 

@ktkachov
Copy link

ktkachov commented Oct 7, 2024

I'm not familiar enough with the LLVM code here to tell if this is a problem, but this transform is only valid if the NZCV output of WHILELE is unused, right? Otherwise it'd have to fold to PTRUES

@paulwalker-arm
Copy link
Collaborator Author

I'm not familiar enough with the LLVM code here to tell if this is a problem, but this transform is only valid if the NZCV output of WHILELE is unused, right? Otherwise it'd have to fold to PTRUES

We don't expose the "S" instruction variants at this level but instead have a dedicated PTEST ISD node that we later try to combine into an instruction that also sets the flags.

@paulwalker-arm
Copy link
Collaborator Author

Review ping.

@paulwalker-arm paulwalker-arm merged commit f1ade1f into llvm:main Oct 22, 2024
11 checks passed
@paulwalker-arm paulwalker-arm deleted the sve-while-saturation-bug-fix branch October 22, 2024 11:28
EricWF pushed a commit to efcs/llvm-project that referenced this pull request Oct 22, 2024
When the second operand of an incrementing while instruction is the
maximum value, comparisons that include equality can never fail.
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