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