1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 11:02:59 +02:00

[WebAssemly] Don't move calls or stores past intervening loads

The register stackifier currently checks for intervening stores (and
loads that may alias them) but doesn't account for the fact that the
instruction being moved may affect intervening loads.

Differential Revision: http://reviews.llvm.org/D17298

llvm-svn: 261014
This commit is contained in:
Derek Schuff 2016-02-16 21:44:19 +00:00
parent e39424112f
commit b9542a8754
2 changed files with 40 additions and 0 deletions

View File

@ -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);

View File

@ -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 = !{}