[llvm] 044f8a1 - [WebAssembly] Port WebAssemblyReduceToAnyAllTruePass
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 15 06:59:07 PDT 2026
Author: Aiden Grossman
Date: 2026-07-15T06:59:02-07:00
New Revision: 044f8a1f151f935d2e718faa5b1d7cb8e8f52bec
URL: https://github.com/llvm/llvm-project/commit/044f8a1f151f935d2e718faa5b1d7cb8e8f52bec
DIFF: https://github.com/llvm/llvm-project/commit/044f8a1f151f935d2e718faa5b1d7cb8e8f52bec.diff
LOG: [WebAssembly] Port WebAssemblyReduceToAnyAllTruePass
Standard NewPM pass porting. Made a little bit annoying by the module
caching that I'm not sure helps much, but I've left it in.
Reviewers: aheejin, dschuff, sbc100
Pull Request: https://github.com/llvm/llvm-project/pull/209043
Added:
Modified:
llvm/lib/Target/WebAssembly/WebAssembly.h
llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
llvm/lib/Target/WebAssembly/WebAssemblyPassRegistry.def
llvm/lib/Target/WebAssembly/WebAssemblyReduceToAnyAllTrue.cpp
llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/WebAssembly/WebAssembly.h b/llvm/lib/Target/WebAssembly/WebAssembly.h
index c5b978402bc50..bfc2107858165 100644
--- a/llvm/lib/Target/WebAssembly/WebAssembly.h
+++ b/llvm/lib/Target/WebAssembly/WebAssembly.h
@@ -63,7 +63,21 @@ class WebAssemblyOptimizeReturnedPass
FunctionPass *createWebAssemblyOptimizeReturnedLegacyPass();
FunctionPass *createWebAssemblyRefTypeMem2Local();
-FunctionPass *createWebAssemblyReduceToAnyAllTrue(WebAssemblyTargetMachine &TM);
+
+class WebAssemblyReduceToAnyAllTruePass
+ : public RequiredPassInfoMixin<WebAssemblyReduceToAnyAllTruePass> {
+private:
+ Module *CachedModule = nullptr;
+ bool ModuleHasInterestingIntrinsics = false;
+ WebAssemblyTargetMachine &TM;
+
+public:
+ WebAssemblyReduceToAnyAllTruePass(WebAssemblyTargetMachine &TM) : TM(TM) {}
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
+};
+
+FunctionPass *
+createWebAssemblyReduceToAnyAllTrueLegacyPass(WebAssemblyTargetMachine &TM);
// GlobalISel
InstructionSelector *
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
index 4fe3e2292346c..eab85273e812e 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
@@ -123,7 +123,7 @@ void WebAssemblyCodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) const {
addFunctionPass(IndirectBrExpandPass(TM), PMW);
// Try to expand `vecreduce_{and, or}` into `{any, all}_true`.
- // TODO(boomanaiden154): WebAssemblyReduceToAnyAllTrue
+ addFunctionPass(WebAssemblyReduceToAnyAllTruePass(TM), PMW);
Base::addIRPasses(PMW);
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyPassRegistry.def b/llvm/lib/Target/WebAssembly/WebAssemblyPassRegistry.def
index fb70a7f0e1321..a771512786b6e 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyPassRegistry.def
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyPassRegistry.def
@@ -23,6 +23,7 @@ MODULE_PASS("wasm-lower-em-ehsjlj", WebAssemblyLowerEmscriptenEHSjLjPass())
#define FUNCTION_PASS(NAME, CREATE_PASS)
#endif
FUNCTION_PASS("wasm-optimize-returned", WebAssemblyOptimizeReturnedPass())
+FUNCTION_PASS("wasm-reduce-to-any-all-true", WebAssemblyReduceToAnyAllTruePass(*this))
#undef FUNCTION_PASS
#ifndef MACHINE_FUNCTION_PASS
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyReduceToAnyAllTrue.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyReduceToAnyAllTrue.cpp
index 4240c8978fd6d..6b2358c1a2d00 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyReduceToAnyAllTrue.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyReduceToAnyAllTrue.cpp
@@ -1,9 +1,11 @@
#include "WebAssembly.h"
#include "WebAssemblySubtarget.h"
#include "WebAssemblyTargetMachine.h"
+#include "llvm/IR/Analysis.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/IntrinsicsWebAssembly.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Pass.h"
@@ -11,123 +13,142 @@ using namespace llvm;
using namespace llvm::PatternMatch;
namespace {
-struct WebAssemblyReduceToAnyAllTrue final : FunctionPass {
+struct WebAssemblyReduceToAnyAllTrueLegacy final : FunctionPass {
static char ID;
WebAssemblyTargetMachine &TM;
- const Module *CachedModule = nullptr;
+ Module *CachedModule = nullptr;
bool ModuleHasInterestingIntrinsics = false;
- WebAssemblyReduceToAnyAllTrue(WebAssemblyTargetMachine &TM)
+ WebAssemblyReduceToAnyAllTrueLegacy(WebAssemblyTargetMachine &TM)
: FunctionPass(ID), TM(TM) {}
StringRef getPassName() const override {
return "WebAssembly convert reduce to any_true/all_true";
}
- bool hasInterestingIntrinsics(const Module &M) {
- if (CachedModule == &M)
- return ModuleHasInterestingIntrinsics;
+ bool runOnFunction(Function &F) override;
+};
+} // end anonymous namespace
- CachedModule = &M;
- ModuleHasInterestingIntrinsics = false;
+char WebAssemblyReduceToAnyAllTrueLegacy::ID = 0;
- for (const Function &Fn : M.functions()) {
- switch (Fn.getIntrinsicID()) {
- case Intrinsic::vector_reduce_or:
- case Intrinsic::vector_reduce_and:
- ModuleHasInterestingIntrinsics = true;
- return true;
- default:
- break;
- }
+static bool hasInterestingIntrinsics(Module &M, Module *&CachedModule,
+ bool &ModuleHasInterestingIntrinsics) {
+ if (CachedModule == &M)
+ return ModuleHasInterestingIntrinsics;
+
+ CachedModule = &M;
+ ModuleHasInterestingIntrinsics = false;
+
+ for (const Function &Fn : M.functions()) {
+ switch (Fn.getIntrinsicID()) {
+ case Intrinsic::vector_reduce_or:
+ case Intrinsic::vector_reduce_and:
+ ModuleHasInterestingIntrinsics = true;
+ return true;
+ default:
+ break;
}
+ }
+
+ return false;
+}
+static bool reduceToAnyAllTrue(Function &F, WebAssemblyTargetMachine &TM,
+ Module *&CachedModule,
+ bool &ModuleHasInterestingIntrinsics) {
+ if (!TM.getSubtarget<WebAssemblySubtarget>(F).hasSIMD128())
return false;
- }
- bool runOnFunction(Function &F) override {
- if (!TM.getSubtarget<WebAssemblySubtarget>(F).hasSIMD128())
- return false;
+ if (!hasInterestingIntrinsics(*F.getParent(), CachedModule,
+ ModuleHasInterestingIntrinsics))
+ return false;
- if (!hasInterestingIntrinsics(*F.getParent()))
- return false;
+ bool Changed = false;
- bool Changed = false;
+ for (auto &BB : F) {
+ for (auto It = BB.begin(), E = BB.end(); It != E;) {
+ Instruction *I = &*It++;
+ auto *Cmp = dyn_cast<ICmpInst>(I);
+ if (!Cmp || Cmp->getPredicate() != ICmpInst::ICMP_NE)
+ continue;
- for (auto &BB : F) {
- for (auto It = BB.begin(), E = BB.end(); It != E;) {
- Instruction *I = &*It++;
- auto *Cmp = dyn_cast<ICmpInst>(I);
- if (!Cmp || Cmp->getPredicate() != ICmpInst::ICMP_NE)
- continue;
+ Value *Reduce = nullptr;
+ if (!match(Cmp, m_ICmp(m_Value(Reduce), m_ZeroInt())))
+ continue;
- Value *Reduce = nullptr;
- if (!match(Cmp, m_ICmp(m_Value(Reduce), m_ZeroInt())))
- continue;
+ auto *II = dyn_cast<IntrinsicInst>(Reduce);
+ if (!II || !II->hasOneUse())
+ continue;
- auto *II = dyn_cast<IntrinsicInst>(Reduce);
- if (!II || !II->hasOneUse())
- continue;
+ IRBuilder<> B(Cmp);
+ Value *Vec = II->getArgOperand(0);
+ Module *M = F.getParent();
- IRBuilder<> B(Cmp);
- Value *Vec = II->getArgOperand(0);
- Module *M = F.getParent();
-
- auto makeIntrinsic = [&](Intrinsic::ID ID, Value *Arg) {
- Function *Fn =
- Intrinsic::getOrInsertDeclaration(M, ID, {Arg->getType()});
- return B.CreateCall(Fn, {Arg});
- };
-
- Value *New = nullptr;
-
- switch (II->getIntrinsicID()) {
- case Intrinsic::vector_reduce_or: {
- // reduce.or(X) != 0 -> anytrue(X)
- Value *Any = makeIntrinsic(Intrinsic::wasm_anytrue, Vec);
- New = B.CreateICmpNE(Any, ConstantInt::get(Any->getType(), 0));
- break;
- }
-
- case Intrinsic::vector_reduce_and: {
- // reduce.and(zext (icmp ne X, zeroinitializer)) != 0 -> alltrue(X)
-
- // Match: zext (icmp ne X, 0) from <N x i1> to <N x iX>
- CmpPredicate Pred;
- Value *LHS = nullptr;
- if (!match(Vec, m_ZExt(m_c_ICmp(Pred, m_Value(LHS), m_Zero()))))
- continue;
- if (Pred != ICmpInst::ICMP_NE)
- continue;
-
- Value *All = makeIntrinsic(Intrinsic::wasm_alltrue, LHS);
- New = B.CreateICmpNE(All, ConstantInt::get(All->getType(), 0));
- break;
- }
-
- default:
- continue;
- }
+ auto makeIntrinsic = [&](Intrinsic::ID ID, Value *Arg) {
+ Function *Fn =
+ Intrinsic::getOrInsertDeclaration(M, ID, {Arg->getType()});
+ return B.CreateCall(Fn, {Arg});
+ };
+
+ Value *New = nullptr;
- Cmp->replaceAllUsesWith(New);
- Cmp->eraseFromParent();
+ switch (II->getIntrinsicID()) {
+ case Intrinsic::vector_reduce_or: {
+ // reduce.or(X) != 0 -> anytrue(X)
+ Value *Any = makeIntrinsic(Intrinsic::wasm_anytrue, Vec);
+ New = B.CreateICmpNE(Any, ConstantInt::get(Any->getType(), 0));
+ break;
+ }
- if (II->use_empty())
- II->eraseFromParent();
+ case Intrinsic::vector_reduce_and: {
+ // reduce.and(zext (icmp ne X, zeroinitializer)) != 0 -> alltrue(X)
- Changed = true;
+ // Match: zext (icmp ne X, 0) from <N x i1> to <N x iX>
+ CmpPredicate Pred;
+ Value *LHS = nullptr;
+ if (!match(Vec, m_ZExt(m_c_ICmp(Pred, m_Value(LHS), m_Zero()))))
+ continue;
+ if (Pred != ICmpInst::ICMP_NE)
+ continue;
+
+ Value *All = makeIntrinsic(Intrinsic::wasm_alltrue, LHS);
+ New = B.CreateICmpNE(All, ConstantInt::get(All->getType(), 0));
+ break;
}
- }
- return Changed;
+ default:
+ continue;
+ }
+
+ Cmp->replaceAllUsesWith(New);
+ Cmp->eraseFromParent();
+
+ if (II->use_empty())
+ II->eraseFromParent();
+
+ Changed = true;
+ }
}
-};
-} // end anonymous namespace
-char WebAssemblyReduceToAnyAllTrue::ID = 0;
+ return Changed;
+}
+
+bool WebAssemblyReduceToAnyAllTrueLegacy::runOnFunction(Function &F) {
+ return reduceToAnyAllTrue(F, TM, CachedModule,
+ ModuleHasInterestingIntrinsics);
+}
+
+PreservedAnalyses
+WebAssemblyReduceToAnyAllTruePass::run(Function &F,
+ FunctionAnalysisManager &FAM) {
+ return reduceToAnyAllTrue(F, TM, CachedModule, ModuleHasInterestingIntrinsics)
+ ? PreservedAnalyses::none().preserveSet<CFGAnalyses>()
+ : PreservedAnalyses::all();
+}
-FunctionPass *
-llvm::createWebAssemblyReduceToAnyAllTrue(WebAssemblyTargetMachine &TM) {
- return new WebAssemblyReduceToAnyAllTrue(TM);
+FunctionPass *llvm::createWebAssemblyReduceToAnyAllTrueLegacyPass(
+ WebAssemblyTargetMachine &TM) {
+ return new WebAssemblyReduceToAnyAllTrueLegacy(TM);
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index 1bdb8a5decbe6..ac292f5c665c1 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -524,7 +524,8 @@ void WebAssemblyPassConfig::addIRPasses() {
addPass(createIndirectBrExpandPass());
// Try to expand `vecreduce_{and, or}` into `{any, all}_true`.
- addPass(createWebAssemblyReduceToAnyAllTrue(getWebAssemblyTargetMachine()));
+ addPass(createWebAssemblyReduceToAnyAllTrueLegacyPass(
+ getWebAssemblyTargetMachine()));
TargetPassConfig::addIRPasses();
}
More information about the llvm-commits
mailing list