diff options
Diffstat (limited to 'llvm/test/CodeGen/WebAssembly/reg-stackify.ll')
-rw-r--r-- | llvm/test/CodeGen/WebAssembly/reg-stackify.ll | 198 |
1 files changed, 197 insertions, 1 deletions
diff --git a/llvm/test/CodeGen/WebAssembly/reg-stackify.ll b/llvm/test/CodeGen/WebAssembly/reg-stackify.ll index 7195cd85482..f36014c1395 100644 --- a/llvm/test/CodeGen/WebAssembly/reg-stackify.ll +++ b/llvm/test/CodeGen/WebAssembly/reg-stackify.ll @@ -1,7 +1,11 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-register-codegen-test-mode -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -verify-machineinstrs | FileCheck %s --check-prefix=NOREGS ; Test the register stackifier pass. +; We have two sets of tests, one with registers and implicit locals, and +; a stack / explicit locals based version (NOREGS). + target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" @@ -9,6 +13,8 @@ target triple = "wasm32-unknown-unknown" ; CHECK-LABEL: no0: ; CHECK: return $1{{$}} +; NOREGS-LABEL: no0: +; NOREGS: return{{$}} define i32 @no0(i32* %p, i32* %q) { %t = load i32, i32* %q store i32 0, i32* %p @@ -19,6 +25,8 @@ define i32 @no0(i32* %p, i32* %q) { ; CHECK-LABEL: no1: ; CHECK: return $1{{$}} +; NOREGS-LABEL: no1: +; NOREGS: return{{$}} define i32 @no1(i32* %p, i32* dereferenceable(4) %q) { %t = load volatile i32, i32* %q, !invariant.load !0 store volatile i32 0, i32* %p @@ -29,6 +37,8 @@ define i32 @no1(i32* %p, i32* dereferenceable(4) %q) { ; CHECK-LABEL: yes0: ; CHECK: return $pop{{[0-9]+}}{{$}} +; NOREGS-LABEL: yes0: +; NOREGS: return{{$}} define i32 @yes0(i32* %p, i32* dereferenceable(4) %q) { %t = load i32, i32* %q, !invariant.load !0 store i32 0, i32* %p @@ -39,6 +49,8 @@ define i32 @yes0(i32* %p, i32* dereferenceable(4) %q) { ; CHECK-LABEL: yes1: ; CHECK: return $pop0{{$}} +; NOREGS-LABEL: yes1: +; NOREGS: return{{$}} define i32 @yes1(i32* %q) { %t = load volatile i32, i32* %q ret i32 %t @@ -48,6 +60,8 @@ define i32 @yes1(i32* %q) { ; CHECK-LABEL: sink_trap: ; CHECK: return $pop{{[0-9]+}}{{$}} +; NOREGS-LABEL: sink_trap: +; NOREGS: return{{$}} define i32 @sink_trap(i32 %x, i32 %y, i32* %p) { %t = sdiv i32 %x, %y store volatile i32 0, i32* %p @@ -58,6 +72,8 @@ define i32 @sink_trap(i32 %x, i32 %y, i32* %p) { ; CHECK-LABEL: sink_readnone_call: ; CHECK: return $pop0{{$}} +; NOREGS-LABEL: sink_readnone_call: +; NOREGS: return{{$}} declare i32 @readnone_callee() readnone nounwind define i32 @sink_readnone_call(i32 %x, i32 %y, i32* %p) { %t = call i32 @readnone_callee() @@ -69,6 +85,8 @@ define i32 @sink_readnone_call(i32 %x, i32 %y, i32* %p) { ; CHECK-LABEL: no_sink_readonly_call: ; CHECK: return ${{[0-9]+}}{{$}} +; NOREGS-LABEL: no_sink_readonly_call: +; NOREGS: return{{$}} declare i32 @readonly_callee() readonly nounwind define i32 @no_sink_readonly_call(i32 %x, i32 %y, i32* %p) { %t = call i32 @readonly_callee() @@ -105,6 +123,34 @@ define i32 @no_sink_readonly_call(i32 %x, i32 %y, i32* %p) { ; CHECK-NEXT: end_block{{$}} ; CHECK-NEXT: i32.const $push14=, 1{{$}} ; CHECK-NEXT: return $pop14{{$}} +; NOREGS-LABEL: stack_uses: +; NOREGS: .param i32, i32, i32, i32{{$}} +; NOREGS-NEXT: .result i32{{$}} +; NOREGS-NEXT: block {{$}} +; NOREGS-NEXT: get_local 0{{$}} +; NOREGS-NEXT: i32.const 1{{$}} +; NOREGS-NEXT: i32.lt_s +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: i32.const 2{{$}} +; NOREGS-NEXT: i32.lt_s +; NOREGS-NEXT: i32.xor {{$}} +; NOREGS-NEXT: get_local 2{{$}} +; NOREGS-NEXT: i32.const 1{{$}} +; NOREGS-NEXT: i32.lt_s +; NOREGS-NEXT: get_local 3{{$}} +; NOREGS-NEXT: i32.const 2{{$}} +; NOREGS-NEXT: i32.lt_s +; NOREGS-NEXT: i32.xor {{$}} +; NOREGS-NEXT: i32.xor {{$}} +; NOREGS-NEXT: i32.const 1{{$}} +; NOREGS-NEXT: i32.ne {{$}} +; NOREGS-NEXT: br_if 0{{$}} +; NOREGS-NEXT: i32.const 0{{$}} +; NOREGS-NEXT: return{{$}} +; NOREGS-NEXT: .LBB7_2: +; NOREGS-NEXT: end_block{{$}} +; NOREGS-NEXT: i32.const 1{{$}} +; NOREGS-NEXT: return{{$}} define i32 @stack_uses(i32 %x, i32 %y, i32 %z, i32 %w) { entry: %c = icmp sle i32 %x, 0 @@ -137,6 +183,26 @@ false: ; CHECK-NEXT: .LBB8_3: ; CHECK-NEXT: end_block{{$}} ; CHECK-NEXT: return{{$}} +; NOREGS-LABEL: multiple_uses: +; NOREGS: .param i32, i32, i32{{$}} +; NOREGS: .local i32{{$}} +; NOREGS-NEXT: block {{$}} +; NOREGS-NEXT: get_local 2{{$}} +; NOREGS-NEXT: i32.load 0{{$}} +; NOREGS-NEXT: tee_local 3{{$}} +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: i32.ge_u +; NOREGS-NEXT: br_if 0{{$}} +; NOREGS-NEXT: get_local 3{{$}} +; NOREGS-NEXT: get_local 0{{$}} +; NOREGS-NEXT: i32.lt_u +; NOREGS-NEXT: br_if 0{{$}} +; NOREGS-NEXT: get_local 2{{$}} +; NOREGS-NEXT: get_local 3{{$}} +; NOREGS-NEXT: i32.store 0{{$}} +; NOREGS-NEXT: .LBB8_3: +; NOREGS-NEXT: end_block{{$}} +; NOREGS-NEXT: return{{$}} define void @multiple_uses(i32* %arg0, i32* %arg1, i32* %arg2) nounwind { bb: br label %loop @@ -167,6 +233,11 @@ return: ; CHECK-NEXT: call ; CHECK: store ; CHECK-NEXT: call +; NOREGS: side_effects: +; NOREGS: store +; NOREGS-NEXT: call +; NOREGS: store +; NOREGS-NEXT: call declare void @evoke_side_effects() define hidden void @stackify_store_across_side_effects(double* nocapture %d) { entry: @@ -200,6 +271,41 @@ entry: ; CHECK-NEXT: i32.div_s $push[[L13:[0-9]+]]=, $pop[[L9]], $pop[[L12]]{{$}} ; CHECK-NEXT: i32.div_s $push[[L14:[0-9]+]]=, $pop[[L6]], $pop[[L13]]{{$}} ; CHECK-NEXT: return $pop[[L14]]{{$}} +; NOREGS-LABEL: div_tree: +; NOREGS: .param i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32{{$}} +; NOREGS-NEXT: .result i32{{$}} +; NOREGS-NEXT: get_local 0{{$}} +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: get_local 2{{$}} +; NOREGS-NEXT: get_local 3{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: get_local 4{{$}} +; NOREGS-NEXT: get_local 5{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: get_local 6{{$}} +; NOREGS-NEXT: get_local 7{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: get_local 8{{$}} +; NOREGS-NEXT: get_local 9{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: get_local 10{{$}} +; NOREGS-NEXT: get_local 11{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: get_local 12{{$}} +; NOREGS-NEXT: get_local 13{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: get_local 14{{$}} +; NOREGS-NEXT: get_local 15{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: i32.div_s{{$}} +; NOREGS-NEXT: return{{$}} define i32 @div_tree(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p) { entry: %div = sdiv i32 %a, %b @@ -229,6 +335,16 @@ entry: ; CHECK-NEXT: call use_a@FUNCTION, $pop[[NUM1]]{{$}} ; CHECK-NEXT: call use_b@FUNCTION, $[[NUM2]]{{$}} ; CHECK-NEXT: return{{$}} +; NOREGS-LABEL: simple_multiple_use: +; NOREGS: .param i32, i32{{$}} +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: get_local 0{{$}} +; NOREGS-NEXT: i32.mul +; NOREGS-NEXT: tee_local 1{{$}} +; NOREGS-NEXT: call use_a@FUNCTION{{$}} +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: call use_b@FUNCTION{{$}} +; NOREGS-NEXT: return{{$}} declare void @use_a(i32) declare void @use_b(i32) define void @simple_multiple_use(i32 %x, i32 %y) { @@ -246,6 +362,15 @@ define void @simple_multiple_use(i32 %x, i32 %y) { ; CHECK-NEXT: tee_local $push[[NUM1:[0-9]+]]=, $[[NUM2:[0-9]+]]=, $pop[[NUM0]]{{$}} ; CHECK-NEXT: call use_2@FUNCTION, $pop[[NUM1]], $[[NUM2]]{{$}} ; CHECK-NEXT: return{{$}} +; NOREGS-LABEL: multiple_uses_in_same_insn: +; NOREGS: .param i32, i32{{$}} +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: get_local 0{{$}} +; NOREGS-NEXT: i32.mul +; NOREGS-NEXT: tee_local 1{{$}} +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: call use_2@FUNCTION{{$}} +; NOREGS-NEXT: return{{$}} declare void @use_2(i32, i32) define void @multiple_uses_in_same_insn(i32 %x, i32 %y) { %mul = mul i32 %y, %x @@ -264,6 +389,15 @@ define void @multiple_uses_in_same_insn(i32 %x, i32 %y) { ; CHECK-NEXT: i32.call $push3=, blue@FUNCTION{{$}} ; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}} ; CHECK-NEXT: return $pop4{{$}} +; NOREGS-LABEL: commute: +; NOREGS-NOT: param +; NOREGS: .result i32{{$}} +; NOREGS-NEXT: i32.call red@FUNCTION{{$}} +; NOREGS-NEXT: i32.call green@FUNCTION{{$}} +; NOREGS-NEXT: i32.add {{$}} +; NOREGS-NEXT: i32.call blue@FUNCTION{{$}} +; NOREGS-NEXT: i32.add {{$}} +; NOREGS-NEXT: return{{$}} declare i32 @red() declare i32 @green() declare i32 @blue() @@ -287,6 +421,19 @@ define i32 @commute() { ; CHECK-NEXT: i32.sub $push3=, $pop2, $1 ; CHECK-NEXT: i32.div_s $push4=, $pop3, $1 ; CHECK-NEXT: return $pop4 +; NOREGS-LABEL: no_stackify_past_use: +; NOREGS: get_local 0{{$}} +; NOREGS-NEXT: i32.call callee@FUNCTION +; NOREGS-NEXT: set_local 1{{$}} +; NOREGS-NEXT: get_local 0{{$}} +; NOREGS-NEXT: i32.const 1 +; NOREGS-NEXT: i32.add +; NOREGS-NEXT: i32.call callee@FUNCTION +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: i32.sub +; NOREGS-NEXT: get_local 1{{$}} +; NOREGS-NEXT: i32.div_s +; NOREGS-NEXT: return declare i32 @callee(i32) define i32 @no_stackify_past_use(i32 %arg) { %tmp1 = call i32 @callee(i32 %arg) @@ -309,6 +456,18 @@ define i32 @no_stackify_past_use(i32 %arg) { ; CHECK: i32.add $push3=, $1, $pop2 ; CHECK: i32.mul $push4=, $pop[[L1]], $pop3 ; CHECK: return $pop4 +; NOREGS-LABEL: commute_to_fix_ordering: +; NOREGS: get_local 0{{$}} +; NOREGS: i32.call callee@FUNCTION +; NOREGS: tee_local 1 +; NOREGS: get_local 1{{$}} +; NOREGS: get_local 0{{$}} +; NOREGS: i32.const 1 +; NOREGS: i32.add +; NOREGS: i32.call callee@FUNCTION +; NOREGS: i32.add +; NOREGS: i32.mul +; NOREGS: return define i32 @commute_to_fix_ordering(i32 %arg) { %tmp1 = call i32 @callee(i32 %arg) %tmp2 = add i32 %arg, 1 @@ -325,6 +484,10 @@ define i32 @commute_to_fix_ordering(i32 %arg) { ; CHECK-NEXT: tee_local $push[[NUM1:[0-9]+]]=, $[[NUM2:[0-9]+]]=, $pop[[NUM0]]{{$}} ; CHECK-NEXT: f64.select $push{{[0-9]+}}=, $pop{{[0-9]+}}, $pop[[NUM1]], ${{[0-9]+}}{{$}} ; CHECK: $[[NUM2]]=, +; NOREGS-LABEL: multiple_defs: +; NOREGS: f64.add +; NOREGS: tee_local +; NOREGS: f64.select define void @multiple_defs(i32 %arg, i32 %arg1, i1 %arg2, i1 %arg3, i1 %arg4) { bb: br label %bb5 @@ -367,6 +530,10 @@ exit: ; CHECK: i32.call $0=, red ; CHECK: i32.const $push0=, 0 ; CHECK: i32.load $1=, count($pop0) +; NOREGS-LABEL: no_stackify_call_past_load: +; NOREGS: i32.call red +; NOREGS: i32.const 0 +; NOREGS: i32.load count @count = hidden global i32 0, align 4 define i32 @no_stackify_call_past_load() { %a = call i32 @red() @@ -381,6 +548,10 @@ define i32 @no_stackify_call_past_load() { ; CHECK: i32.store 0($1), $0 ; CHECK: i32.load {{.*}}, 0($2) ; CHECK: i32.call {{.*}}, callee@FUNCTION, $0{{$}} +; NOREGS-LABEL: no_stackify_store_past_load +; NOREGS: i32.store 0 +; NOREGS: i32.load 0 +; NOREGS: i32.call callee@FUNCTION{{$}} 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 @@ -394,6 +565,11 @@ define i32 @no_stackify_store_past_load(i32 %a, i32* %p1, i32* %p2) { ; CHECK: i32.call {{.*}}, callee@FUNCTION, $0 ; CHECK: i32.load $push{{.*}}, 0($2) ; CHECK: return $pop +; NOREGS-LABEL: store_past_invar_load +; NOREGS: i32.store 0 +; NOREGS: i32.call callee@FUNCTION +; NOREGS: i32.load 0 +; NOREGS: return 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 @@ -404,6 +580,9 @@ define i32 @store_past_invar_load(i32 %a, i32* %p1, i32* dereferenceable(4) %p2) ; CHECK-LABEL: ignore_dbg_value: ; CHECK-NEXT: .Lfunc_begin ; CHECK-NEXT: unreachable +; NOREGS-LABEL: ignore_dbg_value: +; NOREGS-NEXT: .Lfunc_begin +; NOREGS-NEXT: unreachable declare void @llvm.dbg.value(metadata, i64, metadata, metadata) define void @ignore_dbg_value() { call void @llvm.dbg.value(metadata i32 0, i64 0, metadata !7, metadata !9), !dbg !10 @@ -415,6 +594,8 @@ define void @ignore_dbg_value() { ; CHECK-LABEL: no_stackify_past_epilogue: ; CHECK: return ${{[0-9]+}}{{$}} +; NOREGS-LABEL: no_stackify_past_epilogue: +; NOREGS: return{{$}} declare i32 @use_memory(i32*) define i32 @no_stackify_past_epilogue() { %x = alloca i32 @@ -429,6 +610,11 @@ define i32 @no_stackify_past_epilogue() { ; CHECK-NEXT: i32.add $push[[L4:.+]]=, $[[R0:.+]], $pop[[L5]]{{$}} ; CHECK-NEXT: tee_local $push[[L3:.+]]=, $[[R0]]=, $pop[[L4]]{{$}} ; CHECK-NEXT: i32.ne $push[[L2:.+]]=, $0, $pop[[L3]]{{$}} +; NOREGS-LABEL: stackify_indvar: +; NOREGS: i32.const 1{{$}} +; NOREGS-NEXT: i32.add +; NOREGS-NEXT: tee_local 2{{$}} +; NOREGS-NEXT: i32.ne define void @stackify_indvar(i32 %tmp, i32* %v) #0 { bb: br label %bb3 @@ -451,6 +637,9 @@ bb10: ; preds = %bb9, %bb ; CHECK-LABEL: stackpointer_dependency: ; CHECK: call {{.+}}, stackpointer_callee@FUNCTION, ; CHECK-NEXT: set_global __stack_pointer, +; NOREGS-LABEL: stackpointer_dependency: +; NOREGS: call stackpointer_callee@FUNCTION +; NOREGS: set_global __stack_pointer declare i32 @stackpointer_callee(i8* readnone, i8* readnone) declare i8* @llvm.frameaddress(i32) define i32 @stackpointer_dependency(i8* readnone) { @@ -467,6 +656,12 @@ define i32 @stackpointer_dependency(i8* readnone) { ; CHECK-NEXT: i32.load $push[[L0:.+]]=, 0($0) ; CHECK-NEXT: i32.load $push[[L1:.+]]=, 0($pop[[L0]]) ; CHECK-NEXT: i32.call_indirect $push{{.+}}=, $pop[[L3]], $1, $pop[[L1]] +; NOREGS-LABEL: call_indirect_stackify: +; NOREGS: i32.load 0 +; NOREGS-NEXT: tee_local 0 +; NOREGS: i32.load 0 +; NOREGS-NEXT: i32.load 0 +; NOREGS-NEXT: i32.call_indirect %class.call_indirect = type { i32 (...)** } define i32 @call_indirect_stackify(%class.call_indirect** %objptr, i32 %arg) { %obj = load %class.call_indirect*, %class.call_indirect** %objptr @@ -491,3 +686,4 @@ define i32 @call_indirect_stackify(%class.call_indirect** %objptr, i32 %arg) { !8 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !9 = !DIExpression() !10 = !DILocation(line: 15, column: 6, scope: !5) + |