[WebAssembly] Don't stackify calls past stack pointer modifications.
llvm-svn: 269843
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
index 7e2f416..4fcae94 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
@@ -82,7 +82,8 @@
MachineBasicBlock::iterator &InsertAddr,
MachineBasicBlock::iterator &InsertStore,
DebugLoc DL) {
- auto *SPSymbol = MF.createExternalSymbolName("__stack_pointer");
+ const char *ES = "__stack_pointer";
+ auto *SPSymbol = MF.createExternalSymbolName(ES);
MachineRegisterInfo &MRI = MF.getRegInfo();
const TargetRegisterClass *PtrRC =
MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
@@ -92,7 +93,8 @@
BuildMI(MBB, InsertAddr, DL, TII->get(WebAssembly::CONST_I32), SPAddr)
.addExternalSymbol(SPSymbol);
- auto *MMO = new MachineMemOperand(MachinePointerInfo(),
+ auto *MMO = new MachineMemOperand(MachinePointerInfo(MF.getPSVManager()
+ .getExternalSymbolCallEntry(ES)),
MachineMemOperand::MOStore, 4, 4);
BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::STORE_I32),
Discard)
@@ -138,14 +140,12 @@
MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
unsigned SPAddr = MRI.createVirtualRegister(PtrRC);
unsigned SPReg = MRI.createVirtualRegister(PtrRC);
- auto *SPSymbol = MF.createExternalSymbolName("__stack_pointer");
+ const char *ES = "__stack_pointer";
+ auto *SPSymbol = MF.createExternalSymbolName(ES);
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), SPAddr)
.addExternalSymbol(SPSymbol);
- // This MachinePointerInfo should reference __stack_pointer as well but
- // doesn't because MachinePointerInfo() takes a GV which we don't have for
- // __stack_pointer. TODO: check if PseudoSourceValue::ExternalSymbolCallEntry
- // is appropriate instead. (likewise for EmitEpologue below)
- auto *LoadMMO = new MachineMemOperand(MachinePointerInfo(),
+ auto *LoadMMO = new MachineMemOperand(MachinePointerInfo(MF.getPSVManager()
+ .getExternalSymbolCallEntry(ES)),
MachineMemOperand::MOLoad, 4, 4);
// Load the SP value.
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::LOAD_I32),
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
index b47de78..bd843fb 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
@@ -90,7 +90,11 @@
// MI->getOperand(CalleeOpNo) reads memory, writes memory, and/or has side
// effects.
static void QueryCallee(const MachineInstr *MI, unsigned CalleeOpNo,
- bool &Read, bool &Write, bool &Effects) {
+ bool &Read, bool &Write, bool &Effects,
+ bool &StackPointer) {
+ // All calls can use the stack pointer.
+ StackPointer = true;
+
const MachineOperand &MO = MI->getOperand(CalleeOpNo);
if (MO.isGlobal()) {
const Constant *GV = MO.getGlobal();
@@ -116,10 +120,10 @@
Effects = true;
}
-// Determine whether MI reads memory, writes memory, and/or has side
-// effects.
+// Determine whether MI reads memory, writes memory, has side effects,
+// and/or uses the __stack_pointer value.
static void Query(const MachineInstr *MI, AliasAnalysis &AA,
- bool &Read, bool &Write, bool &Effects) {
+ bool &Read, bool &Write, bool &Effects, bool &StackPointer) {
assert(!MI->isPosition());
assert(!MI->isTerminator());
assert(!MI->isDebugValue());
@@ -129,9 +133,21 @@
Read = true;
// Check for stores.
- if (MI->mayStore())
+ if (MI->mayStore()) {
Write = true;
- else if (MI->hasOrderedMemoryRef()) {
+
+ // Check for stores to __stack_pointer.
+ for (auto MMO : MI->memoperands()) {
+ const MachinePointerInfo &MPI = MMO->getPointerInfo();
+ if (MPI.V.is<const PseudoSourceValue *>()) {
+ auto PSV = MPI.V.get<const PseudoSourceValue *>();
+ if (const ExternalSymbolPseudoSourceValue *EPSV =
+ dyn_cast<ExternalSymbolPseudoSourceValue>(PSV))
+ if (StringRef(EPSV->getSymbol()) == "__stack_pointer")
+ StackPointer = true;
+ }
+ }
+ } else if (MI->hasOrderedMemoryRef()) {
switch (MI->getOpcode()) {
case WebAssembly::DIV_S_I32: case WebAssembly::DIV_S_I64:
case WebAssembly::REM_S_I32: case WebAssembly::REM_S_I64:
@@ -181,13 +197,13 @@
if (MI->isCall()) {
switch (MI->getOpcode()) {
case WebAssembly::CALL_VOID:
- QueryCallee(MI, 0, Read, Write, Effects);
+ QueryCallee(MI, 0, Read, Write, Effects, StackPointer);
break;
case WebAssembly::CALL_I32:
case WebAssembly::CALL_I64:
case WebAssembly::CALL_F32:
case WebAssembly::CALL_F64:
- QueryCallee(MI, 1, Read, Write, Effects);
+ QueryCallee(MI, 1, Read, Write, Effects, StackPointer);
break;
case WebAssembly::CALL_INDIRECT_VOID:
case WebAssembly::CALL_INDIRECT_I32:
@@ -197,6 +213,7 @@
Read = true;
Write = true;
Effects = true;
+ StackPointer = true;
break;
default:
llvm_unreachable("unexpected call opcode");
@@ -308,12 +325,12 @@
return false;
}
- bool Read = false, Write = false, Effects = false;
- Query(Def, AA, Read, Write, Effects);
+ bool Read = false, Write = false, Effects = false, StackPointer = false;
+ Query(Def, AA, Read, Write, Effects, StackPointer);
// If the instruction does not access memory and has no side effects, it has
// no additional dependencies.
- if (!Read && !Write && !Effects)
+ if (!Read && !Write && !Effects && !StackPointer)
return true;
// Scan through the intervening instructions between Def and Insert.
@@ -322,13 +339,17 @@
bool InterveningRead = false;
bool InterveningWrite = false;
bool InterveningEffects = false;
- Query(I, AA, InterveningRead, InterveningWrite, InterveningEffects);
+ bool InterveningStackPointer = false;
+ Query(I, AA, InterveningRead, InterveningWrite, InterveningEffects,
+ InterveningStackPointer);
if (Effects && InterveningEffects)
return false;
if (Read && InterveningWrite)
return false;
if (Write && (InterveningRead || InterveningWrite))
return false;
+ if (StackPointer && InterveningStackPointer)
+ return false;
}
return true;