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} // End anonymous namespace
54
55char WebAssemblyOptimizeReturnedLegacy::ID = 0;
56INITIALIZE_PASS(WebAssemblyOptimizeReturnedLegacy, DEBUG_TYPE,
57 "Optimize calls with \"returned\" attributes for WebAssembly",
58 false, false)
59
60FunctionPass *llvm::createWebAssemblyOptimizeReturnedLegacyPass() {
61 return new WebAssemblyOptimizeReturnedLegacy();
62}
63
64void WebAssemblyOptimizeReturnedImpl::visitCallBase(CallBase &CB) {
65 for (unsigned I = 0, E = CB.arg_size(); I < E; ++I)
66 if (CB.paramHasAttr(ArgNo: I, Kind: Attribute::Returned)) {
67 Value *Arg = CB.getArgOperand(i: I);
68 // Ignore constants, globals, undef, etc.
69 if (isa<Constant>(Val: Arg))
70 continue;
71 // Like replaceDominatedUsesWith but using Instruction/Use dominance.
72 Arg->replaceUsesWithIf(New: &CB, ShouldReplace: [&](Use &U) {
73 auto *I = cast<Instruction>(Val: U.getUser());
74 return !I->isLifetimeStartOrEnd() && DT->dominates(Def: &CB, U);
75 });
76 }
77}
78
79bool WebAssemblyOptimizeReturnedImpl::runOnFunction(Function &F) {
80 LLVM_DEBUG(dbgs() << "********** Optimize returned Attributes **********\n"
81 "********** Function: "
82 << F.getName() << '\n');
83
84 visit(F);
85 return true;
86}
87
88bool WebAssemblyOptimizeReturnedLegacy::runOnFunction(Function &F) {
89 DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
90 WebAssemblyOptimizeReturnedImpl Impl(DT);
91 return Impl.runOnFunction(F);
92}
93
94PreservedAnalyses
95WebAssemblyOptimizeReturnedPass::run(Function &F,
96 FunctionAnalysisManager &FAM) {
97 DominatorTree *DT = &FAM.getResult<DominatorTreeAnalysis>(IR&: F);
98 WebAssemblyOptimizeReturnedImpl Impl(DT);
99 return Impl.runOnFunction(F)
100 ? PreservedAnalyses::none().preserveSet<CFGAnalyses>()
101 : PreservedAnalyses::all();
102}
103