LLVM  14.0.0git
WebAssemblyMemIntrinsicResults.cpp
Go to the documentation of this file.
1 //== WebAssemblyMemIntrinsicResults.cpp - Optimize memory intrinsic results ==//
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 /// This file implements an optimization pass using memory intrinsic results.
11 ///
12 /// Calls to memory intrinsics (memcpy, memmove, memset) return the destination
13 /// address. They are in the form of
14 /// %dst_new = call @memcpy %dst, %src, %len
15 /// where %dst and %dst_new registers contain the same value.
16 ///
17 /// This is to enable an optimization wherein uses of the %dst register used in
18 /// the parameter can be replaced by uses of the %dst_new register used in the
19 /// result, making the %dst register more likely to be single-use, thus more
20 /// likely to be useful to register stackifying, and potentially also exposing
21 /// the call instruction itself to register stackifying. These both can reduce
22 /// local.get/local.set traffic.
23 ///
24 /// The LLVM intrinsics for these return void so they can't use the returned
25 /// attribute and consequently aren't handled by the OptimizeReturned pass.
26 ///
27 //===----------------------------------------------------------------------===//
28 
30 #include "WebAssembly.h"
32 #include "WebAssemblySubtarget.h"
38 #include "llvm/CodeGen/Passes.h"
39 #include "llvm/Support/Debug.h"
41 using namespace llvm;
42 
43 #define DEBUG_TYPE "wasm-mem-intrinsic-results"
44 
45 namespace {
46 class WebAssemblyMemIntrinsicResults final : public MachineFunctionPass {
47 public:
48  static char ID; // Pass identification, replacement for typeid
49  WebAssemblyMemIntrinsicResults() : MachineFunctionPass(ID) {}
50 
51  StringRef getPassName() const override {
52  return "WebAssembly Memory Intrinsic Results";
53  }
54 
55  void getAnalysisUsage(AnalysisUsage &AU) const override {
56  AU.setPreservesCFG();
66  }
67 
68  bool runOnMachineFunction(MachineFunction &MF) override;
69 
70 private:
71 };
72 } // end anonymous namespace
73 
75 INITIALIZE_PASS(WebAssemblyMemIntrinsicResults, DEBUG_TYPE,
76  "Optimize memory intrinsic result values for WebAssembly",
77  false, false)
78 
80  return new WebAssemblyMemIntrinsicResults();
81 }
82 
83 // Replace uses of FromReg with ToReg if they are dominated by MI.
85  unsigned FromReg, unsigned ToReg,
86  const MachineRegisterInfo &MRI,
88  LiveIntervals &LIS) {
89  bool Changed = false;
90 
91  LiveInterval *FromLI = &LIS.getInterval(FromReg);
92  LiveInterval *ToLI = &LIS.getInterval(ToReg);
93 
94  SlotIndex FromIdx = LIS.getInstructionIndex(MI).getRegSlot();
95  VNInfo *FromVNI = FromLI->getVNInfoAt(FromIdx);
96 
98 
99  for (auto I = MRI.use_nodbg_begin(FromReg), E = MRI.use_nodbg_end();
100  I != E;) {
101  MachineOperand &O = *I++;
102  MachineInstr *Where = O.getParent();
103 
104  // Check that MI dominates the instruction in the normal way.
105  if (&MI == Where || !MDT.dominates(&MI, Where))
106  continue;
107 
108  // If this use gets a different value, skip it.
109  SlotIndex WhereIdx = LIS.getInstructionIndex(*Where);
110  VNInfo *WhereVNI = FromLI->getVNInfoAt(WhereIdx);
111  if (WhereVNI && WhereVNI != FromVNI)
112  continue;
113 
114  // Make sure ToReg isn't clobbered before it gets there.
115  VNInfo *ToVNI = ToLI->getVNInfoAt(WhereIdx);
116  if (ToVNI && ToVNI != FromVNI)
117  continue;
118 
119  Changed = true;
120  LLVM_DEBUG(dbgs() << "Setting operand " << O << " in " << *Where << " from "
121  << MI << "\n");
122  O.setReg(ToReg);
123 
124  // If the store's def was previously dead, it is no longer.
125  if (!O.isUndef()) {
126  MI.getOperand(0).setIsDead(false);
127 
128  Indices.push_back(WhereIdx.getRegSlot());
129  }
130  }
131 
132  if (Changed) {
133  // Extend ToReg's liveness.
134  LIS.extendToIndices(*ToLI, Indices);
135 
136  // Shrink FromReg's liveness.
137  LIS.shrinkToUses(FromLI);
138 
139  // If we replaced all dominated uses, FromReg is now killed at MI.
140  if (!FromLI->liveAt(FromIdx.getDeadSlot()))
141  MI.addRegisterKilled(FromReg, MBB.getParent()
143  .getRegisterInfo());
144  }
145 
146  return Changed;
147 }
148 
150  const MachineRegisterInfo &MRI,
152  const WebAssemblyTargetLowering &TLI,
153  const TargetLibraryInfo &LibInfo) {
154  MachineOperand &Op1 = MI.getOperand(1);
155  if (!Op1.isSymbol())
156  return false;
157 
159  bool CallReturnsInput = Name == TLI.getLibcallName(RTLIB::MEMCPY) ||
160  Name == TLI.getLibcallName(RTLIB::MEMMOVE) ||
161  Name == TLI.getLibcallName(RTLIB::MEMSET);
162  if (!CallReturnsInput)
163  return false;
164 
165  LibFunc Func;
166  if (!LibInfo.getLibFunc(Name, Func))
167  return false;
168 
169  Register FromReg = MI.getOperand(2).getReg();
170  Register ToReg = MI.getOperand(0).getReg();
171  if (MRI.getRegClass(FromReg) != MRI.getRegClass(ToReg))
172  report_fatal_error("Memory Intrinsic results: call to builtin function "
173  "with wrong signature, from/to mismatch");
174  return replaceDominatedUses(MBB, MI, FromReg, ToReg, MRI, MDT, LIS);
175 }
176 
177 bool WebAssemblyMemIntrinsicResults::runOnMachineFunction(MachineFunction &MF) {
178  LLVM_DEBUG({
179  dbgs() << "********** Memory Intrinsic Results **********\n"
180  << "********** Function: " << MF.getName() << '\n';
181  });
182 
184  auto &MDT = getAnalysis<MachineDominatorTree>();
185  const WebAssemblyTargetLowering &TLI =
186  *MF.getSubtarget<WebAssemblySubtarget>().getTargetLowering();
187  const auto &LibInfo =
188  getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(MF.getFunction());
189  auto &LIS = getAnalysis<LiveIntervals>();
190  bool Changed = false;
191 
192  // We don't preserve SSA form.
193  MRI.leaveSSA();
194 
196  "MemIntrinsicResults expects liveness tracking");
197 
198  for (auto &MBB : MF) {
199  LLVM_DEBUG(dbgs() << "Basic Block: " << MBB.getName() << '\n');
200  for (auto &MI : MBB)
201  switch (MI.getOpcode()) {
202  default:
203  break;
204  case WebAssembly::CALL:
205  Changed |= optimizeCall(MBB, MI, MRI, MDT, LIS, TLI, LibInfo);
206  break;
207  }
208  }
209 
210  return Changed;
211 }
llvm::WebAssemblySubtarget::getRegisterInfo
const WebAssemblyRegisterInfo * getRegisterInfo() const override
Definition: WebAssemblySubtarget.h:80
DEBUG_TYPE
#define DEBUG_TYPE
Definition: WebAssemblyMemIntrinsicResults.cpp:43
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:103
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
WebAssembly.h
llvm::MachineRegisterInfo
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Definition: MachineRegisterInfo.h:52
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::MachineFunctionPass
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Definition: MachineFunctionPass.h:30
llvm::TargetLoweringBase::getLibcallName
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
Definition: TargetLowering.h:2859
llvm::MachineOperand::isSymbol
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
Definition: MachineOperand.h:341
llvm::AArch64ISD::CALL
@ CALL
Definition: AArch64ISelLowering.h:52
llvm::ARMISD::MEMCPY
@ MEMCPY
Definition: ARMISelLowering.h:309
llvm::MachineDominatorTree::dominates
bool dominates(const MachineDomTreeNode *A, const MachineDomTreeNode *B) const
Definition: MachineDominators.h:109
llvm::MachineFunctionPass::getAnalysisUsage
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Definition: MachineFunctionPass.cpp:102
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::LiveIntervals::getInstructionIndex
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
Definition: LiveIntervals.h:226
llvm::MachineRegisterInfo::use_nodbg_begin
use_nodbg_iterator use_nodbg_begin(Register RegNo) const
Definition: MachineRegisterInfo.h:518
MachineRegisterInfo.h
llvm::MachineRegisterInfo::tracksLiveness
bool tracksLiveness() const
tracksLiveness - Returns true when tracking register liveness accurately.
Definition: MachineRegisterInfo.h:197
llvm::WebAssemblyTargetLowering
Definition: WebAssemblyISelLowering.h:43
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::MachineFunction::getRegInfo
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Definition: MachineFunction.h:636
llvm::LiveRange::liveAt
bool liveAt(SlotIndex index) const
Definition: LiveInterval.h:393
llvm::MachineBlockFrequencyInfo
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
Definition: MachineBlockFrequencyInfo.h:33
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::LibFunc
LibFunc
Definition: TargetLibraryInfo.h:34
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
TargetLibraryInfo.h
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:49
llvm::TargetLibraryInfo::getLibFunc
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
Definition: TargetLibraryInfo.h:289
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
llvm::SlotIndex::getDeadSlot
SlotIndex getDeadSlot() const
Returns the dead def kill slot for the current instruction.
Definition: SlotIndexes.h:259
llvm::MachineRegisterInfo::use_nodbg_end
static use_nodbg_iterator use_nodbg_end()
Definition: MachineRegisterInfo.h:521
llvm::SlotIndexes
SlotIndexes pass.
Definition: SlotIndexes.h:314
llvm::LiveInterval
LiveInterval - This class represents the liveness of a register, or stack slot.
Definition: LiveInterval.h:680
llvm::SlotIndex
SlotIndex - An opaque wrapper around machine indexes.
Definition: SlotIndexes.h:83
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:95
WebAssemblyMCTargetDesc.h
replaceDominatedUses
static bool replaceDominatedUses(MachineBasicBlock &MBB, MachineInstr &MI, unsigned FromReg, unsigned ToReg, const MachineRegisterInfo &MRI, MachineDominatorTree &MDT, LiveIntervals &LIS)
Definition: WebAssemblyMemIntrinsicResults.cpp:84
llvm::MachineRegisterInfo::getRegClass
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
Definition: MachineRegisterInfo.h:634
Passes.h
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:626
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:192
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:64
optimizeCall
static bool optimizeCall(MachineBasicBlock &MBB, MachineInstr &MI, const MachineRegisterInfo &MRI, MachineDominatorTree &MDT, LiveIntervals &LIS, const WebAssemblyTargetLowering &TLI, const TargetLibraryInfo &LibInfo)
Definition: WebAssemblyMemIntrinsicResults.cpp:149
llvm::TargetLibraryInfoWrapperPass
Definition: TargetLibraryInfo.h:463
LiveIntervals.h
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::createWebAssemblyMemIntrinsicResults
FunctionPass * createWebAssemblyMemIntrinsicResults()
llvm::MachineFunction::getName
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Definition: MachineFunction.cpp:541
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::MachineBasicBlock::getParent
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
Definition: MachineBasicBlock.h:225
llvm::LiveIntervals::shrinkToUses
bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr * > *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses.
Definition: LiveIntervals.cpp:456
WebAssemblyMachineFunctionInfo.h
llvm::SlotIndex::getRegSlot
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
Definition: SlotIndexes.h:254
llvm::LiveIntervals::getInterval
LiveInterval & getInterval(Register Reg)
Definition: LiveIntervals.h:114
llvm::MachineFunction
Definition: MachineFunction.h:230
llvm::AnalysisUsage::setPreservesCFG
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:253
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::AnalysisUsage::addPreserved
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Definition: PassAnalysisSupport.h:98
llvm::WebAssemblySubtarget
Definition: WebAssemblySubtarget.h:35
INITIALIZE_PASS
INITIALIZE_PASS(WebAssemblyMemIntrinsicResults, DEBUG_TYPE, "Optimize memory intrinsic result values for WebAssembly", false, false) FunctionPass *llvm
Definition: WebAssemblyMemIntrinsicResults.cpp:75
MRI
unsigned const MachineRegisterInfo * MRI
Definition: AArch64AdvSIMDScalarPass.cpp:105
llvm::Register
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
llvm::MachineFunction::getFunction
Function & getFunction()
Return the LLVM function that this machine code represents.
Definition: MachineFunction.h:592
llvm::LiveIntervals::extendToIndices
void extendToIndices(LiveRange &LR, ArrayRef< SlotIndex > Indices, ArrayRef< SlotIndex > Undefs)
Extend the live range LR to reach all points in Indices.
Definition: LiveIntervals.cpp:633
WebAssemblySubtarget.h
llvm::TargetLibraryInfo
Provides information about what library functions are available for the current target.
Definition: TargetLibraryInfo.h:219
llvm::LiveIntervals
Definition: LiveIntervals.h:54
llvm::VNInfo
VNInfo - Value Number Information.
Definition: LiveInterval.h:53
llvm::LiveRange::getVNInfoAt
VNInfo * getVNInfoAt(SlotIndex Idx) const
getVNInfoAt - Return the VNInfo that is live at Idx, or NULL.
Definition: LiveInterval.h:413
llvm::MachineOperand::getSymbolName
const char * getSymbolName() const
Definition: MachineOperand.h:608
llvm::MachineRegisterInfo::leaveSSA
void leaveSSA()
Definition: MachineRegisterInfo.h:191
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
llvm::AnalysisUsage::addRequired
AnalysisUsage & addRequired()
Definition: PassAnalysisSupport.h:75
raw_ostream.h
llvm::MachineDominatorTree
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
Definition: MachineDominators.h:45
MachineBlockFrequencyInfo.h
llvm::MachineBasicBlock::getName
StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
Definition: MachineBasicBlock.cpp:314
Debug.h
MachineDominators.h
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:37