[Mlir-commits] [mlir] [mlir][vector] Refine select uses on uniform reduction paths (PR #235640)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Sat Oct 31 03:44:26 PDT 2026


https://github.com/meinie0826 updated https://github.com/llvm/llvm-project/pull/235640

>From 2c7b87c5b00ea984d95feac3e4d542b8da8f5d19 Mon Sep 17 00:00:00 2001
From: meinie0826 <929449726 at qq.com>
Date: Mon, 26 Oct 2026 15:52:17 +0800
Subject: [PATCH 1/4] [mlir][vector] Refine select uses on uniform reduction
 paths

Use region-branch reachability to prove AND-true and OR-false mask uniformity at individual select uses, preserving opposite and loop-carried paths.
---
 mlir/include/mlir/Dialect/Vector/IR/Vector.td |   1 +
 mlir/lib/Dialect/Vector/IR/VectorOps.cpp      | 104 ++++
 mlir/test/Dialect/Vector/canonicalize.mlir    | 554 ++++++++++++++++++
 3 files changed, 659 insertions(+)

diff --git a/mlir/include/mlir/Dialect/Vector/IR/Vector.td b/mlir/include/mlir/Dialect/Vector/IR/Vector.td
index 5125ae7c13717..45ebb7e83d8d4 100644
--- a/mlir/include/mlir/Dialect/Vector/IR/Vector.td
+++ b/mlir/include/mlir/Dialect/Vector/IR/Vector.td
@@ -21,6 +21,7 @@ def Vector_Dialect : Dialect {
 
   let useDefaultAttributePrinterParser = 1;
   let hasConstantMaterializer = 1;
+  let hasCanonicalizer = 1;
   let dependentDialects = [
     "arith::ArithDialect",
     "ub::UBDialect"
diff --git a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp
index eedf483df2d31..872227cc0f9f3 100644
--- a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp
+++ b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp
@@ -37,6 +37,7 @@
 #include "mlir/IR/PatternMatch.h"
 #include "mlir/IR/TypeUtilities.h"
 #include "mlir/IR/ValueRange.h"
+#include "mlir/Interfaces/ControlFlowInterfaces.h"
 #include "mlir/Interfaces/SubsetOpInterface.h"
 #include "mlir/Interfaces/ValueBoundsOpInterface.h"
 #include "mlir/Support/LLVM.h"
@@ -44,6 +45,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Repeated.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/SmallVectorExtras.h"
 #include "llvm/ADT/StringSet.h"
@@ -8692,6 +8694,108 @@ DeinterleaveOp::getIterationShapeToUnroll() {
   return llvm::to_vector<4>(getResultVectorType().getShape());
 }
 
+//===----------------------------------------------------------------------===//
+// VectorDialect canonicalization
+//===----------------------------------------------------------------------===//
+
+namespace {
+/// Conservatively compute the regions reachable from an operation entry.
+/// Region-to-region edges are included: an entry-only check is insufficient for
+/// loops and operations that enter one region through another.
+static bool isRegionReachable(RegionBranchOpInterface branch, Region *target,
+                              ArrayRef<Attribute> operands) {
+  SmallVector<RegionSuccessor> successors;
+  branch.getEntrySuccessorRegions(operands, successors);
+  SmallVector<Region *> worklist;
+  llvm::SmallPtrSet<Region *, 4> visited;
+  auto append = [&] {
+    for (RegionSuccessor successor : successors)
+      if (Region *region = successor.getSuccessor())
+        if (region->getParentOp() == branch.getOperation() &&
+            visited.insert(region).second)
+          worklist.push_back(region);
+  };
+  append();
+  while (!worklist.empty()) {
+    Region *region = worklist.pop_back_val();
+    if (region == target)
+      return true;
+    successors.clear();
+    branch.getSuccessorRegions(*region, successors);
+    append();
+  }
+  return false;
+}
+
+/// Infer a reduction's value only when the opposite value cannot reach the use.
+struct SelectReductionBranch : OpRewritePattern<arith::SelectOp> {
+  using OpRewritePattern::OpRewritePattern;
+  LogicalResult matchAndRewrite(arith::SelectOp select,
+                                PatternRewriter &rewriter) const override {
+    if (!isa<VectorType>(select.getCondition().getType()))
+      return failure();
+    DenseMap<Region *, Value> replacements;
+    bool changed = false;
+    for (OpOperand &use :
+         llvm::make_early_inc_range(select.getResult().getUses())) {
+      for (Operation *child = use.getOwner();
+           auto *parent = child->getParentOp(); child = parent) {
+        auto branch = dyn_cast<RegionBranchOpInterface>(parent);
+        if (!branch)
+          continue;
+        Region *useRegion = child->getParentRegion();
+        if (!replacements.contains(useRegion)) {
+          replacements[useRegion] = Value();
+          for (Value operand : parent->getOperands()) {
+            auto reduction = operand.getDefiningOp<ReductionOp>();
+            if (!reduction ||
+                !reduction.getDest().getType().isSignlessInteger(1) ||
+                reduction.getAcc() || reduction.isMasked() ||
+                reduction.getVector() != select.getCondition())
+              continue;
+            bool value;
+            if (reduction.getKind() == CombiningKind::AND)
+              value = true;
+            else if (reduction.getKind() == CombiningKind::OR)
+              value = false;
+            else
+              continue;
+            SmallVector<Attribute> knownOperands(parent->getNumOperands());
+            // Every occurrence of this SSA value must have the same constant.
+            for (auto [i, v] : llvm::enumerate(parent->getOperands()))
+              if (v == operand)
+                knownOperands[i] = rewriter.getBoolAttr(!value);
+            if (isRegionReachable(branch, useRegion, knownOperands))
+              continue;
+            for (auto [i, v] : llvm::enumerate(parent->getOperands()))
+              if (v == operand)
+                knownOperands[i] = rewriter.getBoolAttr(value);
+            if (!isRegionReachable(branch, useRegion, knownOperands))
+              continue;
+            Value replacement =
+                value ? select.getTrueValue() : select.getFalseValue();
+            replacements[useRegion] = replacement;
+            break;
+          }
+        }
+        if (Value replacement = replacements.lookup(useRegion)) {
+          rewriter.modifyOpInPlace(use.getOwner(),
+                                   [&] { use.set(replacement); });
+          changed = true;
+          break;
+        }
+      }
+    }
+    return success(changed);
+  }
+};
+} // namespace
+
+void VectorDialect::getCanonicalizationPatterns(
+    RewritePatternSet &results) const {
+  results.add<SelectReductionBranch>(getContext());
+}
+
 //===----------------------------------------------------------------------===//
 // TableGen'd op method definitions
 //===----------------------------------------------------------------------===//
diff --git a/mlir/test/Dialect/Vector/canonicalize.mlir b/mlir/test/Dialect/Vector/canonicalize.mlir
index 4eb3988c417ec..32b7094ecb6f7 100644
--- a/mlir/test/Dialect/Vector/canonicalize.mlir
+++ b/mlir/test/Dialect/Vector/canonicalize.mlir
@@ -4677,3 +4677,557 @@ func.func @interleave_splat() -> vector<[4]xf32> {
   %0 = vector.interleave %cst, %cst : vector<[2]xf32> -> vector<[4]xf32>
   return %0 : vector<[4]xf32>
 }
+
+// -----
+
+// Reduction predicates refine select uses only on paths that require a
+// uniform mask. Opposite branches and outside uses retain elementwise selects.
+// CHECK-LABEL: func.func @and_acc(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: scf.if
+// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: } else {
+// CHECK: %[[ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[ELSE]])
+// CHECK: return %{{.*}} : vector<4xi32>
+func.func @and_acc(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.reduction <and>, %m, %acc : vector<4xi1> into i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %r {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  } else {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @and_changed_loop_mask(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: scf.for
+// CHECK: %[[X:.*]] = arith.select %{{.*}}, %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[X]])
+// CHECK: return %{{.*}} : vector<4xi32>
+func.func @and_changed_loop_mask(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.reduction <and>, %m : vector<4xi1> into i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  %c0 = arith.constant 0 : index
+  %c1 = arith.constant 1 : index
+  scf.if %r {
+    %result = scf.for %i = %c0 to %n step %c1 iter_args(%iter = %m) -> (vector<4xi1>) {
+      %x = arith.select %iter, %a, %b : vector<4xi1>, vector<4xi32>
+      func.call @consume(%x) : (vector<4xi32>) -> ()
+      scf.yield %other : vector<4xi1>
+    }
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @and_execute(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[R:.*]] = vector.reduction <and>, %[[M]]
+// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: scf.if %[[R]]
+// CHECK: func.call @consume(%[[A]])
+// CHECK: } else {
+// CHECK: func.call @consume(%{{.*}})
+func.func @and_execute(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>) {
+  %r = vector.reduction <and>, %m : vector<4xi1> into i1
+  %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %r {
+    scf.execute_region {
+      func.call @consume(%x) : (vector<4xi32>) -> ()
+      scf.yield
+    }
+  } else {
+    scf.execute_region {
+      func.call @consume(%x) : (vector<4xi32>) -> ()
+      scf.yield
+    }
+  }
+  return
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @and_freeze(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: scf.if
+// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: } else {
+// CHECK: %[[ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[ELSE]])
+// CHECK: return %{{.*}} : vector<4xi32>
+func.func @and_freeze(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.reduction <and>, %m : vector<4xi1> into i1
+  %f = "llvm.freeze"(%r) : (i1) -> i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %f {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  } else {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @and_inside(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[R:.*]] = vector.reduction <and>, %[[M]]
+// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: scf.if %[[R]]
+// CHECK: func.call @consume(%[[A]])
+// CHECK: } else {
+// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: return %[[X]] : vector<4xi32>
+func.func @and_inside(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.reduction <and>, %m : vector<4xi1> into i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %r {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  } else {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @and_loop(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[R:.*]] = vector.reduction <and>, %[[M]]
+// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: scf.if %[[R]]
+// CHECK: func.call @consume(%[[A]])
+// CHECK: } else {
+// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: return %[[X]] : vector<4xi32>
+func.func @and_loop(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.reduction <and>, %m : vector<4xi1> into i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %r {
+    %c0 = arith.constant 0 : index
+    %c1 = arith.constant 1 : index
+    scf.for %i = %c0 to %n step %c1 {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+    }
+  } else {
+    %c0 = arith.constant 0 : index
+    %c1 = arith.constant 1 : index
+    scf.for %i = %c0 to %n step %c1 {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+    }
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @and_masked(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: scf.if
+// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: } else {
+// CHECK: %[[ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[ELSE]])
+// CHECK: return %{{.*}} : vector<4xi32>
+func.func @and_masked(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.mask %other { vector.reduction <and>, %m : vector<4xi1> into i1 } : vector<4xi1> -> i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %r {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  } else {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @and_nested(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[R:.*]] = vector.reduction <and>, %[[M]]
+// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: scf.if %[[R]]
+// CHECK: func.call @consume(%[[A]])
+// CHECK: } else {
+// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: return %[[X]] : vector<4xi32>
+func.func @and_nested(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.reduction <and>, %m : vector<4xi1> into i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %r {
+    scf.if %acc {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+    }
+  } else {
+    scf.if %acc {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+    }
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @and_other_mask(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[X:.*]] = arith.select %[[OTHER]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[X]])
+// CHECK: func.call @consume(%[[X]])
+// CHECK: return %{{.*}} : vector<4xi32>
+func.func @and_other_mask(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.reduction <and>, %m : vector<4xi1> into i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %r {
+    %x = arith.select %other, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  } else {
+    %x = arith.select %other, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @and_outside(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[R:.*]] = vector.reduction <and>, %[[M]]
+// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: scf.if %[[R]]
+// CHECK: func.call @consume(%[[A]])
+// CHECK: } else {
+// CHECK: func.call @consume(%{{.*}})
+// CHECK: return %[[X]] : vector<4xi32>
+func.func @and_outside(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.reduction <and>, %m : vector<4xi1> into i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %r {
+    func.call @consume(%outside) : (vector<4xi32>) -> ()
+  } else {
+    func.call @consume(%outside) : (vector<4xi32>) -> ()
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @while_entry(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[X]])
+func.func @while_entry(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %next: i1) {
+  %r = vector.reduction <and>, %m : vector<4xi1> into i1
+  %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  %result = scf.while (%arg = %r) : (i1) -> i1 {
+    scf.condition(%arg) %arg : i1
+  } do {
+  ^bb0(%arg: i1):
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+    scf.yield %next : i1
+  }
+  return
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @or_acc(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: scf.if
+// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: } else {
+// CHECK: %[[ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[ELSE]])
+// CHECK: return %{{.*}} : vector<4xi32>
+func.func @or_acc(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.reduction <or>, %m, %acc : vector<4xi1> into i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %r {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  } else {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @or_changed_loop_mask(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: scf.for
+// CHECK: %[[X:.*]] = arith.select %{{.*}}, %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[X]])
+// CHECK: return %{{.*}} : vector<4xi32>
+func.func @or_changed_loop_mask(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.reduction <or>, %m : vector<4xi1> into i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  %c0 = arith.constant 0 : index
+  %c1 = arith.constant 1 : index
+  scf.if %r {
+    %result = scf.for %i = %c0 to %n step %c1 iter_args(%iter = %m) -> (vector<4xi1>) {
+      %x = arith.select %iter, %a, %b : vector<4xi1>, vector<4xi32>
+      func.call @consume(%x) : (vector<4xi32>) -> ()
+      scf.yield %other : vector<4xi1>
+    }
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @or_execute(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[R:.*]] = vector.reduction <or>, %[[M]]
+// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: scf.if %[[R]]
+// CHECK: func.call @consume(%{{.*}})
+// CHECK: } else {
+// CHECK: func.call @consume(%[[B]])
+func.func @or_execute(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>) {
+  %r = vector.reduction <or>, %m : vector<4xi1> into i1
+  %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %r {
+    scf.execute_region {
+      func.call @consume(%x) : (vector<4xi32>) -> ()
+      scf.yield
+    }
+  } else {
+    scf.execute_region {
+      func.call @consume(%x) : (vector<4xi32>) -> ()
+      scf.yield
+    }
+  }
+  return
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @or_freeze(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: scf.if
+// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: } else {
+// CHECK: %[[ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[ELSE]])
+// CHECK: return %{{.*}} : vector<4xi32>
+func.func @or_freeze(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.reduction <or>, %m : vector<4xi1> into i1
+  %f = "llvm.freeze"(%r) : (i1) -> i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %f {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  } else {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @or_inside(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[R:.*]] = vector.reduction <or>, %[[M]]
+// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: scf.if %[[R]]
+// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: } else {
+// CHECK: func.call @consume(%[[B]])
+// CHECK: return %[[X]] : vector<4xi32>
+func.func @or_inside(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.reduction <or>, %m : vector<4xi1> into i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %r {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  } else {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @or_loop(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[R:.*]] = vector.reduction <or>, %[[M]]
+// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: scf.if %[[R]]
+// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: } else {
+// CHECK: func.call @consume(%[[B]])
+// CHECK: return %[[X]] : vector<4xi32>
+func.func @or_loop(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.reduction <or>, %m : vector<4xi1> into i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %r {
+    %c0 = arith.constant 0 : index
+    %c1 = arith.constant 1 : index
+    scf.for %i = %c0 to %n step %c1 {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+    }
+  } else {
+    %c0 = arith.constant 0 : index
+    %c1 = arith.constant 1 : index
+    scf.for %i = %c0 to %n step %c1 {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+    }
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @or_masked(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: scf.if
+// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: } else {
+// CHECK: %[[ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[ELSE]])
+// CHECK: return %{{.*}} : vector<4xi32>
+func.func @or_masked(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.mask %other { vector.reduction <or>, %m : vector<4xi1> into i1 } : vector<4xi1> -> i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %r {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  } else {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @or_nested(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[R:.*]] = vector.reduction <or>, %[[M]]
+// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: scf.if %[[R]]
+// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: } else {
+// CHECK: func.call @consume(%[[B]])
+// CHECK: return %[[X]] : vector<4xi32>
+func.func @or_nested(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.reduction <or>, %m : vector<4xi1> into i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %r {
+    scf.if %acc {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+    }
+  } else {
+    scf.if %acc {
+    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+    }
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @or_other_mask(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[X:.*]] = arith.select %[[OTHER]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[X]])
+// CHECK: func.call @consume(%[[X]])
+// CHECK: return %{{.*}} : vector<4xi32>
+func.func @or_other_mask(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.reduction <or>, %m : vector<4xi1> into i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %r {
+    %x = arith.select %other, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  } else {
+    %x = arith.select %other, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)
+
+// -----
+
+// CHECK-LABEL: func.func @or_outside(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK: %[[R:.*]] = vector.reduction <or>, %[[M]]
+// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: scf.if %[[R]]
+// CHECK: func.call @consume(%{{.*}})
+// CHECK: } else {
+// CHECK: func.call @consume(%[[B]])
+// CHECK: return %[[X]] : vector<4xi32>
+func.func @or_outside(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
+  %r = vector.reduction <or>, %m : vector<4xi1> into i1
+  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  scf.if %r {
+    func.call @consume(%outside) : (vector<4xi32>) -> ()
+  } else {
+    func.call @consume(%outside) : (vector<4xi32>) -> ()
+  }
+  return %outside : vector<4xi32>
+}
+func.func private @consume(vector<4xi32>)

>From f778545376b97cb87c250e0de5b8f6a9087cc177 Mon Sep 17 00:00:00 2001
From: meinie0826 <929449726 at qq.com>
Date: Mon, 26 Oct 2026 16:44:38 +0800
Subject: [PATCH 2/4] [mlir][vector] Use try_emplace for region replacement
 cache

---
 mlir/lib/Dialect/Vector/IR/VectorOps.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp
index 872227cc0f9f3..86676c3a7d496 100644
--- a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp
+++ b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp
@@ -8744,8 +8744,8 @@ struct SelectReductionBranch : OpRewritePattern<arith::SelectOp> {
         if (!branch)
           continue;
         Region *useRegion = child->getParentRegion();
-        if (!replacements.contains(useRegion)) {
-          replacements[useRegion] = Value();
+        auto [it, inserted] = replacements.try_emplace(useRegion);
+        if (inserted) {
           for (Value operand : parent->getOperands()) {
             auto reduction = operand.getDefiningOp<ReductionOp>();
             if (!reduction ||
@@ -8774,11 +8774,11 @@ struct SelectReductionBranch : OpRewritePattern<arith::SelectOp> {
               continue;
             Value replacement =
                 value ? select.getTrueValue() : select.getFalseValue();
-            replacements[useRegion] = replacement;
+            it->second = replacement;
             break;
           }
         }
-        if (Value replacement = replacements.lookup(useRegion)) {
+        if (Value replacement = it->second) {
           rewriter.modifyOpInPlace(use.getOwner(),
                                    [&] { use.set(replacement); });
           changed = true;

>From 3a73d0e8ff84f4ae36307823fb036ef7821c9788 Mon Sep 17 00:00:00 2001
From: meinie0826 <929449726 at qq.com>
Date: Fri, 30 Oct 2026 10:34:44 +0800
Subject: [PATCH 3/4] Consolidate uniform reduction select tests

---
 mlir/test/Dialect/Vector/canonicalize.mlir | 704 ++++++++-------------
 1 file changed, 277 insertions(+), 427 deletions(-)

diff --git a/mlir/test/Dialect/Vector/canonicalize.mlir b/mlir/test/Dialect/Vector/canonicalize.mlir
index 025d604ddd142..d073302da842c 100644
--- a/mlir/test/Dialect/Vector/canonicalize.mlir
+++ b/mlir/test/Dialect/Vector/canonicalize.mlir
@@ -4790,356 +4790,194 @@ func.func @select_uniform_unselected_poison_vector(%p: i1, %a: vector<4xi32>) ->
 
 // -----
 
-// Reduction predicates refine select uses only on paths that require a
-// uniform mask. Opposite branches and outside uses retain elementwise selects.
-// CHECK-LABEL: func.func @and_acc(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: scf.if
-// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[LOCAL]])
-// CHECK: } else {
-// CHECK: %[[ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[ELSE]])
-// CHECK: return %{{.*}} : vector<4xi32>
-func.func @and_acc(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.reduction <and>, %m, %acc : vector<4xi1> into i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %r {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
-  } else {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
-  }
-  return %outside : vector<4xi32>
-}
-func.func private @consume(vector<4xi32>)
-
-// -----
-
-// CHECK-LABEL: func.func @and_changed_loop_mask(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: scf.for
-// CHECK: %[[X:.*]] = arith.select %{{.*}}, %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[X]])
-// CHECK: return %{{.*}} : vector<4xi32>
-func.func @and_changed_loop_mask(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.reduction <and>, %m : vector<4xi1> into i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  %c0 = arith.constant 0 : index
-  %c1 = arith.constant 1 : index
-  scf.if %r {
-    %result = scf.for %i = %c0 to %n step %c1 iter_args(%iter = %m) -> (vector<4xi1>) {
-      %x = arith.select %iter, %a, %b : vector<4xi1>, vector<4xi32>
-      func.call @consume(%x) : (vector<4xi32>) -> ()
-      scf.yield %other : vector<4xi1>
-    }
-  }
-  return %outside : vector<4xi32>
-}
-func.func private @consume(vector<4xi32>)
-
-// -----
-
-// CHECK-LABEL: func.func @and_execute(
+// Reduction predicates refine only the uniform path; mixed masks and outside
+// uses retain the elementwise select.
+// CHECK-LABEL: func.func @select_reduction_paths(
 // CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: %[[R:.*]] = vector.reduction <and>, %[[M]]
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: scf.if %[[R]]
+// CHECK: %[[Y:.*]] = arith.select %{{.*}}, %[[A]], %[[B]]
+// CHECK: scf.if
 // CHECK: func.call @consume(%[[A]])
+// CHECK-NEXT: func.call @consume(%[[A]])
+// CHECK-NEXT: func.call @consume(%[[Y]])
 // CHECK: } else {
-// CHECK: func.call @consume(%{{.*}})
-func.func @and_execute(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>) {
-  %r = vector.reduction <and>, %m : vector<4xi1> into i1
-  %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %r {
-    scf.execute_region {
-      func.call @consume(%x) : (vector<4xi32>) -> ()
-      scf.yield
-    }
-  } else {
-    scf.execute_region {
-      func.call @consume(%x) : (vector<4xi32>) -> ()
-      scf.yield
-    }
-  }
-  return
-}
-func.func private @consume(vector<4xi32>)
-
-// -----
-
-// CHECK-LABEL: func.func @and_freeze(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: %[[LOCAL_AND_ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_AND_ELSE]])
+// CHECK-NEXT: func.call @consume(%[[X]])
+// CHECK-NEXT: func.call @consume(%[[Y]])
 // CHECK: scf.if
-// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: %[[LOCAL_OR_THEN:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_OR_THEN]])
+// CHECK-NEXT: func.call @consume(%[[X]])
+// CHECK-NEXT: func.call @consume(%[[Y]])
 // CHECK: } else {
-// CHECK: %[[ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[ELSE]])
-// CHECK: return %{{.*}} : vector<4xi32>
-func.func @and_freeze(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.reduction <and>, %m : vector<4xi1> into i1
-  %f = "llvm.freeze"(%r) : (i1) -> i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %f {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+// CHECK: func.call @consume(%[[B]])
+// CHECK-NEXT: func.call @consume(%[[B]])
+// CHECK-NEXT: func.call @consume(%[[Y]])
+// CHECK: return %[[X]] : vector<4xi32>
+func.func @select_reduction_paths(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %other: vector<4xi1>) -> vector<4xi32> {
+  %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  %y = arith.select %other, %a, %b : vector<4xi1>, vector<4xi32>
+  %and = vector.reduction <and>, %m : vector<4xi1> into i1
+  scf.if %and {
+    %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%local) : (vector<4xi32>) -> ()
     func.call @consume(%x) : (vector<4xi32>) -> ()
+    func.call @consume(%y) : (vector<4xi32>) -> ()
   } else {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%local) : (vector<4xi32>) -> ()
     func.call @consume(%x) : (vector<4xi32>) -> ()
+    func.call @consume(%y) : (vector<4xi32>) -> ()
   }
-  return %outside : vector<4xi32>
-}
-func.func private @consume(vector<4xi32>)
-
-// -----
-
-// CHECK-LABEL: func.func @and_inside(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: %[[R:.*]] = vector.reduction <and>, %[[M]]
-// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: scf.if %[[R]]
-// CHECK: func.call @consume(%[[A]])
-// CHECK: } else {
-// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[LOCAL]])
-// CHECK: return %[[X]] : vector<4xi32>
-func.func @and_inside(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.reduction <and>, %m : vector<4xi1> into i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %r {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  %or = vector.reduction <or>, %m : vector<4xi1> into i1
+  scf.if %or {
+    %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%local) : (vector<4xi32>) -> ()
     func.call @consume(%x) : (vector<4xi32>) -> ()
+    func.call @consume(%y) : (vector<4xi32>) -> ()
   } else {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%local) : (vector<4xi32>) -> ()
     func.call @consume(%x) : (vector<4xi32>) -> ()
+    func.call @consume(%y) : (vector<4xi32>) -> ()
   }
-  return %outside : vector<4xi32>
+  return %x : vector<4xi32>
 }
 func.func private @consume(vector<4xi32>)
 
 // -----
 
-// CHECK-LABEL: func.func @and_loop(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: %[[R:.*]] = vector.reduction <and>, %[[M]]
+// CHECK-LABEL: func.func @select_reduction_loop(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: scf.if %[[R]]
+// CHECK: scf.if
+// CHECK: scf.for
 // CHECK: func.call @consume(%[[A]])
 // CHECK: } else {
-// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: scf.for
+// CHECK: %[[LOCAL_AND_ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_AND_ELSE]])
+// CHECK: scf.if
+// CHECK: scf.for
+// CHECK: %[[LOCAL_OR_THEN:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_OR_THEN]])
+// CHECK: } else {
+// CHECK: scf.for
+// CHECK: func.call @consume(%[[B]])
 // CHECK: return %[[X]] : vector<4xi32>
-func.func @and_loop(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.reduction <and>, %m : vector<4xi1> into i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %r {
-    %c0 = arith.constant 0 : index
-    %c1 = arith.constant 1 : index
+func.func @select_reduction_loop(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %n: index) -> vector<4xi32> {
+  %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  %c0 = arith.constant 0 : index
+  %c1 = arith.constant 1 : index
+  %and = vector.reduction <and>, %m : vector<4xi1> into i1
+  scf.if %and {
     scf.for %i = %c0 to %n step %c1 {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
+      %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+      func.call @consume(%local) : (vector<4xi32>) -> ()
     }
   } else {
-    %c0 = arith.constant 0 : index
-    %c1 = arith.constant 1 : index
     scf.for %i = %c0 to %n step %c1 {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
+      %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+      func.call @consume(%local) : (vector<4xi32>) -> ()
     }
   }
-  return %outside : vector<4xi32>
-}
-func.func private @consume(vector<4xi32>)
-
-// -----
-
-// CHECK-LABEL: func.func @and_masked(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: scf.if
-// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[LOCAL]])
-// CHECK: } else {
-// CHECK: %[[ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[ELSE]])
-// CHECK: return %{{.*}} : vector<4xi32>
-func.func @and_masked(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.mask %other { vector.reduction <and>, %m : vector<4xi1> into i1 } : vector<4xi1> -> i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %r {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
+  %or = vector.reduction <or>, %m : vector<4xi1> into i1
+  scf.if %or {
+    scf.for %i = %c0 to %n step %c1 {
+      %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+      func.call @consume(%local) : (vector<4xi32>) -> ()
+    }
   } else {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
+    scf.for %i = %c0 to %n step %c1 {
+      %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+      func.call @consume(%local) : (vector<4xi32>) -> ()
+    }
   }
-  return %outside : vector<4xi32>
+  return %x : vector<4xi32>
 }
 func.func private @consume(vector<4xi32>)
 
 // -----
 
-// CHECK-LABEL: func.func @and_nested(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: %[[R:.*]] = vector.reduction <and>, %[[M]]
+// CHECK-LABEL: func.func @select_reduction_nested(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: scf.if %[[R]]
+// CHECK: scf.if
+// CHECK: scf.if
 // CHECK: func.call @consume(%[[A]])
 // CHECK: } else {
-// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: scf.if
+// CHECK: %[[LOCAL_AND_ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_AND_ELSE]])
+// CHECK: scf.if
+// CHECK: scf.if
+// CHECK: %[[LOCAL_OR_THEN:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_OR_THEN]])
+// CHECK: } else {
+// CHECK: scf.if
+// CHECK: func.call @consume(%[[B]])
 // CHECK: return %[[X]] : vector<4xi32>
-func.func @and_nested(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.reduction <and>, %m : vector<4xi1> into i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %r {
-    scf.if %acc {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
+func.func @select_reduction_nested(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %p: i1) -> vector<4xi32> {
+  %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  %and = vector.reduction <and>, %m : vector<4xi1> into i1
+  scf.if %and {
+    scf.if %p {
+      %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+      func.call @consume(%local) : (vector<4xi32>) -> ()
     }
   } else {
-    scf.if %acc {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
+    scf.if %p {
+      %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+      func.call @consume(%local) : (vector<4xi32>) -> ()
     }
   }
-  return %outside : vector<4xi32>
-}
-func.func private @consume(vector<4xi32>)
-
-// -----
-
-// CHECK-LABEL: func.func @and_other_mask(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: %[[X:.*]] = arith.select %[[OTHER]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[X]])
-// CHECK: func.call @consume(%[[X]])
-// CHECK: return %{{.*}} : vector<4xi32>
-func.func @and_other_mask(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.reduction <and>, %m : vector<4xi1> into i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %r {
-    %x = arith.select %other, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
+  %or = vector.reduction <or>, %m : vector<4xi1> into i1
+  scf.if %or {
+    scf.if %p {
+      %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+      func.call @consume(%local) : (vector<4xi32>) -> ()
+    }
   } else {
-    %x = arith.select %other, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
+    scf.if %p {
+      %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+      func.call @consume(%local) : (vector<4xi32>) -> ()
+    }
   }
-  return %outside : vector<4xi32>
+  return %x : vector<4xi32>
 }
 func.func private @consume(vector<4xi32>)
 
 // -----
 
-// CHECK-LABEL: func.func @and_outside(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: %[[R:.*]] = vector.reduction <and>, %[[M]]
+// CHECK-LABEL: func.func @select_reduction_execute(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: scf.if %[[R]]
+// CHECK: scf.if
 // CHECK: func.call @consume(%[[A]])
 // CHECK: } else {
-// CHECK: func.call @consume(%{{.*}})
-// CHECK: return %[[X]] : vector<4xi32>
-func.func @and_outside(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.reduction <and>, %m : vector<4xi1> into i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %r {
-    func.call @consume(%outside) : (vector<4xi32>) -> ()
-  } else {
-    func.call @consume(%outside) : (vector<4xi32>) -> ()
-  }
-  return %outside : vector<4xi32>
-}
-func.func private @consume(vector<4xi32>)
-
-// -----
-
-// CHECK-LABEL: func.func @while_entry(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
 // CHECK: func.call @consume(%[[X]])
-func.func @while_entry(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %next: i1) {
-  %r = vector.reduction <and>, %m : vector<4xi1> into i1
-  %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  %result = scf.while (%arg = %r) : (i1) -> i1 {
-    scf.condition(%arg) %arg : i1
-  } do {
-  ^bb0(%arg: i1):
-    func.call @consume(%x) : (vector<4xi32>) -> ()
-    scf.yield %next : i1
-  }
-  return
-}
-func.func private @consume(vector<4xi32>)
-
-// -----
-
-// CHECK-LABEL: func.func @or_acc(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
 // CHECK: scf.if
-// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: func.call @consume(%[[X]])
 // CHECK: } else {
-// CHECK: %[[ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[ELSE]])
-// CHECK: return %{{.*}} : vector<4xi32>
-func.func @or_acc(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.reduction <or>, %m, %acc : vector<4xi1> into i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %r {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
+// CHECK: func.call @consume(%[[B]])
+// CHECK: return %[[X]] : vector<4xi32>
+func.func @select_reduction_execute(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>) -> vector<4xi32> {
+  %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  %and = vector.reduction <and>, %m : vector<4xi1> into i1
+  scf.if %and {
+    scf.execute_region {
+      func.call @consume(%x) : (vector<4xi32>) -> ()
+      scf.yield
+    }
   } else {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
-  }
-  return %outside : vector<4xi32>
-}
-func.func private @consume(vector<4xi32>)
-
-// -----
-
-// CHECK-LABEL: func.func @or_changed_loop_mask(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: scf.for
-// CHECK: %[[X:.*]] = arith.select %{{.*}}, %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[X]])
-// CHECK: return %{{.*}} : vector<4xi32>
-func.func @or_changed_loop_mask(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.reduction <or>, %m : vector<4xi1> into i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  %c0 = arith.constant 0 : index
-  %c1 = arith.constant 1 : index
-  scf.if %r {
-    %result = scf.for %i = %c0 to %n step %c1 iter_args(%iter = %m) -> (vector<4xi1>) {
-      %x = arith.select %iter, %a, %b : vector<4xi1>, vector<4xi32>
+    scf.execute_region {
       func.call @consume(%x) : (vector<4xi32>) -> ()
-      scf.yield %other : vector<4xi1>
+      scf.yield
     }
   }
-  return %outside : vector<4xi32>
-}
-func.func private @consume(vector<4xi32>)
-
-// -----
-
-// CHECK-LABEL: func.func @or_execute(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: %[[R:.*]] = vector.reduction <or>, %[[M]]
-// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: scf.if %[[R]]
-// CHECK: func.call @consume(%{{.*}})
-// CHECK: } else {
-// CHECK: func.call @consume(%[[B]])
-func.func @or_execute(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>) {
-  %r = vector.reduction <or>, %m : vector<4xi1> into i1
-  %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %r {
+  %or = vector.reduction <or>, %m : vector<4xi1> into i1
+  scf.if %or {
     scf.execute_region {
       func.call @consume(%x) : (vector<4xi32>) -> ()
       scf.yield
@@ -5150,194 +4988,206 @@ func.func @or_execute(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>) {
       scf.yield
     }
   }
-  return
+  return %x : vector<4xi32>
 }
 func.func private @consume(vector<4xi32>)
 
 // -----
 
-// CHECK-LABEL: func.func @or_freeze(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK-LABEL: func.func @select_reduction_changed_loop_mask(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
 // CHECK: scf.if
-// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: scf.for
+// CHECK: %[[ITER_AND_THEN:.*]] = arith.select %{{.*}}, %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[ITER_AND_THEN]])
 // CHECK: } else {
-// CHECK: %[[ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[ELSE]])
-// CHECK: return %{{.*}} : vector<4xi32>
-func.func @or_freeze(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.reduction <or>, %m : vector<4xi1> into i1
-  %f = "llvm.freeze"(%r) : (i1) -> i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %f {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
-  } else {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
-  }
-  return %outside : vector<4xi32>
-}
-func.func private @consume(vector<4xi32>)
-
-// -----
-
-// CHECK-LABEL: func.func @or_inside(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: %[[R:.*]] = vector.reduction <or>, %[[M]]
-// CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: scf.if %[[R]]
-// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: scf.for
+// CHECK: %[[ITER_AND_ELSE:.*]] = arith.select %{{.*}}, %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[ITER_AND_ELSE]])
+// CHECK: scf.if
+// CHECK: scf.for
+// CHECK: %[[ITER_OR_THEN:.*]] = arith.select %{{.*}}, %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[ITER_OR_THEN]])
 // CHECK: } else {
-// CHECK: func.call @consume(%[[B]])
+// CHECK: scf.for
+// CHECK: %[[ITER_OR_ELSE:.*]] = arith.select %{{.*}}, %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[ITER_OR_ELSE]])
 // CHECK: return %[[X]] : vector<4xi32>
-func.func @or_inside(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.reduction <or>, %m : vector<4xi1> into i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %r {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
+func.func @select_reduction_changed_loop_mask(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %other: vector<4xi1>, %n: index) -> vector<4xi32> {
+  %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  %c0 = arith.constant 0 : index
+  %c1 = arith.constant 1 : index
+  %and = vector.reduction <and>, %m : vector<4xi1> into i1
+  scf.if %and {
+    %result_then_and = scf.for %i = %c0 to %n step %c1 iter_args(%iter = %m) -> (vector<4xi1>) {
+      %local = arith.select %iter, %a, %b : vector<4xi1>, vector<4xi32>
+      func.call @consume(%local) : (vector<4xi32>) -> ()
+      scf.yield %other : vector<4xi1>
+    }
   } else {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
+    %result_else_and = scf.for %i = %c0 to %n step %c1 iter_args(%iter = %m) -> (vector<4xi1>) {
+      %local = arith.select %iter, %a, %b : vector<4xi1>, vector<4xi32>
+      func.call @consume(%local) : (vector<4xi32>) -> ()
+      scf.yield %other : vector<4xi1>
+    }
   }
-  return %outside : vector<4xi32>
+  %or = vector.reduction <or>, %m : vector<4xi1> into i1
+  scf.if %or {
+    %result_then_or = scf.for %i = %c0 to %n step %c1 iter_args(%iter = %m) -> (vector<4xi1>) {
+      %local = arith.select %iter, %a, %b : vector<4xi1>, vector<4xi32>
+      func.call @consume(%local) : (vector<4xi32>) -> ()
+      scf.yield %other : vector<4xi1>
+    }
+  } else {
+    %result_else_or = scf.for %i = %c0 to %n step %c1 iter_args(%iter = %m) -> (vector<4xi1>) {
+      %local = arith.select %iter, %a, %b : vector<4xi1>, vector<4xi32>
+      func.call @consume(%local) : (vector<4xi32>) -> ()
+      scf.yield %other : vector<4xi1>
+    }
+  }
+  return %x : vector<4xi32>
 }
 func.func private @consume(vector<4xi32>)
 
 // -----
 
-// CHECK-LABEL: func.func @or_loop(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: %[[R:.*]] = vector.reduction <or>, %[[M]]
+// CHECK-LABEL: func.func @select_reduction_accumulator(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: scf.if %[[R]]
-// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: scf.if
+// CHECK: %[[LOCAL_AND_THEN:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_AND_THEN]])
 // CHECK: } else {
-// CHECK: func.call @consume(%[[B]])
+// CHECK: %[[LOCAL_AND_ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_AND_ELSE]])
+// CHECK: scf.if
+// CHECK: %[[LOCAL_OR_THEN:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_OR_THEN]])
+// CHECK: } else {
+// CHECK: %[[LOCAL_OR_ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_OR_ELSE]])
 // CHECK: return %[[X]] : vector<4xi32>
-func.func @or_loop(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.reduction <or>, %m : vector<4xi1> into i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %r {
-    %c0 = arith.constant 0 : index
-    %c1 = arith.constant 1 : index
-    scf.for %i = %c0 to %n step %c1 {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
-    }
+func.func @select_reduction_accumulator(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1) -> vector<4xi32> {
+  %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  %and = vector.reduction <and>, %m, %acc : vector<4xi1> into i1
+  scf.if %and {
+    %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%local) : (vector<4xi32>) -> ()
   } else {
-    %c0 = arith.constant 0 : index
-    %c1 = arith.constant 1 : index
-    scf.for %i = %c0 to %n step %c1 {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
-    }
+    %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%local) : (vector<4xi32>) -> ()
+  }
+  %or = vector.reduction <or>, %m, %acc : vector<4xi1> into i1
+  scf.if %or {
+    %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%local) : (vector<4xi32>) -> ()
+  } else {
+    %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%local) : (vector<4xi32>) -> ()
   }
-  return %outside : vector<4xi32>
+  return %x : vector<4xi32>
 }
 func.func private @consume(vector<4xi32>)
 
 // -----
 
-// CHECK-LABEL: func.func @or_masked(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
+// CHECK-LABEL: func.func @select_reduction_masked(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
 // CHECK: scf.if
-// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: %[[LOCAL_AND_THEN:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_AND_THEN]])
 // CHECK: } else {
-// CHECK: %[[ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[ELSE]])
-// CHECK: return %{{.*}} : vector<4xi32>
-func.func @or_masked(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.mask %other { vector.reduction <or>, %m : vector<4xi1> into i1 } : vector<4xi1> -> i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %r {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
+// CHECK: %[[LOCAL_AND_ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_AND_ELSE]])
+// CHECK: scf.if
+// CHECK: %[[LOCAL_OR_THEN:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_OR_THEN]])
+// CHECK: } else {
+// CHECK: %[[LOCAL_OR_ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_OR_ELSE]])
+// CHECK: return %[[X]] : vector<4xi32>
+func.func @select_reduction_masked(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %other: vector<4xi1>) -> vector<4xi32> {
+  %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  %and = vector.mask %other { vector.reduction <and>, %m : vector<4xi1> into i1 } : vector<4xi1> -> i1
+  scf.if %and {
+    %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%local) : (vector<4xi32>) -> ()
   } else {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
+    %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%local) : (vector<4xi32>) -> ()
+  }
+  %or = vector.mask %other { vector.reduction <or>, %m : vector<4xi1> into i1 } : vector<4xi1> -> i1
+  scf.if %or {
+    %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%local) : (vector<4xi32>) -> ()
+  } else {
+    %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%local) : (vector<4xi32>) -> ()
   }
-  return %outside : vector<4xi32>
+  return %x : vector<4xi32>
 }
 func.func private @consume(vector<4xi32>)
 
 // -----
 
-// CHECK-LABEL: func.func @or_nested(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: %[[R:.*]] = vector.reduction <or>, %[[M]]
+// CHECK-LABEL: func.func @select_reduction_freeze(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: scf.if %[[R]]
-// CHECK: %[[LOCAL:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[LOCAL]])
+// CHECK: scf.if
+// CHECK: %[[LOCAL_AND_THEN:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_AND_THEN]])
 // CHECK: } else {
-// CHECK: func.call @consume(%[[B]])
+// CHECK: %[[LOCAL_AND_ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_AND_ELSE]])
+// CHECK: scf.if
+// CHECK: %[[LOCAL_OR_THEN:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_OR_THEN]])
+// CHECK: } else {
+// CHECK: %[[LOCAL_OR_ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
+// CHECK: func.call @consume(%[[LOCAL_OR_ELSE]])
 // CHECK: return %[[X]] : vector<4xi32>
-func.func @or_nested(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.reduction <or>, %m : vector<4xi1> into i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %r {
-    scf.if %acc {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
-    }
+func.func @select_reduction_freeze(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>) -> vector<4xi32> {
+  %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  %and = vector.reduction <and>, %m : vector<4xi1> into i1
+  %f_and = "llvm.freeze"(%and) : (i1) -> i1
+  scf.if %f_and {
+    %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%local) : (vector<4xi32>) -> ()
   } else {
-    scf.if %acc {
-    %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
-    }
+    %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%local) : (vector<4xi32>) -> ()
   }
-  return %outside : vector<4xi32>
-}
-func.func private @consume(vector<4xi32>)
-
-// -----
-
-// CHECK-LABEL: func.func @or_other_mask(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: %[[X:.*]] = arith.select %[[OTHER]], %[[A]], %[[B]]
-// CHECK: func.call @consume(%[[X]])
-// CHECK: func.call @consume(%[[X]])
-// CHECK: return %{{.*}} : vector<4xi32>
-func.func @or_other_mask(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.reduction <or>, %m : vector<4xi1> into i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %r {
-    %x = arith.select %other, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
+  %or = vector.reduction <or>, %m : vector<4xi1> into i1
+  %f_or = "llvm.freeze"(%or) : (i1) -> i1
+  scf.if %f_or {
+    %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%local) : (vector<4xi32>) -> ()
   } else {
-    %x = arith.select %other, %a, %b : vector<4xi1>, vector<4xi32>
-    func.call @consume(%x) : (vector<4xi32>) -> ()
+    %local = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+    func.call @consume(%local) : (vector<4xi32>) -> ()
   }
-  return %outside : vector<4xi32>
+  return %x : vector<4xi32>
 }
 func.func private @consume(vector<4xi32>)
 
 // -----
 
-// CHECK-LABEL: func.func @or_outside(
-// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[OTHER:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
-// CHECK: %[[R:.*]] = vector.reduction <or>, %[[M]]
+// CHECK-LABEL: func.func @while_entry(
+// CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
-// CHECK: scf.if %[[R]]
-// CHECK: func.call @consume(%{{.*}})
-// CHECK: } else {
-// CHECK: func.call @consume(%[[B]])
-// CHECK: return %[[X]] : vector<4xi32>
-func.func @or_outside(%m: vector<4xi1>, %other: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1, %n: index) -> vector<4xi32> {
-  %r = vector.reduction <or>, %m : vector<4xi1> into i1
-  %outside = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
-  scf.if %r {
-    func.call @consume(%outside) : (vector<4xi32>) -> ()
-  } else {
-    func.call @consume(%outside) : (vector<4xi32>) -> ()
+// CHECK: func.call @consume(%[[X]])
+func.func @while_entry(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %next: i1) {
+  %r = vector.reduction <and>, %m : vector<4xi1> into i1
+  %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
+  %result = scf.while (%arg = %r) : (i1) -> i1 {
+    scf.condition(%arg) %arg : i1
+  } do {
+  ^bb0(%arg: i1):
+    func.call @consume(%x) : (vector<4xi32>) -> ()
+    scf.yield %next : i1
   }
-  return %outside : vector<4xi32>
+  return
 }
 func.func private @consume(vector<4xi32>)

>From cd1ae83a520feeb0c8bda48a4cdb4149c817dae0 Mon Sep 17 00:00:00 2001
From: meinie0826 <929449726 at qq.com>
Date: Sat, 31 Oct 2026 18:44:13 +0800
Subject: [PATCH 4/4] Name reduction select tests by scenario and rejection
 reason

---
 mlir/test/Dialect/Vector/canonicalize.mlir | 36 +++++++++++-----------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/mlir/test/Dialect/Vector/canonicalize.mlir b/mlir/test/Dialect/Vector/canonicalize.mlir
index d073302da842c..1d5ca524c742d 100644
--- a/mlir/test/Dialect/Vector/canonicalize.mlir
+++ b/mlir/test/Dialect/Vector/canonicalize.mlir
@@ -4792,7 +4792,7 @@ func.func @select_uniform_unselected_poison_vector(%p: i1, %a: vector<4xi32>) ->
 
 // Reduction predicates refine only the uniform path; mixed masks and outside
 // uses retain the elementwise select.
-// CHECK-LABEL: func.func @select_reduction_paths(
+// CHECK-LABEL: func.func @select_reduction_uniform_paths(
 // CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
 // CHECK: %[[Y:.*]] = arith.select %{{.*}}, %[[A]], %[[B]]
@@ -4815,7 +4815,7 @@ func.func @select_uniform_unselected_poison_vector(%p: i1, %a: vector<4xi32>) ->
 // CHECK-NEXT: func.call @consume(%[[B]])
 // CHECK-NEXT: func.call @consume(%[[Y]])
 // CHECK: return %[[X]] : vector<4xi32>
-func.func @select_reduction_paths(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %other: vector<4xi1>) -> vector<4xi32> {
+func.func @select_reduction_uniform_paths(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %other: vector<4xi1>) -> vector<4xi32> {
   %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
   %y = arith.select %other, %a, %b : vector<4xi1>, vector<4xi32>
   %and = vector.reduction <and>, %m : vector<4xi1> into i1
@@ -4848,7 +4848,7 @@ func.func private @consume(vector<4xi32>)
 
 // -----
 
-// CHECK-LABEL: func.func @select_reduction_loop(
+// CHECK-LABEL: func.func @select_reduction_in_loop(
 // CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
 // CHECK: scf.if
@@ -4866,7 +4866,7 @@ func.func private @consume(vector<4xi32>)
 // CHECK: scf.for
 // CHECK: func.call @consume(%[[B]])
 // CHECK: return %[[X]] : vector<4xi32>
-func.func @select_reduction_loop(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %n: index) -> vector<4xi32> {
+func.func @select_reduction_in_loop(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %n: index) -> vector<4xi32> {
   %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
   %c0 = arith.constant 0 : index
   %c1 = arith.constant 1 : index
@@ -4900,7 +4900,7 @@ func.func private @consume(vector<4xi32>)
 
 // -----
 
-// CHECK-LABEL: func.func @select_reduction_nested(
+// CHECK-LABEL: func.func @select_reduction_in_nested_if(
 // CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
 // CHECK: scf.if
@@ -4918,7 +4918,7 @@ func.func private @consume(vector<4xi32>)
 // CHECK: scf.if
 // CHECK: func.call @consume(%[[B]])
 // CHECK: return %[[X]] : vector<4xi32>
-func.func @select_reduction_nested(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %p: i1) -> vector<4xi32> {
+func.func @select_reduction_in_nested_if(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %p: i1) -> vector<4xi32> {
   %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
   %and = vector.reduction <and>, %m : vector<4xi1> into i1
   scf.if %and {
@@ -4950,7 +4950,7 @@ func.func private @consume(vector<4xi32>)
 
 // -----
 
-// CHECK-LABEL: func.func @select_reduction_execute(
+// CHECK-LABEL: func.func @select_reduction_in_execute_region(
 // CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
 // CHECK: scf.if
@@ -4962,7 +4962,7 @@ func.func private @consume(vector<4xi32>)
 // CHECK: } else {
 // CHECK: func.call @consume(%[[B]])
 // CHECK: return %[[X]] : vector<4xi32>
-func.func @select_reduction_execute(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>) -> vector<4xi32> {
+func.func @select_reduction_in_execute_region(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>) -> vector<4xi32> {
   %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
   %and = vector.reduction <and>, %m : vector<4xi1> into i1
   scf.if %and {
@@ -4994,7 +4994,7 @@ func.func private @consume(vector<4xi32>)
 
 // -----
 
-// CHECK-LABEL: func.func @select_reduction_changed_loop_mask(
+// CHECK-LABEL: func.func @negative_select_reduction_changed_loop_mask(
 // CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
 // CHECK: scf.if
@@ -5014,7 +5014,7 @@ func.func private @consume(vector<4xi32>)
 // CHECK: %[[ITER_OR_ELSE:.*]] = arith.select %{{.*}}, %[[A]], %[[B]]
 // CHECK: func.call @consume(%[[ITER_OR_ELSE]])
 // CHECK: return %[[X]] : vector<4xi32>
-func.func @select_reduction_changed_loop_mask(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %other: vector<4xi1>, %n: index) -> vector<4xi32> {
+func.func @negative_select_reduction_changed_loop_mask(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %other: vector<4xi1>, %n: index) -> vector<4xi32> {
   %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
   %c0 = arith.constant 0 : index
   %c1 = arith.constant 1 : index
@@ -5052,7 +5052,7 @@ func.func private @consume(vector<4xi32>)
 
 // -----
 
-// CHECK-LABEL: func.func @select_reduction_accumulator(
+// CHECK-LABEL: func.func @negative_select_reduction_with_accumulator(
 // CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
 // CHECK: scf.if
@@ -5068,7 +5068,7 @@ func.func private @consume(vector<4xi32>)
 // CHECK: %[[LOCAL_OR_ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
 // CHECK: func.call @consume(%[[LOCAL_OR_ELSE]])
 // CHECK: return %[[X]] : vector<4xi32>
-func.func @select_reduction_accumulator(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1) -> vector<4xi32> {
+func.func @negative_select_reduction_with_accumulator(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %acc: i1) -> vector<4xi32> {
   %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
   %and = vector.reduction <and>, %m, %acc : vector<4xi1> into i1
   scf.if %and {
@@ -5092,7 +5092,7 @@ func.func private @consume(vector<4xi32>)
 
 // -----
 
-// CHECK-LABEL: func.func @select_reduction_masked(
+// CHECK-LABEL: func.func @negative_select_reduction_masked_reduction(
 // CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
 // CHECK: scf.if
@@ -5108,7 +5108,7 @@ func.func private @consume(vector<4xi32>)
 // CHECK: %[[LOCAL_OR_ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
 // CHECK: func.call @consume(%[[LOCAL_OR_ELSE]])
 // CHECK: return %[[X]] : vector<4xi32>
-func.func @select_reduction_masked(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %other: vector<4xi1>) -> vector<4xi32> {
+func.func @negative_select_reduction_masked_reduction(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %other: vector<4xi1>) -> vector<4xi32> {
   %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
   %and = vector.mask %other { vector.reduction <and>, %m : vector<4xi1> into i1 } : vector<4xi1> -> i1
   scf.if %and {
@@ -5132,7 +5132,7 @@ func.func private @consume(vector<4xi32>)
 
 // -----
 
-// CHECK-LABEL: func.func @select_reduction_freeze(
+// CHECK-LABEL: func.func @negative_select_reduction_frozen_predicate(
 // CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
 // CHECK: scf.if
@@ -5148,7 +5148,7 @@ func.func private @consume(vector<4xi32>)
 // CHECK: %[[LOCAL_OR_ELSE:.*]] = arith.select %[[M]], %[[A]], %[[B]]
 // CHECK: func.call @consume(%[[LOCAL_OR_ELSE]])
 // CHECK: return %[[X]] : vector<4xi32>
-func.func @select_reduction_freeze(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>) -> vector<4xi32> {
+func.func @negative_select_reduction_frozen_predicate(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>) -> vector<4xi32> {
   %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
   %and = vector.reduction <and>, %m : vector<4xi1> into i1
   %f_and = "llvm.freeze"(%and) : (i1) -> i1
@@ -5174,11 +5174,11 @@ func.func private @consume(vector<4xi32>)
 
 // -----
 
-// CHECK-LABEL: func.func @while_entry(
+// CHECK-LABEL: func.func @negative_select_reduction_while_backedge(
 // CHECK-SAME: %[[M:[^:]+]]: vector<4xi1>, %[[A:[^:]+]]: vector<4xi32>, %[[B:[^:]+]]: vector<4xi32>
 // CHECK: %[[X:.*]] = arith.select %[[M]], %[[A]], %[[B]]
 // CHECK: func.call @consume(%[[X]])
-func.func @while_entry(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %next: i1) {
+func.func @negative_select_reduction_while_backedge(%m: vector<4xi1>, %a: vector<4xi32>, %b: vector<4xi32>, %next: i1) {
   %r = vector.reduction <and>, %m : vector<4xi1> into i1
   %x = arith.select %m, %a, %b : vector<4xi1>, vector<4xi32>
   %result = scf.while (%arg = %r) : (i1) -> i1 {



More information about the Mlir-commits mailing list