LLVM 23.0.0git
WebAssemblyReduceToAnyAllTrue.cpp
Go to the documentation of this file.
1#include "WebAssembly.h"
4#include "llvm/IR/IRBuilder.h"
5#include "llvm/IR/IntrinsicsWebAssembly.h"
6#include "llvm/IR/Module.h"
8#include "llvm/Pass.h"
9
10using namespace llvm;
11using namespace llvm::PatternMatch;
12
13namespace {
14struct WebAssemblyReduceToAnyAllTrue final : FunctionPass {
15 static char ID;
16
17 WebAssemblyTargetMachine &TM;
18 const Module *CachedModule = nullptr;
19 bool ModuleHasInterestingIntrinsics = false;
20
21 WebAssemblyReduceToAnyAllTrue(WebAssemblyTargetMachine &TM)
22 : FunctionPass(ID), TM(TM) {}
23
24 StringRef getPassName() const override {
25 return "WebAssembly convert reduce to any_true/all_true";
26 }
27
28 bool hasInterestingIntrinsics(const Module &M) {
29 if (CachedModule == &M)
30 return ModuleHasInterestingIntrinsics;
31
32 CachedModule = &M;
33 ModuleHasInterestingIntrinsics = false;
34
35 for (const Function &Fn : M.functions()) {
36 switch (Fn.getIntrinsicID()) {
37 case Intrinsic::vector_reduce_or:
38 case Intrinsic::vector_reduce_and:
39 ModuleHasInterestingIntrinsics = true;
40 return true;
41 default:
42 break;
43 }
44 }
45
46 return false;
47 }
48
49 bool runOnFunction(Function &F) override {
50 if (!TM.getSubtarget<WebAssemblySubtarget>(F).hasSIMD128())
51 return false;
52
53 if (!hasInterestingIntrinsics(*F.getParent()))
54 return false;
55
56 bool Changed = false;
57
58 for (auto &BB : F) {
59 for (auto It = BB.begin(), E = BB.end(); It != E;) {
60 Instruction *I = &*It++;
61 auto *Cmp = dyn_cast<ICmpInst>(I);
62 if (!Cmp || Cmp->getPredicate() != ICmpInst::ICMP_NE)
63 continue;
64
65 Value *Reduce = nullptr;
66 if (!match(Cmp, m_ICmp(m_Value(Reduce), m_ZeroInt())))
67 continue;
68
69 auto *II = dyn_cast<IntrinsicInst>(Reduce);
70 if (!II || !II->hasOneUse())
71 continue;
72
73 IRBuilder<> B(Cmp);
74 Value *Vec = II->getArgOperand(0);
75 Module *M = F.getParent();
76
77 auto makeIntrinsic = [&](Intrinsic::ID ID, Value *Arg) {
78 Function *Fn =
79 Intrinsic::getOrInsertDeclaration(M, ID, {Arg->getType()});
80 return B.CreateCall(Fn, {Arg});
81 };
82
83 Value *New = nullptr;
84
85 switch (II->getIntrinsicID()) {
86 case Intrinsic::vector_reduce_or: {
87 // reduce.or(X) != 0 -> anytrue(X)
88 Value *Any = makeIntrinsic(Intrinsic::wasm_anytrue, Vec);
89 New = B.CreateICmpNE(Any, ConstantInt::get(Any->getType(), 0));
90 break;
91 }
92
93 case Intrinsic::vector_reduce_and: {
94 // reduce.and(zext (icmp ne X, zeroinitializer)) != 0 -> alltrue(X)
95
96 // Match: zext (icmp ne X, 0) from <N x i1> to <N x iX>
97 CmpPredicate Pred;
98 Value *LHS = nullptr;
99 if (!match(Vec, m_ZExt(m_c_ICmp(Pred, m_Value(LHS), m_Zero()))))
100 continue;
101 if (Pred != ICmpInst::ICMP_NE)
102 continue;
103
104 Value *All = makeIntrinsic(Intrinsic::wasm_alltrue, LHS);
105 New = B.CreateICmpNE(All, ConstantInt::get(All->getType(), 0));
106 break;
107 }
108
109 default:
110 continue;
111 }
112
113 Cmp->replaceAllUsesWith(New);
114 Cmp->eraseFromParent();
115
116 if (II->use_empty())
117 II->eraseFromParent();
118
119 Changed = true;
120 }
121 }
122
123 return Changed;
124 }
125};
126} // end anonymous namespace
127
128char WebAssemblyReduceToAnyAllTrue::ID = 0;
129
132 return new WebAssemblyReduceToAnyAllTrue(TM);
133}
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.
#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
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
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
Changed
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
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.
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
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.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
FunctionPass * createWebAssemblyReduceToAnyAllTrue(WebAssemblyTargetMachine &TM)
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >