llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-backend-webassembly Author: Aiden Grossman (boomanaiden154) <details> <summary>Changes</summary> 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. --- Full diff: https://github.com/llvm/llvm-project/pull/209043.diff 5 Files Affected: - (modified) llvm/lib/Target/WebAssembly/WebAssembly.h (+15-1) - (modified) llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp (+1) - (modified) llvm/lib/Target/WebAssembly/WebAssemblyPassRegistry.def (+1) - (modified) llvm/lib/Target/WebAssembly/WebAssemblyReduceToAnyAllTrue.cpp (+109-88) - (modified) llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp (+2-1) ``````````diff 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 d867623f173cb..43990276561e0 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp @@ -113,6 +113,7 @@ void WebAssemblyCodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) const { // 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(); } `````````` </details> https://github.com/llvm/llvm-project/pull/209043 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
