[llvm] [LLVM][InstCombine] Add simplification of SVE compare intrinsics. (PR #211249)
Matthew Devereau via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 29 03:38:42 PDT 2026
================
@@ -0,0 +1,309 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+target triple = "aarch64-unknown-linux-gnu"
+
+; The following tests verify the mechanics of simplification. The operation is
+; not important beyond being commutative.
+
+define <vscale x 4 x i1> @cannonicalise_constant_to_rhs(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a) #0 {
+; CHECK-LABEL: define <vscale x 4 x i1> @cannonicalise_constant_to_rhs(
+; CHECK-SAME: <vscale x 4 x i1> [[PG:%.*]], <vscale x 4 x i32> [[A:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[R:%.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.cmpne.nxv4i32(<vscale x 4 x i1> [[PG]], <vscale x 4 x i32> [[A]], <vscale x 4 x i32> splat (i32 303))
+; CHECK-NEXT: ret <vscale x 4 x i1> [[R]]
+;
+ %r = call <vscale x 4 x i1> @llvm.aarch64.sve.cmpne.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> splat (i32 303), <vscale x 4 x i32> %a)
+ ret <vscale x 4 x i1> %r
+}
+
+define <vscale x 4 x i1> @cannot_cannonicalise_constant_to_rhs_not_commutative_int(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a) #0 {
+; CHECK-LABEL: define <vscale x 4 x i1> @cannot_cannonicalise_constant_to_rhs_not_commutative_int(
+; CHECK-SAME: <vscale x 4 x i1> [[PG:%.*]], <vscale x 4 x i32> [[A:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[R:%.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.cmpge.nxv4i32(<vscale x 4 x i1> [[PG]], <vscale x 4 x i32> splat (i32 303), <vscale x 4 x i32> [[A]])
+; CHECK-NEXT: ret <vscale x 4 x i1> [[R]]
+;
+ %r = call <vscale x 4 x i1> @llvm.aarch64.sve.cmpge.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> splat (i32 303), <vscale x 4 x i32> %a)
+ ret <vscale x 4 x i1> %r
+}
+
+define <vscale x 4 x i1> @cannot_cannonicalise_constant_to_rhs_operand_type_mismatch(<vscale x 4 x i1> %pg, <vscale x 2 x i64> %a) #0 {
+; CHECK-LABEL: define <vscale x 4 x i1> @cannot_cannonicalise_constant_to_rhs_operand_type_mismatch(
+; CHECK-SAME: <vscale x 4 x i1> [[PG:%.*]], <vscale x 2 x i64> [[A:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[R:%.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.cmpne.wide.nxv4i32(<vscale x 4 x i1> [[PG]], <vscale x 4 x i32> splat (i32 303), <vscale x 2 x i64> [[A]])
+; CHECK-NEXT: ret <vscale x 4 x i1> [[R]]
+;
+ %r = call <vscale x 4 x i1> @llvm.aarch64.sve.cmpne.wide.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> splat (i32 303), <vscale x 2 x i64> %a)
+ ret <vscale x 4 x i1> %r
+}
+
+define <vscale x 4 x i1> @cannonicalise_fp_constant_to_rhs(<vscale x 4 x i1> %pg, <vscale x 4 x float> %a) #0 {
+; CHECK-LABEL: define <vscale x 4 x i1> @cannonicalise_fp_constant_to_rhs(
+; CHECK-SAME: <vscale x 4 x i1> [[PG:%.*]], <vscale x 4 x float> [[A:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[R:%.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.fcmpne.nxv4f32(<vscale x 4 x i1> [[PG]], <vscale x 4 x float> [[A]], <vscale x 4 x float> splat (float 5.000000e+00))
+; CHECK-NEXT: ret <vscale x 4 x i1> [[R]]
+;
+ %r = call <vscale x 4 x i1> @llvm.aarch64.sve.fcmpne.nxv4f32(<vscale x 4 x i1> %pg, <vscale x 4 x float> splat (float 5.0), <vscale x 4 x float> %a)
+ ret <vscale x 4 x i1> %r
+}
+
+define <vscale x 4 x i1> @cannot_cannonicalise_fp_constant_to_rhs_not_commutative_fp(<vscale x 4 x i1> %pg, <vscale x 4 x float> %a) #0 {
+; CHECK-LABEL: define <vscale x 4 x i1> @cannot_cannonicalise_fp_constant_to_rhs_not_commutative_fp(
+; CHECK-SAME: <vscale x 4 x i1> [[PG:%.*]], <vscale x 4 x float> [[A:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[R:%.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.fcmpge.nxv4f32(<vscale x 4 x i1> [[PG]], <vscale x 4 x float> splat (float 5.000000e+00), <vscale x 4 x float> [[A]])
+; CHECK-NEXT: ret <vscale x 4 x i1> [[R]]
+;
+ %r = call <vscale x 4 x i1> @llvm.aarch64.sve.fcmpge.nxv4f32(<vscale x 4 x i1> %pg, <vscale x 4 x float> splat (float 5.0), <vscale x 4 x float> %a)
+ ret <vscale x 4 x i1> %r
+}
+
+; Show that we only need to know the active lanes are constant.
+define <vscale x 4 x i1> @constant_icmp_after_striping_inactive_lanes(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b) #0 {
+; CHECK-LABEL: define <vscale x 4 x i1> @constant_icmp_after_striping_inactive_lanes(
+; CHECK-SAME: <vscale x 4 x i1> [[PG:%.*]], <vscale x 4 x i32> [[A:%.*]], <vscale x 4 x i32> [[B:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: ret <vscale x 4 x i1> [[PG]]
+;
+ %a.dup = call <vscale x 4 x i32> @llvm.aarch64.sve.dup.nxv4i32(<vscale x 4 x i32> %a, <vscale x 4 x i1> %pg, i32 3)
+ %b.dup = call <vscale x 4 x i32> @llvm.aarch64.sve.dup.nxv4i32(<vscale x 4 x i32> %b, <vscale x 4 x i1> %pg, i32 2)
+ %r = call <vscale x 4 x i1> @llvm.aarch64.sve.cmpgt.nxv4i32(<vscale x 4 x i1> %pg, <vscale x 4 x i32> %a.dup, <vscale x 4 x i32> %b.dup)
+ ret <vscale x 4 x i1> %r
+}
+
+define <vscale x 16 x i1> @constant_icmp_due_to_range_of_type(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %a) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @constant_icmp_due_to_range_of_type(
+; CHECK-SAME: <vscale x 16 x i1> [[PG:%.*]], <vscale x 16 x i8> [[A:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: ret <vscale x 16 x i1> zeroinitializer
+;
+ %r = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpgt.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %a, <vscale x 16 x i8> splat (i8 127))
+ ret <vscale x 16 x i1> %r
+}
+
+; Wide compares implicitly promote the smaller typed operand to the larger type.
+define <vscale x 16 x i1> @non_constant_icmp_wide_due_to_range_of_type(<vscale x 16 x i1> %pg, <vscale x 2 x i64> %a) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @non_constant_icmp_wide_due_to_range_of_type(
+; CHECK-SAME: <vscale x 16 x i1> [[PG:%.*]], <vscale x 2 x i64> [[A:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[R:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpgt.wide.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> splat (i8 127), <vscale x 2 x i64> [[A]])
+; CHECK-NEXT: ret <vscale x 16 x i1> [[R]]
+;
+ %r = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpgt.wide.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> splat (i8 127), <vscale x 2 x i64> %a)
+ ret <vscale x 16 x i1> %r
+}
+
+; TODO: We can do better here.
+; Wide compares implicitly promote the smaller typed operand to the larger type,
+; but with the larger operand being constant we know it is too big.
+define <vscale x 16 x i1> @constant_icmp_wide_due_to_range_of_type(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %a) #0 {
+; CHECK-LABEL: define <vscale x 16 x i1> @constant_icmp_wide_due_to_range_of_type(
+; CHECK-SAME: <vscale x 16 x i1> [[PG:%.*]], <vscale x 16 x i8> [[A:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[R:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpgt.wide.nxv16i8(<vscale x 16 x i1> [[PG]], <vscale x 16 x i8> [[A]], <vscale x 2 x i64> splat (i64 127))
+; CHECK-NEXT: ret <vscale x 16 x i1> [[R]]
+;
+ %r = call <vscale x 16 x i1> @llvm.aarch64.sve.cmpgt.wide.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %a, <vscale x 2 x i64> splat (i64 127))
+ ret <vscale x 16 x i1> %r
+}
+
+; Ensure inactive lanes are zero'd after simplification.
----------------
MDevereau wrote:
```suggestion
; Ensure inactive lanes are zeroed after simplification.
```
https://github.com/llvm/llvm-project/pull/211249
More information about the llvm-commits
mailing list