[llvm] [InstCombine] Fold canonicalized form of vecreduce_or(get_active_lane_mask) (PR #220085)

Namish Kukreja via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 30 11:03:37 PDT 2026


https://github.com/namikukr-qc updated https://github.com/llvm/llvm-project/pull/220085

>From 9ecc34f63a7d62698be4ab9ed537b8f128ea35ff Mon Sep 17 00:00:00 2001
From: Namish Kukreja <namikukr at qti.qualcomm.com>
Date: Thu, 27 Aug 2026 11:27:37 -0700
Subject: [PATCH 1/5] precommit tests

---
 .../InstCombine/get_active_lane_mask.ll       | 127 ++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/get_active_lane_mask.ll b/llvm/test/Transforms/InstCombine/get_active_lane_mask.ll
index 44ce3f73fab67..632461494dd5d 100644
--- a/llvm/test/Transforms/InstCombine/get_active_lane_mask.ll
+++ b/llvm/test/Transforms/InstCombine/get_active_lane_mask.ll
@@ -89,3 +89,130 @@ define <4 x i1> @extract_fixed_from_active_lane_mask() vscale_range(4, 4) {
   ret <4 x i1> %ext
 }
 
+define i1 @vecreduce_or_get_active_lane_mask_v4i1(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @vecreduce_or_get_active_lane_mask_v4i1(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[MASK:%.*]] = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 [[A]], i32 [[B]])
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <4 x i1> [[MASK]] to i4
+; CHECK-NEXT:    [[RED:%.*]] = icmp ne i4 [[TMP1]], 0
+; CHECK-NEXT:    ret i1 [[RED]]
+;
+  %mask = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 %a, i32 %b)
+  %red = call i1 @llvm.vector.reduce.or.i1(<4 x i1> %mask)
+  ret i1 %red
+}
+
+define i1 @vecreduce_or_get_active_lane_mask_v16i1(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @vecreduce_or_get_active_lane_mask_v16i1(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[MASK:%.*]] = call <16 x i1> @llvm.get.active.lane.mask.v16i1.i32(i32 [[A]], i32 [[B]])
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <16 x i1> [[MASK]] to i16
+; CHECK-NEXT:    [[RED:%.*]] = icmp ne i16 [[TMP1]], 0
+; CHECK-NEXT:    ret i1 [[RED]]
+;
+  %mask = call <16 x i1> @llvm.get.active.lane.mask.v16i1.i32(i32 %a, i32 %b)
+  %red = call i1 @llvm.vector.reduce.or.i1(<16 x i1> %mask)
+  ret i1 %red
+}
+
+define i1 @vecreduce_or_get_active_lane_mask_v32i1(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @vecreduce_or_get_active_lane_mask_v32i1(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[MASK:%.*]] = call <32 x i1> @llvm.get.active.lane.mask.v32i1.i32(i32 [[A]], i32 [[B]])
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <32 x i1> [[MASK]] to i32
+; CHECK-NEXT:    [[RED:%.*]] = icmp ne i32 [[TMP1]], 0
+; CHECK-NEXT:    ret i1 [[RED]]
+;
+  %mask = call <32 x i1> @llvm.get.active.lane.mask.v32i1.i32(i32 %a, i32 %b)
+  %red = call i1 @llvm.vector.reduce.or.i1(<32 x i1> %mask)
+  ret i1 %red
+}
+
+define i1 @vecreduce_or_get_active_lane_mask_v4i1_multiuse(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @vecreduce_or_get_active_lane_mask_v4i1_multiuse(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[MASK:%.*]] = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 [[A]], i32 [[B]])
+; CHECK-NEXT:    call void (...) @llvm.fake.use(<4 x i1> [[MASK]])
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <4 x i1> [[MASK]] to i4
+; CHECK-NEXT:    [[RED:%.*]] = icmp ne i4 [[TMP1]], 0
+; CHECK-NEXT:    ret i1 [[RED]]
+;
+  %mask = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 %a, i32 %b)
+  call void (...) @llvm.fake.use(<4 x i1> %mask)
+  %red = call i1 @llvm.vector.reduce.or.i1(<4 x i1> %mask)
+  ret i1 %red
+}
+
+define i1 @vecreduce_or_get_active_lane_mask_v16i1_multiuse(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @vecreduce_or_get_active_lane_mask_v16i1_multiuse(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[MASK:%.*]] = call <16 x i1> @llvm.get.active.lane.mask.v16i1.i32(i32 [[A]], i32 [[B]])
+; CHECK-NEXT:    call void (...) @llvm.fake.use(<16 x i1> [[MASK]])
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <16 x i1> [[MASK]] to i16
+; CHECK-NEXT:    [[RED:%.*]] = icmp ne i16 [[TMP1]], 0
+; CHECK-NEXT:    ret i1 [[RED]]
+;
+  %mask = call <16 x i1> @llvm.get.active.lane.mask.v16i1.i32(i32 %a, i32 %b)
+  call void (...) @llvm.fake.use(<16 x i1> %mask)
+  %red = call i1 @llvm.vector.reduce.or.i1(<16 x i1> %mask)
+  ret i1 %red
+}
+
+define i1 @vecreduce_or_get_active_lane_mask_v32i1_multiuse(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @vecreduce_or_get_active_lane_mask_v32i1_multiuse(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[MASK:%.*]] = call <32 x i1> @llvm.get.active.lane.mask.v32i1.i32(i32 [[A]], i32 [[B]])
+; CHECK-NEXT:    call void (...) @llvm.fake.use(<32 x i1> [[MASK]])
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <32 x i1> [[MASK]] to i32
+; CHECK-NEXT:    [[RED:%.*]] = icmp ne i32 [[TMP1]], 0
+; CHECK-NEXT:    ret i1 [[RED]]
+;
+  %mask = call <32 x i1> @llvm.get.active.lane.mask.v32i1.i32(i32 %a, i32 %b)
+  call void (...) @llvm.fake.use(<32 x i1> %mask)
+  %red = call i1 @llvm.vector.reduce.or.i1(<32 x i1> %mask)
+  ret i1 %red
+}
+
+define i8 @vecreduce_or_zext_get_active_lane_mask_v4i1(i32 %a, i32 %b) {
+; CHECK-LABEL: define i8 @vecreduce_or_zext_get_active_lane_mask_v4i1(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[MASK:%.*]] = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 [[A]], i32 [[B]])
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <4 x i1> [[MASK]] to i4
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i4 [[TMP1]], 0
+; CHECK-NEXT:    [[RED:%.*]] = zext i1 [[TMP2]] to i8
+; CHECK-NEXT:    ret i8 [[RED]]
+;
+  %mask = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 %a, i32 %b)
+  %ext = zext <4 x i1> %mask to <4 x i8>
+  %red = call i8 @llvm.vector.reduce.or.v4i8(<4 x i8> %ext)
+  ret i8 %red
+}
+
+define i8 @vecreduce_or_sext_get_active_lane_mask_v4i1(i32 %a, i32 %b) {
+; CHECK-LABEL: define i8 @vecreduce_or_sext_get_active_lane_mask_v4i1(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[MASK:%.*]] = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 [[A]], i32 [[B]])
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <4 x i1> [[MASK]] to i4
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i4 [[TMP1]], 0
+; CHECK-NEXT:    [[RED:%.*]] = sext i1 [[TMP2]] to i8
+; CHECK-NEXT:    ret i8 [[RED]]
+;
+  %mask = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 %a, i32 %b)
+  %ext = sext <4 x i1> %mask to <4 x i8>
+  %red = call i8 @llvm.vector.reduce.or.v4i8(<4 x i8> %ext)
+  ret i8 %red
+}
+
+define i1 @bitcast_inverted_condition_v32i1(i32 %a, i32 %b) {
+; CHECK-LABEL: define i1 @bitcast_inverted_condition_v32i1(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[MASK:%.*]] = call <32 x i1> @llvm.get.active.lane.mask.v32i1.i32(i32 [[A]], i32 [[B]])
+; CHECK-NEXT:    [[CAST:%.*]] = bitcast <32 x i1> [[MASK]] to i32
+; CHECK-NEXT:    [[RED:%.*]] = icmp eq i32 [[CAST]], 0
+; CHECK-NEXT:    ret i1 [[RED]]
+;
+  %mask = call <32 x i1> @llvm.get.active.lane.mask.v32i1.i32(i32 %a, i32 %b)
+  %cast = bitcast <32 x i1> %mask to i32
+  %red = icmp eq i32 %cast, 0
+  ret i1 %red
+}

>From aeb7977163a62348ffc2e80a3b49df781011e43b Mon Sep 17 00:00:00 2001
From: Namish Kukreja <namikukr at qti.qualcomm.com>
Date: Thu, 27 Aug 2026 13:37:58 -0700
Subject: [PATCH 2/5] [InstCombine] Fold vecreduce_or(get_active_lane_mask)

We can fold a vecreduce_or from a get_active_lane_mask based on its
bounds to simply lower_bound < upper_bound.
---
 .../InstCombine/InstCombineCompares.cpp       | 16 +++++++++
 .../InstCombine/get_active_lane_mask.ll       | 33 +++++--------------
 2 files changed, 25 insertions(+), 24 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 72f08b398e45d..d65a0f29b6981 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -3581,6 +3581,22 @@ Instruction *InstCombinerImpl::foldICmpBitCast(ICmpInst &Cmp) {
     }
   }
 
+  // Fold the canonicalized form of vector_reduce_or if the arg is
+  // get_active_lane mask.
+  // icmp ne (bitcast <N x i1> to iN (get_active_lane_mask(l, h))), 0 -> 
+  //            icmp ult l, h 
+  // icmp eq (bitcast <N x i1> to iN (get_active_lane_mask(l, h))), 0 -> 
+  //            icmp uge l, h
+  Value *Upper, *Lower;
+  if (match(BCSrcOp, m_Intrinsic<Intrinsic::get_active_lane_mask>(
+                         m_Value(Lower), m_Value(Upper))) &&
+      match(Op1, m_Zero())) {
+    if (Pred == ICmpInst::ICMP_NE)
+      return new ICmpInst(ICmpInst::ICMP_ULT, Lower, Upper);
+    if (Pred == ICmpInst::ICMP_EQ)
+      return new ICmpInst(ICmpInst::ICMP_UGE, Lower, Upper);
+  }
+
   const APInt *C;
   if (!match(Cmp.getOperand(1), m_APInt(C)) || !DstType->isIntegerTy() ||
       !SrcType->isIntOrIntVectorTy())
diff --git a/llvm/test/Transforms/InstCombine/get_active_lane_mask.ll b/llvm/test/Transforms/InstCombine/get_active_lane_mask.ll
index 632461494dd5d..891738483cdbe 100644
--- a/llvm/test/Transforms/InstCombine/get_active_lane_mask.ll
+++ b/llvm/test/Transforms/InstCombine/get_active_lane_mask.ll
@@ -92,9 +92,7 @@ define <4 x i1> @extract_fixed_from_active_lane_mask() vscale_range(4, 4) {
 define i1 @vecreduce_or_get_active_lane_mask_v4i1(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @vecreduce_or_get_active_lane_mask_v4i1(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[MASK:%.*]] = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 [[A]], i32 [[B]])
-; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <4 x i1> [[MASK]] to i4
-; CHECK-NEXT:    [[RED:%.*]] = icmp ne i4 [[TMP1]], 0
+; CHECK-NEXT:    [[RED:%.*]] = icmp ult i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[RED]]
 ;
   %mask = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 %a, i32 %b)
@@ -105,9 +103,7 @@ define i1 @vecreduce_or_get_active_lane_mask_v4i1(i32 %a, i32 %b) {
 define i1 @vecreduce_or_get_active_lane_mask_v16i1(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @vecreduce_or_get_active_lane_mask_v16i1(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[MASK:%.*]] = call <16 x i1> @llvm.get.active.lane.mask.v16i1.i32(i32 [[A]], i32 [[B]])
-; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <16 x i1> [[MASK]] to i16
-; CHECK-NEXT:    [[RED:%.*]] = icmp ne i16 [[TMP1]], 0
+; CHECK-NEXT:    [[RED:%.*]] = icmp ult i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[RED]]
 ;
   %mask = call <16 x i1> @llvm.get.active.lane.mask.v16i1.i32(i32 %a, i32 %b)
@@ -118,9 +114,7 @@ define i1 @vecreduce_or_get_active_lane_mask_v16i1(i32 %a, i32 %b) {
 define i1 @vecreduce_or_get_active_lane_mask_v32i1(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @vecreduce_or_get_active_lane_mask_v32i1(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[MASK:%.*]] = call <32 x i1> @llvm.get.active.lane.mask.v32i1.i32(i32 [[A]], i32 [[B]])
-; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <32 x i1> [[MASK]] to i32
-; CHECK-NEXT:    [[RED:%.*]] = icmp ne i32 [[TMP1]], 0
+; CHECK-NEXT:    [[RED:%.*]] = icmp ult i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[RED]]
 ;
   %mask = call <32 x i1> @llvm.get.active.lane.mask.v32i1.i32(i32 %a, i32 %b)
@@ -133,8 +127,7 @@ define i1 @vecreduce_or_get_active_lane_mask_v4i1_multiuse(i32 %a, i32 %b) {
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
 ; CHECK-NEXT:    [[MASK:%.*]] = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 [[A]], i32 [[B]])
 ; CHECK-NEXT:    call void (...) @llvm.fake.use(<4 x i1> [[MASK]])
-; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <4 x i1> [[MASK]] to i4
-; CHECK-NEXT:    [[RED:%.*]] = icmp ne i4 [[TMP1]], 0
+; CHECK-NEXT:    [[RED:%.*]] = icmp ult i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[RED]]
 ;
   %mask = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 %a, i32 %b)
@@ -148,8 +141,7 @@ define i1 @vecreduce_or_get_active_lane_mask_v16i1_multiuse(i32 %a, i32 %b) {
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
 ; CHECK-NEXT:    [[MASK:%.*]] = call <16 x i1> @llvm.get.active.lane.mask.v16i1.i32(i32 [[A]], i32 [[B]])
 ; CHECK-NEXT:    call void (...) @llvm.fake.use(<16 x i1> [[MASK]])
-; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <16 x i1> [[MASK]] to i16
-; CHECK-NEXT:    [[RED:%.*]] = icmp ne i16 [[TMP1]], 0
+; CHECK-NEXT:    [[RED:%.*]] = icmp ult i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[RED]]
 ;
   %mask = call <16 x i1> @llvm.get.active.lane.mask.v16i1.i32(i32 %a, i32 %b)
@@ -163,8 +155,7 @@ define i1 @vecreduce_or_get_active_lane_mask_v32i1_multiuse(i32 %a, i32 %b) {
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
 ; CHECK-NEXT:    [[MASK:%.*]] = call <32 x i1> @llvm.get.active.lane.mask.v32i1.i32(i32 [[A]], i32 [[B]])
 ; CHECK-NEXT:    call void (...) @llvm.fake.use(<32 x i1> [[MASK]])
-; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <32 x i1> [[MASK]] to i32
-; CHECK-NEXT:    [[RED:%.*]] = icmp ne i32 [[TMP1]], 0
+; CHECK-NEXT:    [[RED:%.*]] = icmp ult i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[RED]]
 ;
   %mask = call <32 x i1> @llvm.get.active.lane.mask.v32i1.i32(i32 %a, i32 %b)
@@ -176,9 +167,7 @@ define i1 @vecreduce_or_get_active_lane_mask_v32i1_multiuse(i32 %a, i32 %b) {
 define i8 @vecreduce_or_zext_get_active_lane_mask_v4i1(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i8 @vecreduce_or_zext_get_active_lane_mask_v4i1(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[MASK:%.*]] = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 [[A]], i32 [[B]])
-; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <4 x i1> [[MASK]] to i4
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i4 [[TMP1]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[A]], [[B]]
 ; CHECK-NEXT:    [[RED:%.*]] = zext i1 [[TMP2]] to i8
 ; CHECK-NEXT:    ret i8 [[RED]]
 ;
@@ -191,9 +180,7 @@ define i8 @vecreduce_or_zext_get_active_lane_mask_v4i1(i32 %a, i32 %b) {
 define i8 @vecreduce_or_sext_get_active_lane_mask_v4i1(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i8 @vecreduce_or_sext_get_active_lane_mask_v4i1(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[MASK:%.*]] = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 [[A]], i32 [[B]])
-; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <4 x i1> [[MASK]] to i4
-; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i4 [[TMP1]], 0
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[A]], [[B]]
 ; CHECK-NEXT:    [[RED:%.*]] = sext i1 [[TMP2]] to i8
 ; CHECK-NEXT:    ret i8 [[RED]]
 ;
@@ -206,9 +193,7 @@ define i8 @vecreduce_or_sext_get_active_lane_mask_v4i1(i32 %a, i32 %b) {
 define i1 @bitcast_inverted_condition_v32i1(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @bitcast_inverted_condition_v32i1(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[MASK:%.*]] = call <32 x i1> @llvm.get.active.lane.mask.v32i1.i32(i32 [[A]], i32 [[B]])
-; CHECK-NEXT:    [[CAST:%.*]] = bitcast <32 x i1> [[MASK]] to i32
-; CHECK-NEXT:    [[RED:%.*]] = icmp eq i32 [[CAST]], 0
+; CHECK-NEXT:    [[RED:%.*]] = icmp uge i32 [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[RED]]
 ;
   %mask = call <32 x i1> @llvm.get.active.lane.mask.v32i1.i32(i32 %a, i32 %b)

>From 7ee72c7873d5ffc12a114274018832c1ec9a5e4f Mon Sep 17 00:00:00 2001
From: Namish Kukreja <namikukr at qti.qualcomm.com>
Date: Mon, 31 Aug 2026 15:11:06 -0700
Subject: [PATCH 3/5] fix clang-format

---
 llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index d65a0f29b6981..417ef2430d698 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -3583,9 +3583,9 @@ Instruction *InstCombinerImpl::foldICmpBitCast(ICmpInst &Cmp) {
 
   // Fold the canonicalized form of vector_reduce_or if the arg is
   // get_active_lane mask.
-  // icmp ne (bitcast <N x i1> to iN (get_active_lane_mask(l, h))), 0 -> 
-  //            icmp ult l, h 
-  // icmp eq (bitcast <N x i1> to iN (get_active_lane_mask(l, h))), 0 -> 
+  // icmp ne (bitcast <N x i1> to iN (get_active_lane_mask(l, h))), 0 ->
+  //            icmp ult l, h
+  // icmp eq (bitcast <N x i1> to iN (get_active_lane_mask(l, h))), 0 ->
   //            icmp uge l, h
   Value *Upper, *Lower;
   if (match(BCSrcOp, m_Intrinsic<Intrinsic::get_active_lane_mask>(

>From affc0bf7b25a269f3ab57015f63406364a3a358e Mon Sep 17 00:00:00 2001
From: Namish Kukreja <namikukr at qti.qualcomm.com>
Date: Fri, 25 Sep 2026 14:59:02 -0700
Subject: [PATCH 4/5] remove unnecessary tests + check scalar integer bitcast
 target

---
 .../InstCombine/InstCombineCompares.cpp       |  2 +-
 .../InstCombine/get_active_lane_mask.ll       | 50 -------------------
 2 files changed, 1 insertion(+), 51 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 417ef2430d698..c9bad74d2a3d4 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -3590,7 +3590,7 @@ Instruction *InstCombinerImpl::foldICmpBitCast(ICmpInst &Cmp) {
   Value *Upper, *Lower;
   if (match(BCSrcOp, m_Intrinsic<Intrinsic::get_active_lane_mask>(
                          m_Value(Lower), m_Value(Upper))) &&
-      match(Op1, m_Zero())) {
+      match(Op1, m_Zero()) && DstType->isIntegerTy()) {
     if (Pred == ICmpInst::ICMP_NE)
       return new ICmpInst(ICmpInst::ICMP_ULT, Lower, Upper);
     if (Pred == ICmpInst::ICMP_EQ)
diff --git a/llvm/test/Transforms/InstCombine/get_active_lane_mask.ll b/llvm/test/Transforms/InstCombine/get_active_lane_mask.ll
index 891738483cdbe..8b0420e39dcd7 100644
--- a/llvm/test/Transforms/InstCombine/get_active_lane_mask.ll
+++ b/llvm/test/Transforms/InstCombine/get_active_lane_mask.ll
@@ -100,28 +100,6 @@ define i1 @vecreduce_or_get_active_lane_mask_v4i1(i32 %a, i32 %b) {
   ret i1 %red
 }
 
-define i1 @vecreduce_or_get_active_lane_mask_v16i1(i32 %a, i32 %b) {
-; CHECK-LABEL: define i1 @vecreduce_or_get_active_lane_mask_v16i1(
-; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[RED:%.*]] = icmp ult i32 [[A]], [[B]]
-; CHECK-NEXT:    ret i1 [[RED]]
-;
-  %mask = call <16 x i1> @llvm.get.active.lane.mask.v16i1.i32(i32 %a, i32 %b)
-  %red = call i1 @llvm.vector.reduce.or.i1(<16 x i1> %mask)
-  ret i1 %red
-}
-
-define i1 @vecreduce_or_get_active_lane_mask_v32i1(i32 %a, i32 %b) {
-; CHECK-LABEL: define i1 @vecreduce_or_get_active_lane_mask_v32i1(
-; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[RED:%.*]] = icmp ult i32 [[A]], [[B]]
-; CHECK-NEXT:    ret i1 [[RED]]
-;
-  %mask = call <32 x i1> @llvm.get.active.lane.mask.v32i1.i32(i32 %a, i32 %b)
-  %red = call i1 @llvm.vector.reduce.or.i1(<32 x i1> %mask)
-  ret i1 %red
-}
-
 define i1 @vecreduce_or_get_active_lane_mask_v4i1_multiuse(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i1 @vecreduce_or_get_active_lane_mask_v4i1_multiuse(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
@@ -136,34 +114,6 @@ define i1 @vecreduce_or_get_active_lane_mask_v4i1_multiuse(i32 %a, i32 %b) {
   ret i1 %red
 }
 
-define i1 @vecreduce_or_get_active_lane_mask_v16i1_multiuse(i32 %a, i32 %b) {
-; CHECK-LABEL: define i1 @vecreduce_or_get_active_lane_mask_v16i1_multiuse(
-; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[MASK:%.*]] = call <16 x i1> @llvm.get.active.lane.mask.v16i1.i32(i32 [[A]], i32 [[B]])
-; CHECK-NEXT:    call void (...) @llvm.fake.use(<16 x i1> [[MASK]])
-; CHECK-NEXT:    [[RED:%.*]] = icmp ult i32 [[A]], [[B]]
-; CHECK-NEXT:    ret i1 [[RED]]
-;
-  %mask = call <16 x i1> @llvm.get.active.lane.mask.v16i1.i32(i32 %a, i32 %b)
-  call void (...) @llvm.fake.use(<16 x i1> %mask)
-  %red = call i1 @llvm.vector.reduce.or.i1(<16 x i1> %mask)
-  ret i1 %red
-}
-
-define i1 @vecreduce_or_get_active_lane_mask_v32i1_multiuse(i32 %a, i32 %b) {
-; CHECK-LABEL: define i1 @vecreduce_or_get_active_lane_mask_v32i1_multiuse(
-; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
-; CHECK-NEXT:    [[MASK:%.*]] = call <32 x i1> @llvm.get.active.lane.mask.v32i1.i32(i32 [[A]], i32 [[B]])
-; CHECK-NEXT:    call void (...) @llvm.fake.use(<32 x i1> [[MASK]])
-; CHECK-NEXT:    [[RED:%.*]] = icmp ult i32 [[A]], [[B]]
-; CHECK-NEXT:    ret i1 [[RED]]
-;
-  %mask = call <32 x i1> @llvm.get.active.lane.mask.v32i1.i32(i32 %a, i32 %b)
-  call void (...) @llvm.fake.use(<32 x i1> %mask)
-  %red = call i1 @llvm.vector.reduce.or.i1(<32 x i1> %mask)
-  ret i1 %red
-}
-
 define i8 @vecreduce_or_zext_get_active_lane_mask_v4i1(i32 %a, i32 %b) {
 ; CHECK-LABEL: define i8 @vecreduce_or_zext_get_active_lane_mask_v4i1(
 ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {

>From 86a7bafb4260c3077947876adacd5c0a6812a10e Mon Sep 17 00:00:00 2001
From: Namish Kukreja <namikukr at qti.qualcomm.com>
Date: Wed, 30 Sep 2026 11:03:15 -0700
Subject: [PATCH 5/5] add test for non-scalar int bitcast

---
 .../Transforms/InstCombine/get_active_lane_mask.ll | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/get_active_lane_mask.ll b/llvm/test/Transforms/InstCombine/get_active_lane_mask.ll
index 8b0420e39dcd7..f084f0a577e43 100644
--- a/llvm/test/Transforms/InstCombine/get_active_lane_mask.ll
+++ b/llvm/test/Transforms/InstCombine/get_active_lane_mask.ll
@@ -151,3 +151,17 @@ define i1 @bitcast_inverted_condition_v32i1(i32 %a, i32 %b) {
   %red = icmp eq i32 %cast, 0
   ret i1 %red
 }
+
+define <2 x i1> @bitcast_not_scalar_integer(i32 %a, i32 %b) {
+; CHECK-LABEL: define <2 x i1> @bitcast_not_scalar_integer(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
+; CHECK-NEXT:    [[MASK:%.*]] = call <32 x i1> @llvm.get.active.lane.mask.v32i1.i32(i32 [[A]], i32 [[B]])
+; CHECK-NEXT:    [[CAST:%.*]] = bitcast <32 x i1> [[MASK]] to <2 x i16>
+; CHECK-NEXT:    [[RED:%.*]] = icmp eq <2 x i16> [[CAST]], zeroinitializer
+; CHECK-NEXT:    ret <2 x i1> [[RED]]
+;
+  %mask = call <32 x i1> @llvm.get.active.lane.mask.v32i1(i32 %a, i32 %b)
+  %cast = bitcast <32 x i1> %mask to <2 x i16>
+  %red = icmp eq <2 x i16> %cast, zeroinitializer
+  ret <2 x i1> %red
+}



More information about the llvm-commits mailing list