diff options
| -rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp | 1 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WebAssembly/reg-stackify.ll | 39 |
2 files changed, 40 insertions, 0 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp index e23066c1a92..9108b4206cf 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp @@ -129,6 +129,7 @@ static bool IsSafeToMove(const MachineInstr *Def, const MachineInstr *Insert, return false; } + SawStore = Def->isCall() || Def->mayStore(); // Check for memory dependencies and side effects. for (--I; I != D; --I) SawSideEffects |= !I->isSafeToMove(&AA, SawStore); diff --git a/llvm/test/CodeGen/WebAssembly/reg-stackify.ll b/llvm/test/CodeGen/WebAssembly/reg-stackify.ll index 7cc467cc9cd..82e5d43ce22 100644 --- a/llvm/test/CodeGen/WebAssembly/reg-stackify.ll +++ b/llvm/test/CodeGen/WebAssembly/reg-stackify.ll @@ -308,4 +308,43 @@ bb21: ; preds = %bb17, %bb5 br label %bb5 } +; Don't move calls past loads +; CHECK-LABEL: no_stackify_call_past_load: +; CHECK: i32.call $0=, red +; CHECK: i32.const $push0=, 0 +; CHECK: i32.load $1=, count($pop0) +@count = hidden global i32 0, align 4 +define i32 @no_stackify_call_past_load() { + %a = call i32 @red() + %b = load i32, i32* @count, align 4 + call i32 @callee(i32 %a) + ret i32 %b + ; use of a +} + +; Don't move stores past loads if there may be aliasing +; CHECK-LABEL: no_stackify_store_past_load +; CHECK: i32.store {{.*}}, 0($1), $0 +; CHECK: i32.load {{.*}}, 0($2) +; CHECK: i32.call {{.*}}, callee@FUNCTION, $0 +define i32 @no_stackify_store_past_load(i32 %a, i32* %p1, i32* %p2) { + store i32 %a, i32* %p1 + %b = load i32, i32* %p2, align 4 + call i32 @callee(i32 %a) + ret i32 %b +} + +; Can still stackify past invariant loads. +; CHECK-LABEL: store_past_invar_load +; CHECK: i32.store $push{{.*}}, 0($1), $0 +; CHECK: i32.call {{.*}}, callee@FUNCTION, $pop +; CHECK: i32.load $push{{.*}}, 0($2) +; CHECK: return $pop +define i32 @store_past_invar_load(i32 %a, i32* %p1, i32* dereferenceable(4) %p2) { + store i32 %a, i32* %p1 + %b = load i32, i32* %p2, !invariant.load !0 + call i32 @callee(i32 %a) + ret i32 %b +} + !0 = !{} |

