[llvm] [LLVM][LangRef] Remove "n > 0" restriction from get.active.lanes.mask. (PR #152140)

Paul Walker via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 5 06:50:40 PDT 2025


https://github.com/paulwalker-arm created https://github.com/llvm/llvm-project/pull/152140

The specification for get.active.lanes.mask says a limit value of zero results in poison. This seems like an artificial restriction and means you cannot use the intrinsic to create minimal loops of the form:

  foo(int count, ....) {
    int i = 0;
    while (mask = get.active.lane.mask(i, count)) {
      ; do work
      i += count_bits(mask);
    }
  }

I cannot see any code that generates poison in this case, in fact ConstantFoldFixedVectorCall returns the logical result (i.e. an all false vector).

There are also cases like `can_overflow_i64_induction_var` in sve-tail-folding-overflow-checks.ll that look broken by the current definition? for the case when "%N <= vscale * 4".

For these reasons I'm asking if we can simply remove the restriction?

>From 2de4c92778cc3ec342fa6ea01e1b8456fc33091d Mon Sep 17 00:00:00 2001
From: Paul Walker <paul.walker at arm.com>
Date: Tue, 5 Aug 2025 11:01:22 +0000
Subject: [PATCH] [LLVM][LangRef] Remove "n > 0" restriction from
 get.active.lanes.mask.

The specification for get.active.lanes.mask says a limit value of
zero results in poison. This seems like an artificial restriction and
means you cannot use the intrinsic to create minimal loops of the form:

  foo(int count, ....) {
    int i = 0;
    while (mask = get.active.lane.mask(i, count)) {
      ; do work
      i += count_bits(mask);
    }
  }

I cannot see any code that generates poison in this case, in fact
ConstantFoldFixedVectorCall returns the logical result (i.e. an all
false vector).

There are also cases like `can_overflow_i64_induction_var` in
sve-tail-folding-overflow-checks.ll that look broken by the current
definition? for the case when "%N <= vscale * 4".

For these reasons I'm asking if we can simply remove the restriction?
---
 llvm/docs/LangRef.rst                         |  3 +-
 llvm/lib/Analysis/Lint.cpp                    |  7 ----
 .../Analysis/Lint/get-active-lane-mask.ll     | 39 -------------------
 3 files changed, 1 insertion(+), 48 deletions(-)
 delete mode 100644 llvm/test/Analysis/Lint/get-active-lane-mask.ll

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index d8cd3b894cda4..77b10b3c22ef4 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -24014,8 +24014,7 @@ indexed by ``i``,  and ``%base``, ``%n`` are the two arguments to
 ``llvm.get.active.lane.mask.*``, ``%icmp`` is an integer compare and ``ult``
 the unsigned less-than comparison operator.  Overflow cannot occur in
 ``(%base + i)`` and its comparison against ``%n`` as it is performed in integer
-numbers and not in machine numbers.  If ``%n`` is ``0``, then the result is a
-poison value. The above is equivalent to:
+numbers and not in machine numbers.  The above is equivalent to:
 
 ::
 
diff --git a/llvm/lib/Analysis/Lint.cpp b/llvm/lib/Analysis/Lint.cpp
index 1168005f48c0e..32a4264c0343c 100644
--- a/llvm/lib/Analysis/Lint.cpp
+++ b/llvm/lib/Analysis/Lint.cpp
@@ -374,13 +374,6 @@ void Lint::visitCallBase(CallBase &I) {
       visitMemoryReference(I, MemoryLocation::getForArgument(&I, 0, TLI),
                            std::nullopt, nullptr, MemRef::Read | MemRef::Write);
       break;
-    case Intrinsic::get_active_lane_mask:
-      if (auto *TripCount = dyn_cast<ConstantInt>(I.getArgOperand(1)))
-        Check(!TripCount->isZero(),
-              "get_active_lane_mask: operand #2 "
-              "must be greater than 0",
-              &I);
-      break;
     }
 }
 
diff --git a/llvm/test/Analysis/Lint/get-active-lane-mask.ll b/llvm/test/Analysis/Lint/get-active-lane-mask.ll
deleted file mode 100644
index e9b161846e8bd..0000000000000
--- a/llvm/test/Analysis/Lint/get-active-lane-mask.ll
+++ /dev/null
@@ -1,39 +0,0 @@
-; RUN: opt -passes=lint -disable-output < %s 2>&1 | FileCheck %s
-
-define <4 x i1> @t1(i32 %IV) {
-;
-; CHECK:      get_active_lane_mask: operand #2 must be greater than 0
-; CHECK-NEXT: %res = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 %IV, i32 0)
-;
-  %res = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 %IV, i32 0)
-  ret <4 x i1> %res
-}
-
-define <4 x i1> @t2(i32 %IV) {
-;
-; CHECK-NOT: get_active_lane_mask
-; CHECK-NOT: call <4 x i1> @llvm.get.active.lane.mask
-;
-  %res = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 %IV, i32 1)
-  ret <4 x i1> %res
-}
-
-define <4 x i1> @t3(i32 %IV) {
-;
-; CHECK-NOT: get_active_lane_mask
-; CHECK-NOT: call <4 x i1> @llvm.get.active.lane.mask
-;
-  %res = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 %IV, i32 -1)
-  ret <4 x i1> %res
-}
-
-define <4 x i1> @t4(i32 %IV, i32 %TC) {
-;
-; CHECK-NOT: get_active_lane_mask
-; CHECK-NOT: call <4 x i1> @llvm.get.active.lane.mask
-;
-  %res = call <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32 %IV, i32 %TC)
-  ret <4 x i1> %res
-}
-
-declare <4 x i1> @llvm.get.active.lane.mask.v4i1.i32(i32, i32)



More information about the llvm-commits mailing list