Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit c61677f

Browse files
committed
[WebAssembly] Make register stackification more conservative
Register stackification currently checks VNInfo for changes. Make that more accurate by testing each intervening instruction for any other defs to the same virtual register. Patch by Jacob Gravelle Differential Revision: https://reviews.llvm.org/D24942 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282886 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent eabc8ab commit c61677f

File tree

2 files changed

+51
-19
lines changed

2 files changed

+51
-19
lines changed

lib/Target/WebAssembly/WebAssemblyRegStackify.cpp

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -274,11 +274,11 @@ static bool HasOneUse(unsigned Reg, MachineInstr *Def,
274274
// TODO: Compute memory dependencies in a way that uses AliasAnalysis to be
275275
// more precise.
276276
static bool IsSafeToMove(const MachineInstr *Def, const MachineInstr *Insert,
277-
AliasAnalysis &AA, const LiveIntervals &LIS,
278-
const MachineRegisterInfo &MRI) {
277+
AliasAnalysis &AA, const MachineRegisterInfo &MRI) {
279278
assert(Def->getParent() == Insert->getParent());
280279

281280
// Check for register dependencies.
281+
SmallVector<unsigned, 4> MutableRegisters;
282282
for (const MachineOperand &MO : Def->operands()) {
283283
if (!MO.isReg() || MO.isUndef())
284284
continue;
@@ -301,29 +301,20 @@ static bool IsSafeToMove(const MachineInstr *Def, const MachineInstr *Insert,
301301
return false;
302302
}
303303

304-
// Ask LiveIntervals whether moving this virtual register use or def to
305-
// Insert will change which value numbers are seen.
306-
//
307-
// If the operand is a use of a register that is also defined in the same
308-
// instruction, test that the newly defined value reaches the insert point,
309-
// since the operand will be moving along with the def.
310-
const LiveInterval &LI = LIS.getInterval(Reg);
311-
VNInfo *DefVNI =
312-
(MO.isDef() || Def->definesRegister(Reg)) ?
313-
LI.getVNInfoAt(LIS.getInstructionIndex(*Def).getRegSlot()) :
314-
LI.getVNInfoBefore(LIS.getInstructionIndex(*Def));
315-
assert(DefVNI && "Instruction input missing value number");
316-
VNInfo *InsVNI = LI.getVNInfoBefore(LIS.getInstructionIndex(*Insert));
317-
if (InsVNI && DefVNI != InsVNI)
318-
return false;
304+
// If one of the operands isn't in SSA form, it has different values at
305+
// different times, and we need to make sure we don't move our use across
306+
// a different def.
307+
if (!MO.isDef() && !MRI.hasOneDef(Reg))
308+
MutableRegisters.push_back(Reg);
319309
}
320310

321311
bool Read = false, Write = false, Effects = false, StackPointer = false;
322312
Query(*Def, AA, Read, Write, Effects, StackPointer);
323313

324314
// If the instruction does not access memory and has no side effects, it has
325315
// no additional dependencies.
326-
if (!Read && !Write && !Effects && !StackPointer)
316+
bool HasMutableRegisters = !MutableRegisters.empty();
317+
if (!Read && !Write && !Effects && !StackPointer && !HasMutableRegisters)
327318
return true;
328319

329320
// Scan through the intervening instructions between Def and Insert.
@@ -343,6 +334,11 @@ static bool IsSafeToMove(const MachineInstr *Def, const MachineInstr *Insert,
343334
return false;
344335
if (StackPointer && InterveningStackPointer)
345336
return false;
337+
338+
for (unsigned Reg : MutableRegisters)
339+
for (const MachineOperand &MO : I->operands())
340+
if (MO.isReg() && MO.isDef() && MO.getReg() == Reg)
341+
return false;
346342
}
347343

348344
return true;
@@ -781,7 +777,7 @@ bool WebAssemblyRegStackify::runOnMachineFunction(MachineFunction &MF) {
781777
// supports intra-block moves) and it's MachineSink's job to catch all
782778
// the sinking opportunities anyway.
783779
bool SameBlock = Def->getParent() == &MBB;
784-
bool CanMove = SameBlock && IsSafeToMove(Def, Insert, AA, LIS, MRI) &&
780+
bool CanMove = SameBlock && IsSafeToMove(Def, Insert, AA, MRI) &&
785781
!TreeWalker.IsOnStack(Reg);
786782
if (CanMove && HasOneUse(Reg, Def, MRI, MDT, LIS)) {
787783
Insert = MoveForSingleUse(Reg, Op, Def, MBB, Insert, LIS, MFI, MRI);

test/CodeGen/WebAssembly/userstack.ll

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,42 @@ define void @dynamic_static_alloca(i32 %alloc) noredzone {
232232
ret void
233233
}
234234

235+
declare i8* @llvm.stacksave()
236+
declare void @llvm.stackrestore(i8*)
237+
238+
; CHECK-LABEL: llvm_stack_builtins:
239+
define void @llvm_stack_builtins(i32 %alloc) noredzone {
240+
; CHECK: i32.load $push[[L11:.+]]=, __stack_pointer($pop{{.+}})
241+
; CHECK-NEXT: tee_local $push[[L10:.+]]=, ${{.+}}=, $pop[[L11]]
242+
; CHECK-NEXT: copy_local $[[STACK:.+]]=, $pop[[L10]]
243+
%stack = call i8* @llvm.stacksave()
244+
245+
; Ensure we don't reassign the stacksave local
246+
; CHECK-NOT: $[[STACK]]=
247+
%dynamic = alloca i32, i32 %alloc
248+
249+
; CHECK: i32.store $drop=, __stack_pointer($pop{{.+}}), $[[STACK]]
250+
call void @llvm.stackrestore(i8* %stack)
251+
252+
ret void
253+
}
254+
255+
; Not actually using the alloca'd variables exposed an issue with register
256+
; stackification, where copying the stack pointer into the frame pointer was
257+
; moved after the stack pointer was updated for the dynamic alloca.
258+
; CHECK-LABEL: dynamic_alloca_nouse:
259+
define void @dynamic_alloca_nouse(i32 %alloc) noredzone {
260+
; CHECK: i32.load $push[[L11:.+]]=, __stack_pointer($pop{{.+}})
261+
; CHECK-NEXT: tee_local $push[[L10:.+]]=, ${{.+}}=, $pop[[L11]]
262+
; CHECK-NEXT: copy_local $[[FP:.+]]=, $pop[[L10]]
263+
%dynamic = alloca i32, i32 %alloc
264+
265+
; CHECK-NOT: $[[FP]]=,
266+
267+
; CHECK: i32.store $drop=, __stack_pointer($pop{{.+}}), $[[FP]]
268+
ret void
269+
}
270+
235271
; The use of the alloca in a phi causes a CopyToReg DAG node to be generated,
236272
; which has to have special handling because CopyToReg can't have a FI operand
237273
; CHECK-LABEL: copytoreg_fi:

0 commit comments

Comments
 (0)