[llvm] [RISCV] Convert vector.reduce.or + cttz.elts to vfirst (PR #175952)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 14 09:37:35 PST 2026
================
@@ -281,6 +286,100 @@ bool RISCVCodeGenPrepare::expandVPStrideLoad(IntrinsicInst &II) {
return true;
}
+// Convert vector.reduce.or + cttz.elts into riscv.vfirst.
+//
+// The RISC-V vfirst instruction natively provides the functionality of both
+// vector.reduce.or (checking if any element is set) and cttz.elts (finding
+// the first set element). This function matches the following pattern and
+// replaces it with a single vfirst intrinsic:
+//
+// Before:
+// block1:
+// %ffload = call {<vTy>, i32} @llvm.vp.load.ff(ptr, <mask>, i32)
+// %evl = extractvalue %ffload, 1
+// %alm = call @llvm.get.active.lane.mask(0, %evl)
+// %cond = ...
+// %select = select %alm, %cond, zeroinitializer
+// %reduce = call @llvm.vector.reduce.or(%select)
+// br i1 %reduce, label %early.exit, label %continue
+// early.exit:
+// %idx = call @llvm.experimental.cttz.elts(%cond)
+// ...
+//
+// After:
+// block1:
+// %vfirst = call @llvm.riscv.vfirst.mask(%cond, %mask, %evl)
+// %found = icmp sge %vfirst, 0
+// br i1 %found, label %early.exit, label %continue
+// early.exit:
+// ; uses of cttz.elts replaced with %vfirst
+// ...
+bool RISCVCodeGenPrepare::convertVFirstPattern(IntrinsicInst &II) {
+ using namespace PatternMatch;
+ Value *Select, *ALM, *Cond, *EVL, *FFLoad, *Mask;
+
+ // Match the reduce.or pattern with freeze, select, active lane mask,
+ // and vp.load.ff.
+ bool MatchReduceOr =
+ match(&II, m_Intrinsic<Intrinsic::vector_reduce_or>(
+ m_Freeze(m_Value(Select)))) &&
----------------
topperc wrote:
There's no `freeze` in the IR in the comment. Can you add it?
https://github.com/llvm/llvm-project/pull/175952
More information about the llvm-commits
mailing list