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/Analysis.h"
16#include "llvm/IR/Dominators.h"
17#include "llvm/IR/InstVisitor.h"
18#include "llvm/IR/PassManager.h"
19#include "llvm/Support/Debug.h"
20#include "llvm/Support/raw_ostream.h"
21using namespace llvm;
22
23#define DEBUG_TYPE "wasm-optimize-returned"
24
25namespace {
26class WebAssemblyOptimizeReturnedImpl
27 : public InstVisitor<WebAssemblyOptimizeReturnedImpl> {
28 DominatorTree *DT = nullptr;
29
30public:
31 WebAssemblyOptimizeReturnedImpl(DominatorTree *DT) : DT(DT) {}
32 bool runOnFunction(Function &F);
33 void visitCallBase(CallBase &CB);
34};
35
36class WebAssemblyOptimizeReturnedLegacy final : public FunctionPass {
37 StringRef getPassName() const override {
38 return "WebAssembly Optimize Returned";
39 }
40
41 void getAnalysisUsage(AnalysisUsage &AU) const override {
42 AU.setPreservesCFG();
43 AU.addRequired<DominatorTreeWrapperPass>();
44 FunctionPass::getAnalysisUsage(AU);
45 }
46
47 bool runOnFunction(Function &F) override;
48
49public:
50 static char ID;
51 WebAssemblyOptimizeReturnedLegacy() : FunctionPass(ID) {}
52
53 void visitCallBase(CallBase &CB);
54};
55} // End anonymous namespace
56
57char WebAssemblyOptimizeReturnedLegacy::ID = 0;
58INITIALIZE_PASS(WebAssemblyOptimizeReturnedLegacy, DEBUG_TYPE,
59 "Optimize calls with \"returned\" attributes for WebAssembly",
60 false, false)
61
62FunctionPass *llvm::createWebAssemblyOptimizeReturnedLegacyPass() {
63 return new WebAssemblyOptimizeReturnedLegacy();
64}
65
66void WebAssemblyOptimizeReturnedImpl::visitCallBase(CallBase &CB) {
67 for (unsigned I = 0, E = CB.arg_size(); I < E; ++I)
68 if (CB.paramHasAttr(ArgNo: I, Kind: Attribute::Returned)) {
69 Value *Arg = CB.getArgOperand(i: I);
70 // Ignore constants, globals, undef, etc.
71 if (isa<Constant>(Val: Arg))
72 continue;
73 // Like replaceDominatedUsesWith but using Instruction/Use dominance.
74 Arg->replaceUsesWithIf(New: &CB, ShouldReplace: [&](Use &U) {
75 auto *I = cast<Instruction>(Val: U.getUser());
76 return !I->isLifetimeStartOrEnd() && DT->dominates(Def: &CB, U);
77 });
78 }
79}
80
81bool WebAssemblyOptimizeReturnedImpl::runOnFunction(Function &F) {
82 LLVM_DEBUG(dbgs() << "********** Optimize returned Attributes **********\n"
83 "********** Function: "
84 << F.getName() << '\n');
85
86 visit(F);
87 return true;
88}
89
90bool WebAssemblyOptimizeReturnedLegacy::runOnFunction(Function &F) {
91 DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
92 WebAssemblyOptimizeReturnedImpl Impl(DT);
93 return Impl.runOnFunction(F);
94}
95
96PreservedAnalyses
97WebAssemblyOptimizeReturnedPass::run(Function &F,
98 FunctionAnalysisManager &FAM) {
99 DominatorTree *DT = &FAM.getResult<DominatorTreeAnalysis>(IR&: F);
100 WebAssemblyOptimizeReturnedImpl Impl(DT);
101 return Impl.runOnFunction(F)
102 ? PreservedAnalyses::none().preserveSet<CFGAnalyses>()
103 : PreservedAnalyses::all();
104}
105