[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