LLVM 24.0.0git
WebAssemblyReduceToAnyAllTrue.cpp
Go to the documentation of this file.
1#include "WebAssembly.h"
4#include "llvm/IR/Analysis.h"
5#include "llvm/IR/IRBuilder.h"
6#include "llvm/IR/IntrinsicsWebAssembly.h"
7#include "llvm/IR/Module.h"
10#include "llvm/Pass.h"
11
12using namespace llvm;
13using namespace llvm::PatternMatch;
14
15namespace {
16struct WebAssemblyReduceToAnyAllTrueLegacy final : FunctionPass {
17 static char ID;
18
19 WebAssemblyTargetMachine &TM;
20 Module *CachedModule = nullptr;
21 bool ModuleHasInterestingIntrinsics = false;
22
23 WebAssemblyReduceToAnyAllTrueLegacy(WebAssemblyTargetMachine &TM)
24 : FunctionPass(ID), TM(TM) {}
25
26 StringRef getPassName() const override {
27 return "WebAssembly convert reduce to any_true/all_true";
28 }
29
30 bool runOnFunction(Function &F) override;
31};
32} // end anonymous namespace
33
34char WebAssemblyReduceToAnyAllTrueLegacy::ID = 0;
35
36static bool hasInterestingIntrinsics(Module &M, Module *&CachedModule,
37 bool &ModuleHasInterestingIntrinsics) {
38 if (CachedModule == &M)
39 return ModuleHasInterestingIntrinsics;
40
41 CachedModule = &M;
42 ModuleHasInterestingIntrinsics = false;
43
44 for (const Function &Fn : M.functions()) {
45 switch (Fn.getIntrinsicID()) {
46 case Intrinsic::vector_reduce_or:
47 case Intrinsic::vector_reduce_and:
48 ModuleHasInterestingIntrinsics = true;
49 return true;
50 default:
51 break;
52 }
53 }
54
55 return false;
56}
57
59 Module *&CachedModule,
60 bool &ModuleHasInterestingIntrinsics) {
62 return false;
63
64 if (!hasInterestingIntrinsics(*F.getParent(), CachedModule,
65 ModuleHasInterestingIntrinsics))
66 return false;
67
68 bool Changed = false;
69
70 for (auto &BB : F) {
71 for (auto It = BB.begin(), E = BB.end(); It != E;) {
72 Instruction *I = &*It++;
73 auto *Cmp = dyn_cast<ICmpInst>(I);
74 if (!Cmp || Cmp->getPredicate() != ICmpInst::ICMP_NE)
75 continue;
76
77 Value *Reduce = nullptr;
78 if (!match(Cmp, m_ICmp(m_Value(Reduce), m_ZeroInt())))
79 continue;
80
81 auto *II = dyn_cast<IntrinsicInst>(Reduce);
82 if (!II || !II->hasOneUse())
83 continue;
84
85 IRBuilder<> B(Cmp);
86 Value *Vec = II->getArgOperand(0);
87 Module *M = F.getParent();
88
89 auto makeIntrinsic = [&](Intrinsic::ID ID, Value *Arg) {
90 Function *Fn =
91 Intrinsic::getOrInsertDeclaration(M, ID, {Arg->getType()});
92 return B.CreateCall(Fn, {Arg});
93 };
94
95 Value *New = nullptr;
96
97 switch (II->getIntrinsicID()) {
98 case Intrinsic::vector_reduce_or: {
99 // reduce.or(X) != 0 -> anytrue(X)
100 Value *Any = makeIntrinsic(Intrinsic::wasm_anytrue, Vec);
101 New = B.CreateICmpNE(Any, ConstantInt::get(Any->getType(), 0));
102 break;
103 }
104
105 case Intrinsic::vector_reduce_and: {
106 // reduce.and(zext (icmp ne X, zeroinitializer)) != 0 -> alltrue(X)
107
108 // Match: zext (icmp ne X, 0) from <N x i1> to <N x iX>
109 CmpPredicate Pred;
110 Value *LHS = nullptr;
111 if (!match(Vec, m_ZExt(m_c_ICmp(Pred, m_Value(LHS), m_Zero()))))
112 continue;
113 if (Pred != ICmpInst::ICMP_NE)
114 continue;
115
116 Value *All = makeIntrinsic(Intrinsic::wasm_alltrue, LHS);
117 New = B.CreateICmpNE(All, ConstantInt::get(All->getType(), 0));
118 break;
119 }
120
121 default:
122 continue;
123 }
124
125 Cmp->replaceAllUsesWith(New);
126 Cmp->eraseFromParent();
127
128 if (II->use_empty())
129 II->eraseFromParent();
130
131 Changed = true;
132 }
133 }
134
135 return Changed;
136}
137
138bool WebAssemblyReduceToAnyAllTrueLegacy::runOnFunction(Function &F) {
139 return reduceToAnyAllTrue(F, TM, CachedModule,
140 ModuleHasInterestingIntrinsics);
141}
142
143PreservedAnalyses
150
153 return new WebAssemblyReduceToAnyAllTrueLegacy(TM);
154}
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
static bool hasInterestingIntrinsics(Module &M, Module *&CachedModule, bool &ModuleHasInterestingIntrinsics)
static bool reduceToAnyAllTrue(Function &F, WebAssemblyTargetMachine &TM, Module *&CachedModule, bool &ModuleHasInterestingIntrinsics)
This file declares the WebAssembly-specific subclass of TargetSubtarget.
This file declares the WebAssembly-specific subclass of TargetMachine.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
Value * LHS
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
@ ICMP_NE
not equal
Definition InstrTypes.h:762
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2893
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
LLVM Value Representation.
Definition Value.h:75
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Changed
Pass manager infrastructure for declaring and invalidating analyses.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
bool match(Val *V, const Pattern &P)
CmpClass_match< LHS, RHS, ICmpInst, true > m_c_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
Matches an ICmp with a predicate over LHS and RHS in either order.
auto m_Value()
Match an arbitrary value and ignore it.
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
FunctionPass * createWebAssemblyReduceToAnyAllTrueLegacyPass(WebAssemblyTargetMachine &TM)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.