1292915Sdim//===-- WebAssemblyOptimizeReturned.cpp - Optimize "returned" attributes --===//
2292915Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6292915Sdim//
7292915Sdim//===----------------------------------------------------------------------===//
8292915Sdim///
9292915Sdim/// \file
10341825Sdim/// Optimize calls with "returned" attributes for WebAssembly.
11292915Sdim///
12292915Sdim//===----------------------------------------------------------------------===//
13292915Sdim
14292915Sdim#include "WebAssembly.h"
15292915Sdim#include "llvm/IR/Dominators.h"
16292915Sdim#include "llvm/IR/InstVisitor.h"
17292915Sdim#include "llvm/Support/Debug.h"
18292915Sdim#include "llvm/Support/raw_ostream.h"
19292915Sdimusing namespace llvm;
20292915Sdim
21292915Sdim#define DEBUG_TYPE "wasm-optimize-returned"
22292915Sdim
23292915Sdimnamespace {
24292915Sdimclass OptimizeReturned final : public FunctionPass,
25292915Sdim                               public InstVisitor<OptimizeReturned> {
26314564Sdim  StringRef getPassName() const override {
27292915Sdim    return "WebAssembly Optimize Returned";
28292915Sdim  }
29292915Sdim
30292915Sdim  void getAnalysisUsage(AnalysisUsage &AU) const override {
31292915Sdim    AU.setPreservesCFG();
32292915Sdim    AU.addRequired<DominatorTreeWrapperPass>();
33292915Sdim    AU.addPreserved<DominatorTreeWrapperPass>();
34292915Sdim    FunctionPass::getAnalysisUsage(AU);
35292915Sdim  }
36292915Sdim
37292915Sdim  bool runOnFunction(Function &F) override;
38292915Sdim
39353358Sdim  DominatorTree *DT = nullptr;
40292915Sdim
41292915Sdimpublic:
42292915Sdim  static char ID;
43353358Sdim  OptimizeReturned() : FunctionPass(ID) {}
44292915Sdim
45292915Sdim  void visitCallSite(CallSite CS);
46292915Sdim};
47292915Sdim} // End anonymous namespace
48292915Sdim
49292915Sdimchar OptimizeReturned::ID = 0;
50341825SdimINITIALIZE_PASS(OptimizeReturned, DEBUG_TYPE,
51341825Sdim                "Optimize calls with \"returned\" attributes for WebAssembly",
52341825Sdim                false, false)
53341825Sdim
54292915SdimFunctionPass *llvm::createWebAssemblyOptimizeReturned() {
55292915Sdim  return new OptimizeReturned();
56292915Sdim}
57292915Sdim
58292915Sdimvoid OptimizeReturned::visitCallSite(CallSite CS) {
59353358Sdim  for (unsigned I = 0, E = CS.getNumArgOperands(); I < E; ++I)
60353358Sdim    if (CS.paramHasAttr(I, Attribute::Returned)) {
61292915Sdim      Instruction *Inst = CS.getInstruction();
62353358Sdim      Value *Arg = CS.getArgOperand(I);
63292915Sdim      // Ignore constants, globals, undef, etc.
64292915Sdim      if (isa<Constant>(Arg))
65292915Sdim        continue;
66292915Sdim      // Like replaceDominatedUsesWith but using Instruction/Use dominance.
67360784Sdim      Arg->replaceUsesWithIf(Inst,
68360784Sdim                             [&](Use &U) { return DT->dominates(Inst, U); });
69292915Sdim    }
70292915Sdim}
71292915Sdim
72292915Sdimbool OptimizeReturned::runOnFunction(Function &F) {
73344779Sdim  LLVM_DEBUG(dbgs() << "********** Optimize returned Attributes **********\n"
74344779Sdim                       "********** Function: "
75344779Sdim                    << F.getName() << '\n');
76344779Sdim
77292915Sdim  DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
78292915Sdim  visit(F);
79292915Sdim  return true;
80292915Sdim}
81