From 120265029b7c9ae8778fa83c8b0fe82f7ab84ceb Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 28 Jan 2016 03:59:09 +0000 Subject: [PATCH] [WebAssembly] Don't stackify a register def past a get_local use in the same tree. llvm-svn: 259013 --- .../WebAssembly/WebAssemblyRegStackify.cpp | 14 ++++++++++++- test/CodeGen/WebAssembly/reg-stackify.ll | 21 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp b/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp index 3377ca0979d..15da0d175f3 100644 --- a/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp +++ b/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp @@ -326,6 +326,17 @@ public: const RangeTy &Range = Worklist.back(); return Range.begin() != Range.end() && Range.begin()->getParent() == Instr; } + + /// Test whether the given register is present on the stack, indicating an + /// operand in the tree that we haven't visited yet. Moving a definition of + /// Reg to a point in the tree after that would change its value. + bool IsOnStack(unsigned Reg) const { + for (const RangeTy &Range : Worklist) + for (const MachineOperand &MO : Range) + if (MO.isReg() && MO.getReg() == Reg) + return true; + return false; + } }; /// State to keep track of whether commuting is in flight or whether it's been @@ -467,7 +478,8 @@ bool WebAssemblyRegStackify::runOnMachineFunction(MachineFunction &MF) { // supports intra-block moves) and it's MachineSink's job to catch all // the sinking opportunities anyway. bool SameBlock = Def->getParent() == &MBB; - bool CanMove = SameBlock && IsSafeToMove(Def, Insert, AA, LIS, MRI); + bool CanMove = SameBlock && IsSafeToMove(Def, Insert, AA, LIS, MRI) && + !TreeWalker.IsOnStack(Reg); if (CanMove && MRI.hasOneUse(Reg)) { Insert = MoveForSingleUse(Reg, Def, MBB, Insert, LIS, MFI); } else if (Def->isAsCheapAsAMove() && diff --git a/test/CodeGen/WebAssembly/reg-stackify.ll b/test/CodeGen/WebAssembly/reg-stackify.ll index 0083b410626..d745e67caad 100644 --- a/test/CodeGen/WebAssembly/reg-stackify.ll +++ b/test/CodeGen/WebAssembly/reg-stackify.ll @@ -244,4 +244,25 @@ define i32 @commute() { ret i32 %add3 } +; Don't stackify a register when it would move a the def of the register past +; an implicit get_local for the register. + +; CHECK-LABEL: no_stackify_past_use: +; CHECK: i32.call $1=, callee@FUNCTION, $0 +; CHECK: i32.const $push0=, 1 +; CHECK: i32.add $push1=, $0, $pop0 +; CHECK: i32.call $push2=, callee@FUNCTION, $pop1 +; CHECK: i32.add $push3=, $1, $pop2 +; CHECK: i32.mul $push4=, $1, $pop3 +; CHECK: return $pop4 +declare i32 @callee(i32) +define i32 @no_stackify_past_use(i32 %arg) { + %tmp1 = call i32 @callee(i32 %arg) + %tmp2 = add i32 %arg, 1 + %tmp3 = call i32 @callee(i32 %tmp2) + %tmp5 = add i32 %tmp3, %tmp1 + %tmp6 = mul i32 %tmp5, %tmp1 + ret i32 %tmp6 +} + !0 = !{}