[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