forked from OSchip/llvm-project
[WebAssembly] Don't stackify calls past stack pointer modifications.
llvm-svn: 269843
This commit is contained in:
parent
096ccdd389
commit
d08cd15f33
|
@ -82,7 +82,8 @@ static void writeSPToMemory(unsigned SrcReg, MachineFunction &MF,
|
|||
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 @@ static void writeSPToMemory(unsigned SrcReg, MachineFunction &MF,
|
|||
|
||||
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 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
|
|||
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),
|
||||
|
|
|
@ -90,7 +90,11 @@ static void ImposeStackOrdering(MachineInstr *MI) {
|
|||
// 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 @@ static void QueryCallee(const MachineInstr *MI, unsigned CalleeOpNo,
|
|||
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 @@ static void Query(const MachineInstr *MI, AliasAnalysis &AA,
|
|||
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 @@ static void Query(const MachineInstr *MI, AliasAnalysis &AA,
|
|||
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 @@ static void Query(const MachineInstr *MI, AliasAnalysis &AA,
|
|||
Read = true;
|
||||
Write = true;
|
||||
Effects = true;
|
||||
StackPointer = true;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("unexpected call opcode");
|
||||
|
@ -308,12 +325,12 @@ static bool IsSafeToMove(const MachineInstr *Def, const MachineInstr *Insert,
|
|||
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 @@ static bool IsSafeToMove(const MachineInstr *Def, const MachineInstr *Insert,
|
|||
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;
|
||||
|
|
|
@ -402,7 +402,7 @@ define i32 @no_stackify_past_epilogue() {
|
|||
|
||||
; Stackify a loop induction variable into a loop comparison.
|
||||
|
||||
; CHECK_LABEL: stackify_indvar:
|
||||
; CHECK-LABEL: stackify_indvar:
|
||||
; CHECK: i32.const $push[[L5:.+]]=, 1{{$}}
|
||||
; CHECK-NEXT: i32.add $push[[L4:.+]]=, $[[R0:.+]], $pop[[L5]]{{$}}
|
||||
; CHECK-NEXT: tee_local $push[[L3:.+]]=, $[[R0]]=, $pop[[L4]]{{$}}
|
||||
|
@ -424,6 +424,20 @@ bb10: ; preds = %bb9, %bb
|
|||
ret void
|
||||
}
|
||||
|
||||
; Don't stackify a call past a __stack_pointer store.
|
||||
|
||||
; CHECK-LABEL: stackpointer_dependency:
|
||||
; CHECK: call {{.+}}, stackpointer_callee@FUNCTION,
|
||||
; CHECK: i32.const $push[[L0:.+]]=, __stack_pointer
|
||||
; CHECK-NEXT: i32.store $discard=, 0($pop[[L0]]),
|
||||
declare i32 @stackpointer_callee(i8* readnone, i8* readnone)
|
||||
declare i8* @llvm.frameaddress(i32)
|
||||
define i32 @stackpointer_dependency(i8* readnone) {
|
||||
%2 = tail call i8* @llvm.frameaddress(i32 0)
|
||||
%3 = tail call i32 @stackpointer_callee(i8* %0, i8* %2)
|
||||
ret i32 %3
|
||||
}
|
||||
|
||||
!llvm.module.flags = !{!0}
|
||||
!llvm.dbg.cu = !{!1}
|
||||
|
||||
|
|
Loading…
Reference in New Issue