1 //===-- WebAssemblyOptimizeReturned.cpp - Optimize "returned" attributes --===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// Optimize calls with "returned" attributes for WebAssembly.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "WebAssembly.h"
15 #include "llvm/IR/Dominators.h"
16 #include "llvm/IR/InstVisitor.h"
17 #include "llvm/Support/Debug.h"
18 #include "llvm/Support/raw_ostream.h"
19 using namespace llvm;
20 
21 #define DEBUG_TYPE "wasm-optimize-returned"
22 
23 namespace {
24 class OptimizeReturned final : public FunctionPass,
25                                public InstVisitor<OptimizeReturned> {
26   StringRef getPassName() const override {
27     return "WebAssembly Optimize Returned";
28   }
29 
30   void getAnalysisUsage(AnalysisUsage &AU) const override {
31     AU.setPreservesCFG();
32     AU.addRequired<DominatorTreeWrapperPass>();
33     AU.addPreserved<DominatorTreeWrapperPass>();
34     FunctionPass::getAnalysisUsage(AU);
35   }
36 
37   bool runOnFunction(Function &F) override;
38 
39   DominatorTree *DT = nullptr;
40 
41 public:
42   static char ID;
43   OptimizeReturned() : FunctionPass(ID) {}
44 
45   void visitCallSite(CallSite CS);
46 };
47 } // End anonymous namespace
48 
49 char OptimizeReturned::ID = 0;
50 INITIALIZE_PASS(OptimizeReturned, DEBUG_TYPE,
51                 "Optimize calls with \"returned\" attributes for WebAssembly",
52                 false, false)
53 
54 FunctionPass *llvm::createWebAssemblyOptimizeReturned() {
55   return new OptimizeReturned();
56 }
57 
58 void OptimizeReturned::visitCallSite(CallSite CS) {
59   for (unsigned I = 0, E = CS.getNumArgOperands(); I < E; ++I)
60     if (CS.paramHasAttr(I, Attribute::Returned)) {
61       Instruction *Inst = CS.getInstruction();
62       Value *Arg = CS.getArgOperand(I);
63       // Ignore constants, globals, undef, etc.
64       if (isa<Constant>(Arg))
65         continue;
66       // Like replaceDominatedUsesWith but using Instruction/Use dominance.
67       for (auto UI = Arg->use_begin(), UE = Arg->use_end(); UI != UE;) {
68         Use &U = *UI++;
69         if (DT->dominates(Inst, U))
70           U.set(Inst);
71       }
72     }
73 }
74 
75 bool OptimizeReturned::runOnFunction(Function &F) {
76   LLVM_DEBUG(dbgs() << "********** Optimize returned Attributes **********\n"
77                        "********** Function: "
78                     << F.getName() << '\n');
79 
80   DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
81   visit(F);
82   return true;
83 }
84