42 #define DEBUG_TYPE "wasm-reg-stackify" 47 return "WebAssembly Register Stackify";
73 "Reorder instructions to use the WebAssembly value stack",
77 return new WebAssemblyRegStackify();
107 if (RegClass == &WebAssembly::I32RegClass) {
108 MI->
setDesc(TII->
get(WebAssembly::CONST_I32));
110 }
else if (RegClass == &WebAssembly::I64RegClass) {
111 MI->
setDesc(TII->
get(WebAssembly::CONST_I64));
113 }
else if (RegClass == &WebAssembly::F32RegClass) {
114 MI->
setDesc(TII->
get(WebAssembly::CONST_F32));
118 }
else if (RegClass == &WebAssembly::F64RegClass) {
119 MI->
setDesc(TII->
get(WebAssembly::CONST_F64));
123 }
else if (RegClass == &WebAssembly::V128RegClass) {
125 MI->
setDesc(TII->
get(WebAssembly::SPLAT_v4i32));
128 TII->
get(WebAssembly::CONST_I32), TempReg)
140 bool &Write,
bool &Effects,
bool &StackPointer) {
147 if (
const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
148 if (!GA->isInterposable())
149 GV = GA->getAliasee();
151 if (
const Function *
F = dyn_cast<Function>(GV)) {
152 if (!
F->doesNotThrow())
154 if (
F->doesNotAccessMemory())
156 if (
F->onlyReadsMemory()) {
172 bool &Write,
bool &Effects,
bool &StackPointer) {
187 case WebAssembly::DIV_S_I32:
188 case WebAssembly::DIV_S_I64:
189 case WebAssembly::REM_S_I32:
190 case WebAssembly::REM_S_I64:
191 case WebAssembly::DIV_U_I32:
192 case WebAssembly::DIV_U_I64:
193 case WebAssembly::REM_U_I32:
194 case WebAssembly::REM_U_I64:
195 case WebAssembly::I32_TRUNC_S_F32:
196 case WebAssembly::I64_TRUNC_S_F32:
197 case WebAssembly::I32_TRUNC_S_F64:
198 case WebAssembly::I64_TRUNC_S_F64:
199 case WebAssembly::I32_TRUNC_U_F32:
200 case WebAssembly::I64_TRUNC_U_F32:
201 case WebAssembly::I32_TRUNC_U_F64:
202 case WebAssembly::I64_TRUNC_U_F64:
222 case WebAssembly::DIV_S_I32:
223 case WebAssembly::DIV_S_I64:
224 case WebAssembly::REM_S_I32:
225 case WebAssembly::REM_S_I64:
226 case WebAssembly::DIV_U_I32:
227 case WebAssembly::DIV_U_I64:
228 case WebAssembly::REM_U_I32:
229 case WebAssembly::REM_U_I64:
230 case WebAssembly::I32_TRUNC_S_F32:
231 case WebAssembly::I64_TRUNC_S_F32:
232 case WebAssembly::I32_TRUNC_S_F64:
233 case WebAssembly::I64_TRUNC_S_F64:
234 case WebAssembly::I32_TRUNC_U_F32:
235 case WebAssembly::I64_TRUNC_U_F32:
236 case WebAssembly::I32_TRUNC_U_F64:
237 case WebAssembly::I64_TRUNC_U_F64:
250 if (MI.
getOpcode() == WebAssembly::GLOBAL_SET_I32 &&
257 QueryCallee(MI, CalleeOpNo, Read, Write, Effects, StackPointer);
264 return Def.
isAsCheapAsAMove() && TII->isTriviallyReMaterializable(Def, &AA);
301 if (Result.valueIn() == DefVNI) {
302 if (!Result.isKill())
324 if (!MO.isReg() || MO.isUndef())
326 unsigned Reg = MO.getReg();
336 if (Reg == WebAssembly::ARGUMENTS)
349 MutableRegisters.push_back(Reg);
352 bool Read =
false, Write =
false, Effects =
false, StackPointer =
false;
353 Query(*Def, AA, Read, Write, Effects, StackPointer);
357 bool HasMutableRegisters = !MutableRegisters.empty();
358 if (!Read && !Write && !Effects && !StackPointer && !HasMutableRegisters)
363 for (--I; I !=
D; --
I) {
364 bool InterveningRead =
false;
365 bool InterveningWrite =
false;
366 bool InterveningEffects =
false;
367 bool InterveningStackPointer =
false;
368 Query(*I, AA, InterveningRead, InterveningWrite, InterveningEffects,
369 InterveningStackPointer);
370 if (Effects && InterveningEffects)
372 if (Read && InterveningWrite)
374 if (Write && (InterveningRead || InterveningWrite))
376 if (StackPointer && InterveningStackPointer)
379 for (
unsigned Reg : MutableRegisters)
381 if (MO.isReg() && MO.isDef() && MO.getReg() ==
Reg)
407 if (UseVNI != OneUseVNI)
410 if (UseInst == OneUseInst) {
417 while (!MDT.
dominates(OneUseInst, UseInst)) {
428 unsigned DefReg = MO.
getReg();
435 if (NewUseInst == OneUseInst) {
436 if (&OneUse > &NewUse)
440 UseInst = NewUseInst;
449 if (RC == &WebAssembly::I32RegClass)
450 return WebAssembly::TEE_I32;
451 if (RC == &WebAssembly::I64RegClass)
452 return WebAssembly::TEE_I64;
453 if (RC == &WebAssembly::F32RegClass)
454 return WebAssembly::TEE_F32;
455 if (RC == &WebAssembly::F64RegClass)
456 return WebAssembly::TEE_F64;
457 if (RC == &WebAssembly::V128RegClass)
458 return WebAssembly::TEE_V128;
480 MBB.
splice(Insert, &MBB, Def);
506 DefDIs.updateReg(NewReg);
528 TII->reMaterialize(MBB, Insert, NewReg, 0, Def, *TRI);
556 DefDIs.move(&*Insert);
557 DefDIs.updateReg(NewReg);
559 DefDIs.clone(&*Insert, NewReg);
594 MBB.
splice(Insert, &MBB, Def);
629 DefDIs.clone(Tee, DefReg);
630 DefDIs.clone(Insert, TeeReg);
640 class TreeWalkerState {
642 typedef std::reverse_iterator<mop_iterator> mop_reverse_iterator;
653 bool Done()
const {
return Worklist.
empty(); }
656 RangeTy &Range = Worklist.
back();
659 if (Range.begin() == Range.end())
662 Worklist.
back().begin() != Worklist.
back().end()) &&
663 "Empty ranges shouldn't remain in the worklist");
670 if (Range.begin() != Range.end())
677 assert(HasRemainingOperands(Instr) &&
678 "Reseting operands should only be done when the instruction has " 679 "an operand still on the stack");
685 bool HasRemainingOperands(
const MachineInstr *Instr)
const {
686 if (Worklist.
empty())
688 const RangeTy &Range = Worklist.
back();
689 return Range.begin() != Range.end() && Range.begin()->getParent() == Instr;
698 bool IsOnStack(
unsigned Reg)
const {
699 for (
const RangeTy &Range : Worklist)
701 if (MO.isReg() && MO.getReg() ==
Reg)
709 class CommutingState {
715 bool TentativelyCommuting;
720 unsigned Operand0, Operand1;
723 CommutingState() : TentativelyCommuting(
false), Declined(
false) {}
728 void MaybeCommute(
MachineInstr *Insert, TreeWalkerState &TreeWalker,
730 if (TentativelyCommuting) {
732 "Don't decline commuting until you've finished trying it");
734 TII->commuteInstruction(*Insert,
false, Operand0, Operand1);
735 TentativelyCommuting =
false;
737 }
else if (!Declined && TreeWalker.HasRemainingOperands(Insert)) {
740 if (TII->findCommutedOpIndices(*Insert, Operand0, Operand1)) {
742 TII->commuteInstruction(*Insert,
false, Operand0, Operand1);
743 TreeWalker.ResetTopOperands(Insert);
744 TentativelyCommuting =
true;
753 TentativelyCommuting =
false;
759 bool WebAssemblyRegStackify::runOnMachineFunction(
MachineFunction &MF) {
760 LLVM_DEBUG(
dbgs() <<
"********** Register Stackifying **********\n" 761 "********** Function: " 764 bool Changed =
false;
769 AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
779 for (
auto MII = MBB.rbegin(); MII != MBB.rend(); ++MII) {
787 if (Insert->
getOpcode() == TargetOpcode::DBG_VALUE)
792 CommutingState Commuting;
793 TreeWalkerState TreeWalker(Insert);
794 while (!TreeWalker.Done()) {
802 assert(Op.
isUse() &&
"explicit_uses() should only iterate over uses");
804 "explicit_uses() should only iterate over explicit operands");
829 bool SameBlock = Def->
getParent() == &MBB;
830 bool CanMove = SameBlock &&
IsSafeToMove(Def, Insert, AA, MRI) &&
831 !TreeWalker.IsOnStack(Reg);
832 if (CanMove &&
HasOneUse(Reg, Def, MRI, MDT, LIS)) {
838 }
else if (CanMove &&
845 if (!CanMove && SameBlock)
846 Commuting.MaybeCommute(Insert, TreeWalker, TII);
854 if (Insert->
getOpcode() == TargetOpcode::IMPLICIT_DEF)
860 TreeWalker.PushOperands(Insert);
865 if (Insert != &*MII) {
876 MF.getRegInfo().addLiveIn(WebAssembly::VALUE_STACK);
878 MBB.addLiveIn(WebAssembly::VALUE_STACK);
886 if (
MI.isDebugInstr())
891 unsigned Reg = MO.getReg();
898 "Register stack pop should be paired with a push");
905 "Register stack pushes and pops should be balanced");
static MachineInstr * GetVRegDef(unsigned Reg, const MachineInstr *Insert, const MachineRegisterInfo &MRI, const LiveIntervals &LIS)
static Type * getDoubleTy(LLVMContext &C)
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
bool isCall(QueryType Type=AnyInBundle) const
const TargetRegisterClass * getRegClass(unsigned Reg) const
Return the register class of the specified virtual register.
SlotIndex def
The index of the defining instruction.
void RemoveMachineInstrFromMaps(MachineInstr &MI)
This class represents lattice values for constants.
void removePhysRegDefAt(unsigned Reg, SlotIndex Pos)
Remove value numbers and related live segments starting at position Pos that are part of any liverang...
Segments::iterator iterator
bool isPhysRegModified(unsigned PhysReg, bool SkipNoReturnDef=false) const
Return true if the specified register is modified in this function.
void push_back(const T &Elt)
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LiveInterval - This class represents the liveness of a register, or stack slot.
iterator_range< use_nodbg_iterator > use_nodbg_operands(unsigned Reg) const
unsigned getReg() const
getReg - Returns the register number.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
static MachineInstr * RematerializeCheapDef(unsigned Reg, MachineOperand &Op, MachineInstr &Def, MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator Insert, LiveIntervals &LIS, WebAssemblyFunctionInfo &MFI, MachineRegisterInfo &MRI, const WebAssemblyInstrInfo *TII, const WebAssemblyRegisterInfo *TRI)
A trivially cloneable instruction; clone it and nest the new copy with the current instruction...
unsigned const TargetRegisterInfo * TRI
bool hasOneDef(unsigned RegNo) const
Return true if there is exactly one operand defining the specified register.
VNInfo - Value Number Information.
iterator_range< mop_iterator > operands()
use_nodbg_iterator use_nodbg_begin(unsigned RegNo) const
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
static MachineOperand CreateReg(unsigned Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
FunctionPass * createWebAssemblyRegStackify()
AnalysisUsage & addRequired()
SlotIndex getDeadSlot() const
Returns the dead def kill slot for the current instruction.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
static Type * getFloatTy(LLVMContext &C)
static void ImposeStackOrdering(MachineInstr *MI)
A Use represents the edge between a Value definition and its users.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
bool isTerminator(QueryType Type=AnyInBundle) const
Returns true if this instruction part of the terminator for a basic block.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const char * getSymbolName() const
INLINEASM - Represents an inline asm block.
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
MachineInstr * getInstructionFromIndex(SlotIndex index) const
Returns the instruction associated with the given index.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def...
SlotIndex InsertMachineInstrInMaps(MachineInstr &MI)
static bool HasOneUse(unsigned Reg, MachineInstr *Def, MachineRegisterInfo &MRI, MachineDominatorTree &MDT, LiveIntervals &LIS)
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
AnalysisUsage & addPreservedID(const void *ID)
bool isVRegStackified(unsigned VReg) const
static MachineInstr * MoveAndTeeForMultiUse(unsigned Reg, MachineOperand &Op, MachineInstr *Def, MachineBasicBlock &MBB, MachineInstr *Insert, LiveIntervals &LIS, WebAssemblyFunctionInfo &MFI, MachineRegisterInfo &MRI, const WebAssemblyInstrInfo *TII)
A multiple-use def in the same block with no intervening memory or register dependencies; move the de...
static bool ShouldRematerialize(const MachineInstr &Def, AliasAnalysis &AA, const WebAssemblyInstrInfo *TII)
unsigned getUndefRegState(bool B)
bool isDereferenceableInvariantLoad(AliasAnalysis *AA) const
Return true if this load instruction never traps and points to a memory location whose value doesn't ...
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
static void ConvertImplicitDefToConstZero(MachineInstr *MI, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineFunction &MF, LiveIntervals &LIS)
LiveQueryResult Query(SlotIndex Idx) const
Query Liveness at Idx.
TargetInstrInfo - Interface to description of machine instruction set.
VNInfo * getVNInfoAt(SlotIndex Idx) const
getVNInfoAt - Return the VNInfo that is live at Idx, or NULL.
This file contains the declaration of the WebAssembly-specific utility functions. ...
char & LiveVariablesID
LiveVariables pass - This pass computes the set of blocks in which each variable is life and sets mac...
static const unsigned CommuteAnyOperandIndex
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
MachineInstrBundleIterator< MachineInstr > iterator
unsigned const MachineRegisterInfo * MRI
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
void removeInterval(unsigned Reg)
Interval removal.
bool liveAt(SlotIndex index) const
static MachineOperand CreateFPImm(const ConstantFP *CFP)
This is an important base class in LLVM.
void splitSeparateComponents(LiveInterval &LI, SmallVectorImpl< LiveInterval *> &SplitLIs)
Split separate components in LiveInterval LI into separate intervals.
const GlobalValue * getGlobal() const
ConstantFP - Floating Point Values [float, double].
This file provides WebAssembly-specific target descriptions.
Represent the analysis usage information of a pass.
bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr *> *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses...
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
FunctionPass class - This class is used to implement most global optimizations.
bool definesRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr fully defines the specified register.
self_iterator getIterator()
void stackifyVReg(unsigned VReg)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
iterator_range< decltype(adl_begin(std::declval< T >)))> drop_begin(T &&t, int n)
bool isDebugInstr() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static void QueryCallee(const MachineInstr &MI, unsigned CalleeOpNo, bool &Read, bool &Write, bool &Effects, bool &StackPointer)
iterator_range< mop_iterator > explicit_uses()
void removeSegment(SlotIndex Start, SlotIndex End, bool RemoveDeadValNo=false)
Remove the specified segment from this range.
This file declares the WebAssembly-specific subclass of TargetSubtarget.
Iterator for intrusive lists based on ilist_node.
void setDesc(const MCInstrDesc &tid)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one...
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
static unsigned GetTeeOpcode(const TargetRegisterClass *RC)
Get the appropriate tee opcode for the given register class.
bool isArgument(const MachineInstr &MI)
MachineOperand class - Representation of each machine instruction operand.
bool dominates(const MachineDomTreeNode *A, const MachineDomTreeNode *B) const
LLVM_NODISCARD T pop_back_val()
static void ShrinkToUses(LiveInterval &LI, LiveIntervals &LIS)
bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
LiveInterval & getInterval(unsigned Reg)
static bool IsSafeToMove(const MachineInstr *Def, const MachineInstr *Insert, AliasAnalysis &AA, const MachineRegisterInfo &MRI)
MachineInstr * getUniqueVRegDef(unsigned Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
VNInfo * getVNInfoBefore(SlotIndex Idx) const
getVNInfoBefore - Return the VNInfo that is live up to but not necessarilly including Idx...
A range adaptor for a pair of iterators.
bool readsRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr reads the specified register.
bool use_empty(unsigned RegNo) const
use_empty - Return true if there are no instructions using the specified register.
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
const MachineBasicBlock * getParent() const
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
INITIALIZE_PASS(WebAssemblyRegStackify, DEBUG_TYPE, "Reorder instructions to use the WebAssembly value stack", false, false) FunctionPass *llvm
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
bool hasOneUse(unsigned RegNo) const
hasOneUse - Return true if there is exactly one instruction using the specified register.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
LLVM_NODISCARD bool empty() const
unsigned getCalleeOpNo(const MachineInstr &MI)
Returns the operand number of a callee, assuming the argument is a call instruction.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
void setReg(unsigned Reg)
Change the register this operand corresponds to.
static MachineOperand CreateImm(int64_t Val)
This file declares WebAssembly-specific per-machine-function information.
static void Query(const MachineInstr &MI, AliasAnalysis &AA, bool &Read, bool &Write, bool &Effects, bool &StackPointer)
static bool OneUseDominatesOtherUses(unsigned Reg, const MachineOperand &OneUse, const MachineBasicBlock &MBB, const MachineRegisterInfo &MRI, const MachineDominatorTree &MDT, LiveIntervals &LIS, WebAssemblyFunctionInfo &MFI)
Test whether OneUse, a use of Reg, dominates all of Reg's other uses.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool hasOneNonDBGUse(unsigned RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug instruction using the specified regis...
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains the declaration of the WebAssembly-specific manager for DebugValues associated wit...
bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore...
StringRef - Represent a constant reference to a string, i.e.
iterator FindSegmentContaining(SlotIndex Idx)
Return an iterator to the segment that contains the specified index, or end() if there is none...
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object...
const MachineOperand & getOperand(unsigned i) const
SlotIndex - An opaque wrapper around machine indexes.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
bool isAsCheapAsAMove(QueryType Type=AllInBundle) const
Returns true if this instruction has the same cost (or less) than a move instruction.
static MachineInstr * MoveForSingleUse(unsigned Reg, MachineOperand &Op, MachineInstr *Def, MachineBasicBlock &MBB, MachineInstr *Insert, LiveIntervals &LIS, WebAssemblyFunctionInfo &MFI, MachineRegisterInfo &MRI)
A single-use def in the same block with no intervening memory or register dependencies; move the def ...
unsigned createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
void handleMove(MachineInstr &MI, bool UpdateFlags=false)
Call this method to notify LiveIntervals that instruction MI has been moved within a basic block...
LiveInterval & createAndComputeVirtRegInterval(unsigned Reg)