39 #define DEBUG_TYPE "wasm-reg-stackify"
44 return "WebAssembly Register Stackify";
70 return new WebAssemblyRegStackify();
98 const auto *RegClass =
100 if (RegClass == &WebAssembly::I32RegClass) {
101 MI->
setDesc(TII->
get(WebAssembly::CONST_I32));
103 }
else if (RegClass == &WebAssembly::I64RegClass) {
104 MI->
setDesc(TII->
get(WebAssembly::CONST_I64));
106 }
else if (RegClass == &WebAssembly::F32RegClass) {
107 MI->
setDesc(TII->
get(WebAssembly::CONST_F32));
111 }
else if (RegClass == &WebAssembly::F64RegClass) {
112 MI->
setDesc(TII->
get(WebAssembly::CONST_F64));
125 bool &Write,
bool &Effects,
bool &StackPointer) {
132 if (
const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
133 if (!GA->isInterposable())
134 GV = GA->getAliasee();
136 if (
const Function *
F = dyn_cast<Function>(GV)) {
137 if (!
F->doesNotThrow())
139 if (
F->doesNotAccessMemory())
141 if (
F->onlyReadsMemory()) {
157 bool &Write,
bool &Effects,
bool &StackPointer) {
178 dyn_cast<ExternalSymbolPseudoSourceValue>(PSV))
179 if (
StringRef(EPSV->getSymbol()) ==
"__stack_pointer")
185 case WebAssembly::DIV_S_I32:
case WebAssembly::DIV_S_I64:
186 case WebAssembly::REM_S_I32:
case WebAssembly::REM_S_I64:
187 case WebAssembly::DIV_U_I32:
case WebAssembly::DIV_U_I64:
188 case WebAssembly::REM_U_I32:
case WebAssembly::REM_U_I64:
189 case WebAssembly::I32_TRUNC_S_F32:
case WebAssembly::I64_TRUNC_S_F32:
190 case WebAssembly::I32_TRUNC_S_F64:
case WebAssembly::I64_TRUNC_S_F64:
191 case WebAssembly::I32_TRUNC_U_F32:
case WebAssembly::I64_TRUNC_U_F32:
192 case WebAssembly::I32_TRUNC_U_F64:
case WebAssembly::I64_TRUNC_U_F64:
212 case WebAssembly::DIV_S_I32:
case WebAssembly::DIV_S_I64:
213 case WebAssembly::REM_S_I32:
case WebAssembly::REM_S_I64:
214 case WebAssembly::DIV_U_I32:
case WebAssembly::DIV_U_I64:
215 case WebAssembly::REM_U_I32:
case WebAssembly::REM_U_I64:
216 case WebAssembly::I32_TRUNC_S_F32:
case WebAssembly::I64_TRUNC_S_F32:
217 case WebAssembly::I32_TRUNC_S_F64:
case WebAssembly::I64_TRUNC_S_F64:
218 case WebAssembly::I32_TRUNC_U_F32:
case WebAssembly::I64_TRUNC_U_F32:
219 case WebAssembly::I32_TRUNC_U_F64:
case WebAssembly::I64_TRUNC_U_F64:
234 case WebAssembly::CALL_VOID:
235 case WebAssembly::CALL_INDIRECT_VOID:
236 QueryCallee(MI, 0, Read, Write, Effects, StackPointer);
238 case WebAssembly::CALL_I32:
case WebAssembly::CALL_I64:
239 case WebAssembly::CALL_F32:
case WebAssembly::CALL_F64:
240 case WebAssembly::CALL_INDIRECT_I32:
case WebAssembly::CALL_INDIRECT_I64:
241 case WebAssembly::CALL_INDIRECT_F32:
case WebAssembly::CALL_INDIRECT_F64:
242 QueryCallee(MI, 1, Read, Write, Effects, StackPointer);
253 return Def.
isAsCheapAsAMove() && TII->isTriviallyReMaterializable(Def, &AA);
292 if (Result.valueIn() == DefVNI) {
293 if (!Result.isKill())
315 if (!MO.isReg() || MO.isUndef())
317 unsigned Reg = MO.getReg();
327 if (Reg == WebAssembly::ARGUMENTS)
340 MutableRegisters.push_back(Reg);
343 bool Read =
false, Write =
false, Effects =
false, StackPointer =
false;
344 Query(*Def, AA, Read, Write, Effects, StackPointer);
348 bool HasMutableRegisters = !MutableRegisters.empty();
349 if (!Read && !Write && !Effects && !StackPointer && !HasMutableRegisters)
354 for (--I; I !=
D; --
I) {
355 bool InterveningRead =
false;
356 bool InterveningWrite =
false;
357 bool InterveningEffects =
false;
358 bool InterveningStackPointer =
false;
359 Query(*I, AA, InterveningRead, InterveningWrite, InterveningEffects,
360 InterveningStackPointer);
361 if (Effects && InterveningEffects)
363 if (Read && InterveningWrite)
365 if (Write && (InterveningRead || InterveningWrite))
367 if (StackPointer && InterveningStackPointer)
370 for (
unsigned Reg : MutableRegisters)
372 if (MO.isReg() && MO.isDef() && MO.getReg() ==
Reg)
398 if (UseVNI != OneUseVNI)
402 if (UseInst == OneUseInst) {
409 while (!MDT.
dominates(OneUseInst, UseInst)) {
420 unsigned DefReg = MO.
getReg();
427 if (NewUseInst == OneUseInst) {
428 if (&OneUse > &NewUse)
432 UseInst = NewUseInst;
441 if (RC == &WebAssembly::I32RegClass)
442 return WebAssembly::TEE_I32;
443 if (RC == &WebAssembly::I64RegClass)
444 return WebAssembly::TEE_I64;
445 if (RC == &WebAssembly::F32RegClass)
446 return WebAssembly::TEE_F32;
447 if (RC == &WebAssembly::F64RegClass)
448 return WebAssembly::TEE_F64;
449 if (RC == &WebAssembly::V128RegClass)
450 return WebAssembly::TEE_V128;
472 MBB.
splice(Insert, &MBB, Def);
515 TII->reMaterialize(MBB, Insert, NewReg, 0, Def, *TRI);
535 DEBUG(
dbgs() <<
" - Deleting original\n");
573 MBB.
splice(Insert, &MBB, Def);
614 class TreeWalkerState {
616 typedef std::reverse_iterator<mop_iterator> mop_reverse_iterator;
624 Worklist.push_back(
reverse(Range));
627 bool Done()
const {
return Worklist.empty(); }
630 RangeTy &Range = Worklist.back();
633 if (Range.begin() == Range.end())
635 assert((Worklist.empty() ||
636 Worklist.back().begin() != Worklist.back().end()) &&
637 "Empty ranges shouldn't remain in the worklist");
644 if (Range.begin() != Range.end())
645 Worklist.push_back(
reverse(Range));
651 assert(HasRemainingOperands(Instr) &&
652 "Reseting operands should only be done when the instruction has "
653 "an operand still on the stack");
659 bool HasRemainingOperands(
const MachineInstr *Instr)
const {
660 if (Worklist.empty())
662 const RangeTy &Range = Worklist.back();
663 return Range.begin() != Range.end() && Range.begin()->getParent() == Instr;
672 bool IsOnStack(
unsigned Reg)
const {
673 for (
const RangeTy &Range : Worklist)
675 if (MO.isReg() && MO.getReg() ==
Reg)
683 class CommutingState {
689 bool TentativelyCommuting;
694 unsigned Operand0, Operand1;
697 CommutingState() : TentativelyCommuting(
false), Declined(
false) {}
702 void MaybeCommute(
MachineInstr *Insert, TreeWalkerState &TreeWalker,
704 if (TentativelyCommuting) {
706 "Don't decline commuting until you've finished trying it");
708 TII->commuteInstruction(*Insert,
false, Operand0, Operand1);
709 TentativelyCommuting =
false;
711 }
else if (!Declined && TreeWalker.HasRemainingOperands(Insert)) {
714 if (TII->findCommutedOpIndices(*Insert, Operand0, Operand1)) {
716 TII->commuteInstruction(*Insert,
false, Operand0, Operand1);
717 TreeWalker.ResetTopOperands(Insert);
718 TentativelyCommuting =
true;
727 TentativelyCommuting =
false;
733 bool WebAssemblyRegStackify::runOnMachineFunction(
MachineFunction &MF) {
734 DEBUG(
dbgs() <<
"********** Register Stackifying **********\n"
735 "********** Function: "
738 bool Changed =
false;
743 AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
761 if (Insert->
getOpcode() == TargetOpcode::DBG_VALUE)
766 CommutingState Commuting;
767 TreeWalkerState TreeWalker(Insert);
768 while (!TreeWalker.Done()) {
775 unsigned Reg = Op.
getReg();
776 assert(Op.
isUse() &&
"explicit_uses() should only iterate over uses");
778 "explicit_uses() should only iterate over explicit operands");
804 bool CanMove = SameBlock &&
IsSafeToMove(Def, Insert, AA, MRI) &&
805 !TreeWalker.IsOnStack(Reg);
806 if (CanMove &&
HasOneUse(Reg, Def, MRI, MDT, LIS)) {
812 }
else if (CanMove &&
819 if (!CanMove && SameBlock)
820 Commuting.MaybeCommute(Insert, TreeWalker, TII);
828 if (Insert->
getOpcode() == TargetOpcode::IMPLICIT_DEF)
834 TreeWalker.PushOperands(Insert);
839 if (Insert != &*MII) {
850 MF.getRegInfo().addLiveIn(WebAssembly::VALUE_STACK);
860 if (
MI.isDebugValue())
865 unsigned Reg = MO.getReg();
872 "Register stack pop should be paired with a push");
879 "Register stack pushes and pops should be balanced");
static MachineInstr * GetVRegDef(unsigned Reg, const MachineInstr *Insert, const MachineRegisterInfo &MRI, const LiveIntervals &LIS)
void push_back(const T &Elt)
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.
const GlobalValue * getGlobal() const
Segments::iterator iterator
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
SlotIndex def
The index of the defining instruction.
void RemoveMachineInstrFromMaps(MachineInstr &MI)
void removePhysRegDefAt(unsigned Reg, SlotIndex Pos)
Remove value numbers and related live segments starting at position Pos that are part of any liverang...
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
unsigned createVirtualRegister(const TargetRegisterClass *RegClass)
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LiveInterval - This class represents the liveness of a register, or stack slot.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
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...
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
MachineInstrBundleIterator< MachineInstr > iterator
bool isVRegStackified(unsigned VReg) const
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
void splitSeparateComponents(LiveInterval &LI, SmallVectorImpl< LiveInterval * > &SplitLIs)
Split separate components in LiveInterval LI into separate intervals.
iterator_range< mmo_iterator > memoperands()
VNInfo - Value Number Information.
iterator_range< mop_iterator > operands()
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
VNInfo * getVNInfoAt(SlotIndex Idx) const
getVNInfoAt - Return the VNInfo that is live at Idx, or NULL.
bool isTerminator(QueryType Type=AnyInBundle) const
Returns true if this instruction part of the terminator for a basic block.
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
bool isDereferenceableInvariantLoad(AliasAnalysis *AA) const
Return true if this load instruction never traps and points to a memory location whose value doesn't ...
AnalysisUsage & addRequired()
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
static Type * getFloatTy(LLVMContext &C)
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)
static void ImposeStackOrdering(MachineInstr *MI)
A Use represents the edge between a Value definition and its users.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static GCRegistry::Add< StatepointGC > D("statepoint-example","an example strategy for statepoint")
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
const TargetRegisterClass * getRegClass(unsigned Reg) const
Return the register class of the specified virtual register.
Reg
All possible values of the reg field in the ModR/M byte.
SlotIndex getDeadSlot() const
Returns the dead def kill slot for the current instruction.
INLINEASM - Represents an inline asm block.
LLVM_NODISCARD bool empty() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
SlotIndex InsertMachineInstrInMaps(MachineInstr &MI)
Function Alias Analysis false
static bool HasOneUse(unsigned Reg, MachineInstr *Def, MachineRegisterInfo &MRI, MachineDominatorTree &MDT, LiveIntervals &LIS)
bool shrinkToUses(LiveInterval *li, SmallVectorImpl< MachineInstr * > *dead=nullptr)
After removing some uses of a register, shrink its live range to just the remaining uses...
AnalysisUsage & addPreservedID(const void *ID)
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)
reverse_iterator rbegin()
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
static void ConvertImplicitDefToConstZero(MachineInstr *MI, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineFunction &MF)
const MachineBasicBlock * getParent() const
TargetInstrInfo - Interface to description of machine instruction set.
bool isDebugValue() const
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.
void addLiveIn(MCPhysReg PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
LiveQueryResult Query(SlotIndex Idx) const
Query Liveness at Idx.
unsigned const MachineRegisterInfo * MRI
iterator_range< use_nodbg_iterator > use_nodbg_operands(unsigned Reg) const
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
void removeInterval(unsigned Reg)
static MachineOperand CreateFPImm(const ConstantFP *CFP)
PointerUnion< const Value *, const PseudoSourceValue * > V
This is the IR pointer value for the access, or it is null if unknown.
This is an important base class in LLVM.
bool isAsCheapAsAMove(QueryType Type=AllInBundle) const
Returns true if this instruction has the same cost (or less) than a move instruction.
const MachineOperand & getOperand(unsigned i) const
ConstantFP - Floating Point Values [float, double].
This file provides WebAssembly-specific target descriptions.
Represent the analysis usage information of a pass.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore...
FunctionPass class - This class is used to implement most global optimizations.
self_iterator getIterator()
void stackifyVReg(unsigned VReg)
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
bool liveAt(SlotIndex index) const
This class contains a discriminated union of information about pointers in memory operands...
#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)
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
bool definesRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr fully defines the specified register.
iterator_range< mop_iterator > explicit_uses()
void removeSegment(SlotIndex Start, SlotIndex End, bool RemoveDeadValNo=false)
Remove the specified segment from this range.
bool readsRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr reads the specified register.
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.
static unsigned GetTeeOpcode(const TargetRegisterClass *RC)
Get the appropriate tee opcode for the given register class.
bool isArgument(const MachineInstr &MI)
T get() const
Returns the value of the specified pointer type.
MachineOperand class - Representation of each machine instruction operand.
FunctionPass * createWebAssemblyRegStackify()
bool hasOneUse(unsigned RegNo) const
hasOneUse - Return true if there is exactly one instruction using the specified register.
LLVM_NODISCARD T pop_back_val()
static void ShrinkToUses(LiveInterval &LI, LiveIntervals &LIS)
void dump(const TargetInstrInfo *TII=nullptr) const
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)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
A range adaptor for a pair of iterators.
A specialized pseudo source value for holding external symbol values.
Special value supplied for machine level alias analysis.
MachineInstr * getUniqueVRegDef(unsigned Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
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.
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 hasOneDef(unsigned RegNo) const
Return true if there is exactly one operand defining 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.
use_iterator use_begin(unsigned RegNo) const
void setReg(unsigned Reg)
Change the register this operand corresponds to.
static MachineOperand CreateImm(int64_t Val)
bool isCall(QueryType Type=AnyInBundle) const
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.
bool isPhysRegModified(unsigned PhysReg, bool SkipNoReturnDef=false) const
Return true if the specified register is modified in this function.
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def...
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
MachineInstr * getInstructionFromIndex(SlotIndex index) const
Returns the instruction associated with the given index.
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...
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
iterator_range< decltype(begin(std::declval< T >)))> drop_begin(T &&t, int n)
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object...
int is() const
Test if the Union currently holds the type matching T.
bool dominates(const MachineDomTreeNode *A, const MachineDomTreeNode *B) const
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
SlotIndex - An opaque wrapper around machine indexes.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
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 ...
VNInfo * getVNInfoBefore(SlotIndex Idx) const
getVNInfoBefore - Return the VNInfo that is live up to but not necessarilly including Idx...
void handleMove(MachineInstr &MI, bool UpdateFlags=false)
handleMove - call this method to notify LiveIntervals that instruction 'mi' has been moved within a b...
LiveInterval & createAndComputeVirtRegInterval(unsigned Reg)
bool use_empty(unsigned RegNo) const
use_empty - Return true if there are no instructions using the specified register.