mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[WebAssembly] Disable the store-results optimization.
The WebAssemly spec removing the return value from store instructions, so remove the associated optimization from LLVM. This patch leaves the store instruction operands in place for now, so stores now always write to "$drop"; these will be removed in a seperate patch. llvm-svn: 279100
This commit is contained in:
parent
6e2f9dbe22
commit
1386262329
@ -139,15 +139,6 @@ static bool ReplaceDominatedUses(MachineBasicBlock &MBB, MachineInstr &MI,
|
||||
return Changed;
|
||||
}
|
||||
|
||||
static bool optimizeStore(MachineBasicBlock &MBB, MachineInstr &MI,
|
||||
const MachineRegisterInfo &MRI,
|
||||
MachineDominatorTree &MDT,
|
||||
LiveIntervals &LIS) {
|
||||
unsigned ToReg = MI.getOperand(0).getReg();
|
||||
unsigned FromReg = MI.getOperand(WebAssembly::StoreValueOperandNo).getReg();
|
||||
return ReplaceDominatedUses(MBB, MI, FromReg, ToReg, MRI, MDT, LIS);
|
||||
}
|
||||
|
||||
static bool optimizeCall(MachineBasicBlock &MBB, MachineInstr &MI,
|
||||
const MachineRegisterInfo &MRI,
|
||||
MachineDominatorTree &MDT,
|
||||
@ -202,17 +193,6 @@ bool WebAssemblyStoreResults::runOnMachineFunction(MachineFunction &MF) {
|
||||
switch (MI.getOpcode()) {
|
||||
default:
|
||||
break;
|
||||
case WebAssembly::STORE8_I32:
|
||||
case WebAssembly::STORE16_I32:
|
||||
case WebAssembly::STORE8_I64:
|
||||
case WebAssembly::STORE16_I64:
|
||||
case WebAssembly::STORE32_I64:
|
||||
case WebAssembly::STORE_F32:
|
||||
case WebAssembly::STORE_F64:
|
||||
case WebAssembly::STORE_I32:
|
||||
case WebAssembly::STORE_I64:
|
||||
Changed |= optimizeStore(MBB, MI, MRI, MDT, LIS);
|
||||
break;
|
||||
case WebAssembly::CALL_I32:
|
||||
case WebAssembly::CALL_I64:
|
||||
Changed |= optimizeCall(MBB, MI, MRI, MDT, LIS, TLI, LibInfo);
|
||||
|
@ -28,13 +28,13 @@ define void @byval_arg(%SmallStruct* %ptr) {
|
||||
; CHECK: i32.const $push[[L1:.+]]=, 0
|
||||
; CHECK-NEXT: i32.load $push[[L2:.+]]=, __stack_pointer($pop[[L1]])
|
||||
; CHECK-NEXT: i32.const $push[[L3:.+]]=, 16
|
||||
; CHECK-NEXT: i32.sub $push[[L10:.+]]=, $pop[[L2]], $pop[[L3]]
|
||||
; CHECK-NEXT: i32.sub $push[[L11:.+]]=, $pop[[L2]], $pop[[L3]]
|
||||
; Ensure SP is stored back before the call
|
||||
; CHECK-NEXT: i32.store $push[[L12:.+]]=, __stack_pointer($pop[[L4]]), $pop[[L10]]{{$}}
|
||||
; CHECK-NEXT: tee_local $push[[L11:.+]]=, $[[SP:.+]]=, $pop[[L12]]{{$}}
|
||||
; CHECK-NEXT: tee_local $push[[L10:.+]]=, $[[SP:.+]]=, $pop[[L11]]{{$}}
|
||||
; CHECK-NEXT: i32.store $drop=, __stack_pointer($pop[[L4]]), $pop[[L10]]{{$}}
|
||||
; Copy the SmallStruct argument to the stack (SP+12, original SP-4)
|
||||
; CHECK-NEXT: i32.load $push[[L0:.+]]=, 0($0)
|
||||
; CHECK-NEXT: i32.store $drop=, 12($pop[[L11]]), $pop[[L0]]
|
||||
; CHECK-NEXT: i32.store $drop=, 12($[[SP]]), $pop[[L0]]
|
||||
; Pass a pointer to the stack slot to the function
|
||||
; CHECK-NEXT: i32.const $push[[L5:.+]]=, 12{{$}}
|
||||
; CHECK-NEXT: i32.add $push[[ARG:.+]]=, $[[SP]], $pop[[L5]]{{$}}
|
||||
@ -54,12 +54,12 @@ define void @byval_arg_align8(%SmallStruct* %ptr) {
|
||||
; CHECK: .param i32
|
||||
; Don't check the entire SP sequence, just enough to get the alignment.
|
||||
; CHECK: i32.const $push[[L1:.+]]=, 16
|
||||
; CHECK-NEXT: i32.sub $push[[L10:.+]]=, {{.+}}, $pop[[L1]]
|
||||
; CHECK-NEXT: i32.store $push[[L12:.+]]=, __stack_pointer($pop{{.+}}), $pop[[L10]]{{$}}
|
||||
; CHECK-NEXT: tee_local $push[[L11:.+]]=, $[[SP:.+]]=, $pop[[L12]]{{$}}
|
||||
; CHECK-NEXT: i32.sub $push[[L11:.+]]=, {{.+}}, $pop[[L1]]
|
||||
; CHECK-NEXT: tee_local $push[[L10:.+]]=, $[[SP:.+]]=, $pop[[L11]]{{$}}
|
||||
; CHECK-NEXT: i32.store $drop=, __stack_pointer($pop{{.+}}), $pop[[L10]]{{$}}
|
||||
; Copy the SmallStruct argument to the stack (SP+8, original SP-8)
|
||||
; CHECK-NEXT: i32.load $push[[L0:.+]]=, 0($0){{$}}
|
||||
; CHECK-NEXT: i32.store $drop=, 8($pop[[L11]]), $pop[[L0]]{{$}}
|
||||
; CHECK-NEXT: i32.store $drop=, 8($[[SP]]), $pop[[L0]]{{$}}
|
||||
; Pass a pointer to the stack slot to the function
|
||||
; CHECK-NEXT: i32.const $push[[L5:.+]]=, 8{{$}}
|
||||
; CHECK-NEXT: i32.add $push[[ARG:.+]]=, $[[SP]], $pop[[L5]]{{$}}
|
||||
@ -73,9 +73,9 @@ define void @byval_arg_double(%AlignedStruct* %ptr) {
|
||||
; CHECK: .param i32
|
||||
; Subtract 16 from SP (SP is 16-byte aligned)
|
||||
; CHECK: i32.const $push[[L1:.+]]=, 16
|
||||
; CHECK-NEXT: i32.sub $push[[L12:.+]]=, {{.+}}, $pop[[L1]]
|
||||
; CHECK-NEXT: i32.store $push[[L15:.+]]=, {{.+}}, $pop[[L12]]
|
||||
; CHECK-NEXT: tee_local $push[[L14:.+]]=, $[[SP:.+]]=, $pop[[L15]]
|
||||
; CHECK-NEXT: i32.sub $push[[L14:.+]]=, {{.+}}, $pop[[L1]]
|
||||
; CHECK-NEXT: tee_local $push[[L13:.+]]=, $[[SP:.+]]=, $pop[[L14]]
|
||||
; CHECK-NEXT: i32.store $drop=, {{.+}}, $pop[[L13]]
|
||||
; Copy the AlignedStruct argument to the stack (SP+0, original SP-16)
|
||||
; Just check the last load/store pair of the memcpy
|
||||
; CHECK: i64.load $push[[L4:.+]]=, 0($0)
|
||||
@ -117,10 +117,11 @@ define void @byval_empty_callee(%EmptyStruct* byval %ptr) {
|
||||
; CHECK: i32.const $push[[L1:.+]]=, 0
|
||||
; CHECK-NEXT: i32.load $push[[L2:.+]]=, __stack_pointer($pop[[L1]])
|
||||
; CHECK-NEXT: i32.const $push[[L3:.+]]=, 131072
|
||||
; CHECK-NEXT: i32.sub $push[[L8:.+]]=, $pop[[L2]], $pop[[L3]]
|
||||
; CHECK-NEXT: i32.store $push[[L12:.+]]=, __stack_pointer($pop[[L4]]), $pop[[L8]]{{$}}
|
||||
; CHECK-NEXT: i32.sub $push[[L11:.+]]=, $pop[[L2]], $pop[[L3]]
|
||||
; CHECK-NEXT: tee_local $push[[L10:.+]]=, $[[SP:.+]]=, $pop[[L11]]{{$}}
|
||||
; CHECK-NEXT: i32.store $drop=, __stack_pointer($pop[[L4]]), $pop[[L10]]{{$}}
|
||||
; CHECK-NEXT: i32.const $push[[L0:.+]]=, 131072
|
||||
; CHECK-NEXT: i32.call $push[[L11:.+]]=, memcpy@FUNCTION, $pop{{.+}}, ${{.+}}, $pop{{.+}}
|
||||
; CHECK-NEXT: i32.call $push[[L11:.+]]=, memcpy@FUNCTION, $[[SP]], ${{.+}}, $pop{{.+}}
|
||||
; CHECK-NEXT: tee_local $push[[L9:.+]]=, $[[SP:.+]]=, $pop[[L11]]{{$}}
|
||||
; CHECK-NEXT: call big_byval_callee@FUNCTION,
|
||||
%big = type [131072 x i8]
|
||||
|
@ -207,12 +207,12 @@ exit:
|
||||
; CHECK: block{{$}}
|
||||
; CHECK: br_if 0, $1{{$}}
|
||||
; CHECK: .LBB4_2:
|
||||
; CHECK: return ${{[0-9]+}}{{$}}
|
||||
; CHECK: return
|
||||
; OPT-LABEL: triangle:
|
||||
; OPT: block{{$}}
|
||||
; OPT: br_if 0, $1{{$}}
|
||||
; OPT: .LBB4_2:
|
||||
; OPT: return ${{[0-9]+}}{{$}}
|
||||
; OPT: return
|
||||
define i32 @triangle(i32* %p, i32 %a) {
|
||||
entry:
|
||||
%c = icmp eq i32 %a, 0
|
||||
@ -329,7 +329,7 @@ exit:
|
||||
; CHECK: br_if 0, $1{{$}}
|
||||
; CHECK: .LBB9_3:
|
||||
; CHECK: .LBB9_4:
|
||||
; CHECK: return ${{[0-9]+}}{{$}}
|
||||
; CHECK: return
|
||||
; OPT-LABEL: doubletriangle:
|
||||
; OPT: block{{$}}
|
||||
; OPT: br_if 0, $0{{$}}
|
||||
@ -337,7 +337,7 @@ exit:
|
||||
; OPT: br_if 0, $1{{$}}
|
||||
; OPT: .LBB9_3:
|
||||
; OPT: .LBB9_4:
|
||||
; OPT: return ${{[0-9]+}}{{$}}
|
||||
; OPT: return
|
||||
define i32 @doubletriangle(i32 %a, i32 %b, i32* %p) {
|
||||
entry:
|
||||
%c = icmp eq i32 %a, 0
|
||||
@ -965,6 +965,7 @@ bb6:
|
||||
; CHECK: br_if 0, {{[^,]+}}{{$}}
|
||||
; CHECK-NOT: block
|
||||
; CHECK: block{{$}}
|
||||
; CHECK-NEXT: i32.const
|
||||
; CHECK-NEXT: br_if 0, {{[^,]+}}{{$}}
|
||||
; CHECK-NOT: block
|
||||
; CHECK: br_if 2, {{[^,]+}}{{$}}
|
||||
@ -996,7 +997,8 @@ bb6:
|
||||
; OPT: br_if 0, $pop{{[0-9]+}}{{$}}
|
||||
; OPT-NOT: block
|
||||
; OPT: block{{$}}
|
||||
; OPT-NEXT: br_if 0, $0{{$}}
|
||||
; OPT-NEXT: i32.const
|
||||
; OPT-NEXT: br_if 0, {{[^,]+}}{{$}}
|
||||
; OPT-NOT: block
|
||||
; OPT: br_if 2, {{[^,]+}}{{$}}
|
||||
; OPT-NEXT: .LBB20_3:
|
||||
|
@ -398,7 +398,8 @@ define void @aggregate_load_store({i32,i32,i32,i32}* %p, {i32,i32,i32,i32}* %q)
|
||||
|
||||
; CHECK-LABEL: aggregate_return:
|
||||
; CHECK: i64.const $push[[L0:[0-9]+]]=, 0{{$}}
|
||||
; CHECK: i64.store $push[[L1:[0-9]+]]=, 8($0):p2align=2, $pop[[L0]]{{$}}
|
||||
; CHECK: i64.store $drop=, 8($0):p2align=2, $pop[[L0]]{{$}}
|
||||
; CHECK: i64.const $push[[L1:[0-9]+]]=, 0{{$}}
|
||||
; CHECK: i64.store $drop=, 0($0):p2align=2, $pop[[L1]]{{$}}
|
||||
define {i32,i32,i32,i32} @aggregate_return() {
|
||||
ret {i32,i32,i32,i32} zeroinitializer
|
||||
@ -409,8 +410,10 @@ define {i32,i32,i32,i32} @aggregate_return() {
|
||||
|
||||
; CHECK-LABEL: aggregate_return_without_merge:
|
||||
; CHECK: i32.const $push[[L0:[0-9]+]]=, 0{{$}}
|
||||
; CHECK: i32.store8 $push[[L1:[0-9]+]]=, 14($0), $pop[[L0]]{{$}}
|
||||
; CHECK: i32.store16 $push[[L2:[0-9]+]]=, 12($0), $pop[[L1]]{{$}}
|
||||
; CHECK: i32.store8 $drop=, 14($0), $pop[[L0]]{{$}}
|
||||
; CHECK: i32.const $push[[L1:[0-9]+]]=, 0{{$}}
|
||||
; CHECK: i32.store16 $drop=, 12($0), $pop[[L1]]{{$}}
|
||||
; CHECK: i32.const $push[[L2:[0-9]+]]=, 0{{$}}
|
||||
; CHECK: i32.store $drop=, 8($0), $pop[[L2]]{{$}}
|
||||
; CHECK: i64.const $push[[L3:[0-9]+]]=, 0{{$}}
|
||||
; CHECK: i64.store $drop=, 0($0), $pop[[L3]]{{$}}
|
||||
|
@ -166,7 +166,7 @@ return:
|
||||
; CHECK: side_effects:
|
||||
; CHECK: store
|
||||
; CHECK-NEXT: call
|
||||
; CHECK-NEXT: store
|
||||
; CHECK: store
|
||||
; CHECK-NEXT: call
|
||||
declare void @evoke_side_effects()
|
||||
define hidden void @stackify_store_across_side_effects(double* nocapture %d) {
|
||||
@ -377,9 +377,9 @@ define i32 @no_stackify_call_past_load() {
|
||||
|
||||
; Don't move stores past loads if there may be aliasing
|
||||
; CHECK-LABEL: no_stackify_store_past_load
|
||||
; CHECK: i32.store $[[L0:[0-9]+]]=, 0($1), $0
|
||||
; CHECK: i32.store $drop=, 0($1), $0
|
||||
; CHECK: i32.load {{.*}}, 0($2)
|
||||
; CHECK: i32.call {{.*}}, callee@FUNCTION, $[[L0]]{{$}}
|
||||
; 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
|
||||
@ -389,8 +389,8 @@ define i32 @no_stackify_store_past_load(i32 %a, i32* %p1, i32* %p2) {
|
||||
|
||||
; 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.store $drop=, 0($1), $0
|
||||
; CHECK: i32.call {{.*}}, callee@FUNCTION, $0
|
||||
; CHECK: i32.load $push{{.*}}, 0($2)
|
||||
; CHECK: return $pop
|
||||
define i32 @store_past_invar_load(i32 %a, i32* %p1, i32* dereferenceable(4) %p2) {
|
||||
|
@ -1,72 +0,0 @@
|
||||
; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
|
||||
|
||||
; Test that the wasm-store-results pass makes users of stored values use the
|
||||
; result of store expressions to reduce get_local/set_local traffic.
|
||||
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
||||
target triple = "wasm32-unknown-unknown"
|
||||
|
||||
; CHECK-LABEL: single_block:
|
||||
; CHECK-NOT: local
|
||||
; CHECK: i32.const $push{{[0-9]+}}=, 0{{$}}
|
||||
; CHECK: i32.store $push[[STORE:[0-9]+]]=, 0($0), $pop{{[0-9]+}}{{$}}
|
||||
; CHECK: return $pop[[STORE]]{{$}}
|
||||
define i32 @single_block(i32* %p) {
|
||||
entry:
|
||||
store i32 0, i32* %p
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
; Test interesting corner cases for wasm-store-results, in which the operand of
|
||||
; a store ends up getting used by a phi, which needs special handling in the
|
||||
; dominance test, since phis use their operands on their incoming edges.
|
||||
|
||||
%class.Vec3 = type { float, float, float }
|
||||
|
||||
@pos = global %class.Vec3 zeroinitializer, align 4
|
||||
|
||||
; CHECK-LABEL: foo:
|
||||
; CHECK: i32.store $drop=, pos($pop{{[0-9]+}}), $pop{{[0-9]+}}{{$}}
|
||||
define void @foo() {
|
||||
for.body.i:
|
||||
br label %for.body5.i
|
||||
|
||||
for.body5.i:
|
||||
%i.0168.i = phi i32 [ 0, %for.body.i ], [ %inc.i, %for.body5.i ]
|
||||
%conv6.i = sitofp i32 %i.0168.i to float
|
||||
store volatile float 0.0, float* getelementptr inbounds (%class.Vec3, %class.Vec3* @pos, i32 0, i32 0)
|
||||
%inc.i = add nuw nsw i32 %i.0168.i, 1
|
||||
%exitcond.i = icmp eq i32 %inc.i, 256
|
||||
br i1 %exitcond.i, label %for.cond.cleanup4.i, label %for.body5.i
|
||||
|
||||
for.cond.cleanup4.i:
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: bar:
|
||||
; CHECK: i32.store $drop=, pos($pop{{[0-9]+}}), $pop{{[0-9]+}}{{$}}
|
||||
define void @bar() {
|
||||
for.body.i:
|
||||
br label %for.body5.i
|
||||
|
||||
for.body5.i:
|
||||
%i.0168.i = phi float [ 0.0, %for.body.i ], [ %inc.i, %for.body5.i ]
|
||||
store volatile float 0.0, float* getelementptr inbounds (%class.Vec3, %class.Vec3* @pos, i32 0, i32 0)
|
||||
%inc.i = fadd float %i.0168.i, 1.0
|
||||
%exitcond.i = fcmp oeq float %inc.i, 256.0
|
||||
br i1 %exitcond.i, label %for.cond.cleanup4.i, label %for.body5.i
|
||||
|
||||
for.cond.cleanup4.i:
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: fi_ret:
|
||||
; CHECK: i32.store $push0=,
|
||||
; CHECK: return $pop0{{$}}
|
||||
define hidden i8* @fi_ret(i8** %addr) {
|
||||
entry:
|
||||
%buf = alloca [27 x i8], align 16
|
||||
%0 = getelementptr inbounds [27 x i8], [27 x i8]* %buf, i32 0, i32 0
|
||||
store i8* %0, i8** %addr
|
||||
ret i8* %0
|
||||
}
|
@ -14,12 +14,12 @@ define void @alloca32() noredzone {
|
||||
; CHECK: i32.const $push[[L1:.+]]=, 0{{$}}
|
||||
; CHECK-NEXT: i32.load $push[[L2:.+]]=, __stack_pointer($pop[[L1]])
|
||||
; CHECK-NEXT: i32.const $push[[L3:.+]]=, 16
|
||||
; CHECK-NEXT: i32.sub $push[[L8:.+]]=, $pop[[L2]], $pop[[L3]]
|
||||
; CHECK-NEXT: i32.store $push[[L10:.+]]=, __stack_pointer($pop[[L4]]), $pop[[L8]]{{$}}
|
||||
; CHECK-NEXT: tee_local $push[[L9:.+]]=, $[[SP:.+]]=, $pop[[L10]]{{$}}
|
||||
; CHECK-NEXT: i32.sub $push[[L9:.+]]=, $pop[[L2]], $pop[[L3]]
|
||||
; CHECK-NEXT: tee_local $push[[L8:.+]]=, $[[SP:.+]]=, $pop[[L9]]{{$}}
|
||||
; CHECK-NEXT: i32.store $drop=, __stack_pointer($pop[[L4]]), $pop[[L8]]{{$}}
|
||||
%retval = alloca i32
|
||||
; CHECK: i32.const $push[[L0:.+]]=, 0
|
||||
; CHECK: i32.store {{.*}}=, 12($pop[[L9]]), $pop[[L0]]
|
||||
; CHECK: i32.store $drop=, 12($[[SP]]), $pop[[L0]]
|
||||
store i32 0, i32* %retval
|
||||
; CHECK: i32.const $push[[L6:.+]]=, 0
|
||||
; CHECK-NEXT: i32.const $push[[L5:.+]]=, 16
|
||||
@ -51,43 +51,45 @@ define void @alloca3264() {
|
||||
; CHECK-LABEL: allocarray:
|
||||
; CHECK: .local i32{{$}}
|
||||
define void @allocarray() {
|
||||
; CHECK: i32.const $push[[L7:.+]]=, 0{{$}}
|
||||
; CHECK: i32.const $push[[L4:.+]]=, 0{{$}}
|
||||
; CHECK-NEXT: i32.load $push[[L5:.+]]=, __stack_pointer($pop[[L4]])
|
||||
; CHECK-NEXT: i32.const $push[[L6:.+]]=, 144{{$}}
|
||||
; CHECK-NEXT: i32.sub $push[[L11:.+]]=, $pop[[L5]], $pop[[L6]]
|
||||
; CHECK-NEXT: i32.store ${{.+}}=, __stack_pointer($pop[[L7]]), $pop[[L11]]
|
||||
; CHECK: i32.const $push[[L6:.+]]=, 0{{$}}
|
||||
; CHECK: i32.const $push[[L3:.+]]=, 0{{$}}
|
||||
; CHECK-NEXT: i32.load $push[[L4:.+]]=, __stack_pointer($pop[[L3]])
|
||||
; CHECK-NEXT: i32.const $push[[L5:.+]]=, 144{{$}}
|
||||
; CHECK-NEXT: i32.sub $push[[L12:.+]]=, $pop[[L4]], $pop[[L5]]
|
||||
; CHECK-NEXT: tee_local $push[[L11:.+]]=, $0=, $pop[[L12]]
|
||||
; CHECK-NEXT: i32.store $drop=, __stack_pointer($pop[[L6]]), $pop[[L11]]
|
||||
%r = alloca [33 x i32]
|
||||
|
||||
; CHECK: i32.const $push{{.+}}=, 24
|
||||
; CHECK-NEXT: i32.add $push[[L3:.+]]=, $[[SP]], $pop{{.+}}
|
||||
; CHECK-NEXT: i32.const $push[[L1:.+]]=, 1{{$}}
|
||||
; CHECK-NEXT: i32.store $push[[L0:.+]]=, 0($pop[[L3]]), $pop[[L1]]{{$}}
|
||||
; CHECK-NEXT: i32.store $drop=, 12(${{.+}}), $pop[[L0]]{{$}}
|
||||
; CHECK-NEXT: i32.store $drop=, 0($pop[[L3]]), $pop[[L1]]{{$}}
|
||||
; CHECK-NEXT: i32.const $push[[L10:.+]]=, 1{{$}}
|
||||
; CHECK-NEXT: i32.store $drop=, 12(${{.+}}), $pop[[L10]]{{$}}
|
||||
%p = getelementptr [33 x i32], [33 x i32]* %r, i32 0, i32 0
|
||||
store i32 1, i32* %p
|
||||
%p2 = getelementptr [33 x i32], [33 x i32]* %r, i32 0, i32 3
|
||||
store i32 1, i32* %p2
|
||||
|
||||
; CHECK: i32.const $push[[L10:.+]]=, 0{{$}}
|
||||
; CHECK-NEXT: i32.const $push[[L8:.+]]=, 144
|
||||
; CHECK-NEXT: i32.add $push[[L19:.+]]=, $[[SP]], $pop[[L8]]
|
||||
; CHECK-NEXT: i32.store $drop=, __stack_pointer($pop[[L10]]), $pop[[L9]]
|
||||
; CHECK: i32.const $push[[L9:.+]]=, 0{{$}}
|
||||
; CHECK-NEXT: i32.const $push[[L7:.+]]=, 144
|
||||
; CHECK-NEXT: i32.add $push[[L8:.+]]=, $[[SP]], $pop[[L7]]
|
||||
; CHECK-NEXT: i32.store $drop=, __stack_pointer($pop[[L9]]), $pop[[L8]]
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: non_mem_use
|
||||
define void @non_mem_use(i8** %addr) {
|
||||
; CHECK: i32.const $push[[L1:.+]]=, 48
|
||||
; CHECK-NEXT: i32.sub $push[[L11:.+]]=, {{.+}}, $pop[[L1]]
|
||||
; CHECK-NEXT: i32.store $[[SP:.+]]=, {{.+}}, $pop[[L11]]
|
||||
; CHECK: i32.const $push[[L2:.+]]=, 48
|
||||
; CHECK-NEXT: i32.sub $push[[L12:.+]]=, {{.+}}, $pop[[L2]]
|
||||
; CHECK-NEXT: tee_local $push[[L11:.+]]=, $[[SP:.+]]=, $pop[[L12]]
|
||||
; CHECK-NEXT: i32.store $drop=, {{.+}}, $pop[[L11]]
|
||||
%buf = alloca [27 x i8], align 16
|
||||
%r = alloca i64
|
||||
%r2 = alloca i64
|
||||
; %r is at SP+8
|
||||
; CHECK: tee_local $push[[L12:.+]]=, $[[SP:.+]]=, $pop{{.+}}
|
||||
; CHECK: i32.const $push[[OFF:.+]]=, 8
|
||||
; CHECK-NEXT: i32.add $push[[ARG1:.+]]=, $pop[[L12]], $pop[[OFF]]
|
||||
; CHECK-NEXT: i32.add $push[[ARG1:.+]]=, $[[SP]], $pop[[OFF]]
|
||||
; CHECK-NEXT: call ext_func@FUNCTION, $pop[[ARG1]]
|
||||
call void @ext_func(i64* %r)
|
||||
; %r2 is at SP+0, no add needed
|
||||
@ -97,7 +99,7 @@ define void @non_mem_use(i8** %addr) {
|
||||
; %buf is at SP+16
|
||||
; CHECK: i32.const $push[[OFF:.+]]=, 16
|
||||
; CHECK-NEXT: i32.add $push[[VAL:.+]]=, $[[SP]], $pop[[OFF]]
|
||||
; CHECK-NEXT: i32.store {{.*}}=, 0($0), $pop[[VAL]]
|
||||
; CHECK-NEXT: i32.store $drop=, 0($0), $pop[[VAL]]
|
||||
%gep = getelementptr inbounds [27 x i8], [27 x i8]* %buf, i32 0, i32 0
|
||||
store i8* %gep, i8** %addr
|
||||
ret void
|
||||
@ -106,15 +108,16 @@ define void @non_mem_use(i8** %addr) {
|
||||
; CHECK-LABEL: allocarray_inbounds:
|
||||
; CHECK: .local i32{{$}}
|
||||
define void @allocarray_inbounds() {
|
||||
; CHECK: i32.const $push[[L6:.+]]=, 0{{$}}
|
||||
; CHECK: i32.const $push[[L3:.+]]=, 0{{$}}
|
||||
; CHECK-NEXT: i32.load $push[[L4:.+]]=, __stack_pointer($pop[[L3]])
|
||||
; CHECK-NEXT: i32.const $push[[L5:.+]]=, 32{{$}}
|
||||
; CHECK-NEXT: i32.sub $push[[L10:.+]]=, $pop[[L4]], $pop[[L5]]
|
||||
; CHECK-NEXT: i32.store ${{.+}}=, __stack_pointer($pop[[L6]]), $pop[[L10]]{{$}}
|
||||
; CHECK: i32.const $push[[L5:.+]]=, 0{{$}}
|
||||
; CHECK: i32.const $push[[L2:.+]]=, 0{{$}}
|
||||
; CHECK-NEXT: i32.load $push[[L3:.+]]=, __stack_pointer($pop[[L2]])
|
||||
; CHECK-NEXT: i32.const $push[[L4:.+]]=, 32{{$}}
|
||||
; CHECK-NEXT: i32.sub $push[[L11:.+]]=, $pop[[L3]], $pop[[L4]]
|
||||
; CHECK-NEXT: tee_local $push[[L10:.+]]=, $[[SP:.+]]=, $pop[[L11]]
|
||||
; CHECK-NEXT: i32.store $drop=, __stack_pointer($pop[[L5]]), $pop[[L10]]{{$}}
|
||||
%r = alloca [5 x i32]
|
||||
; CHECK: i32.const $push[[L3:.+]]=, 1
|
||||
; CHECK-DAG: i32.store $push{{.*}}=, 24(${{.+}}), $pop[[L3]]
|
||||
; CHECK-DAG: i32.store $drop=, 24(${{.+}}), $pop[[L3]]
|
||||
%p = getelementptr inbounds [5 x i32], [5 x i32]* %r, i32 0, i32 0
|
||||
store i32 1, i32* %p
|
||||
; This store should have both the GEP and the FI folded into it.
|
||||
@ -170,14 +173,13 @@ define void @dynamic_alloca_redzone(i32 %alloc) {
|
||||
; CHECK-LABEL: dynamic_static_alloca:
|
||||
define void @dynamic_static_alloca(i32 %alloc) noredzone {
|
||||
; Decrement SP in the prolog by the static amount and writeback to memory.
|
||||
; CHECK: i32.const $push[[L7:.+]]=, 0{{$}}
|
||||
; CHECK: i32.const $push[[L11:.+]]=, 0{{$}}
|
||||
; CHECK: i32.const $push[[L8:.+]]=, 0{{$}}
|
||||
; CHECK: i32.const $push[[L9:.+]]=, 0{{$}}
|
||||
; CHECK-NEXT: i32.load $push[[L10:.+]]=, __stack_pointer($pop[[L9]])
|
||||
; CHECK-NEXT: i32.const $push[[L11:.+]]=, 16
|
||||
; CHECK-NEXT: i32.sub $push[[L20:.+]]=, $pop[[L10]], $pop[[L11]]
|
||||
; CHECK-NEXT: i32.load $push[[L9:.+]]=, __stack_pointer($pop[[L8]])
|
||||
; CHECK-NEXT: i32.const $push[[L10:.+]]=, 16
|
||||
; CHECK-NEXT: i32.sub $push[[L20:.+]]=, $pop[[L9]], $pop[[L10]]
|
||||
; CHECK-NEXT: tee_local $push[[L19:.+]]=, $[[FP:.+]]=, $pop[[L20]]
|
||||
; CHECK: i32.store $push[[L0:.+]]=, __stack_pointer($pop{{.+}}), $pop{{.+}}
|
||||
; CHECK: i32.store $drop=, __stack_pointer($pop{{.+}}), $pop{{.+}}
|
||||
; Decrement SP in the body by the dynamic amount.
|
||||
; CHECK: i32.sub
|
||||
; Writeback to memory.
|
||||
|
Loading…
Reference in New Issue
Block a user