1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 04:32:44 +01:00
llvm-mirror/test/CodeGen/WebAssembly/switch.ll
Wouter van Oortmerssen a492dddf2e [WebAssembly] Fixed 64-bit indices in br_table
LLVM selection dag assumes "switch" indices are pointer sized, which causes problems for our 32-bit br_table. The new function ensures 32-bit operands don't get unnecessarily extended, and 64-bit operands get truncated.

Note that the changes to the existing test test exactly that: the addition of -NEXT in 2 places ensures no extension is inserted (which the test previously ignored) and that the wrap is present (previously omitted in wasm64 mode).

Differential Revision: https://reviews.llvm.org/D84705
2020-07-30 10:52:16 -07:00

217 lines
6.3 KiB
LLVM

; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs | FileCheck %s
; RUN: llc < %s --mtriple=wasm64-unknown-unknown -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs | FileCheck %s
; Test switch instructions. Block placement is disabled because it reorders
; the blocks in a way that isn't interesting here.
declare void @foo0()
declare void @foo1()
declare void @foo2()
declare void @foo3()
declare void @foo4()
declare void @foo5()
; CHECK-LABEL: bar32:
; CHECK: block {{$}}
; CHECK: block {{$}}
; CHECK: block {{$}}
; CHECK: block {{$}}
; CHECK: block {{$}}
; CHECK: block {{$}}
; CHECK: block {{$}}
; CHECK-NEXT: br_table {{[^,]+}}, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 4, 5, 6{{$}}
; CHECK: .LBB{{[0-9]+}}_1:
; CHECK: call foo0{{$}}
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK: call foo1{{$}}
; CHECK: .LBB{{[0-9]+}}_3:
; CHECK: call foo2{{$}}
; CHECK: .LBB{{[0-9]+}}_4:
; CHECK: call foo3{{$}}
; CHECK: .LBB{{[0-9]+}}_5:
; CHECK: call foo4{{$}}
; CHECK: .LBB{{[0-9]+}}_6:
; CHECK: call foo5{{$}}
; CHECK: .LBB{{[0-9]+}}_7:
; CHECK: return{{$}}
define void @bar32(i32 %n) {
entry:
switch i32 %n, label %sw.epilog [
i32 0, label %sw.bb
i32 1, label %sw.bb
i32 2, label %sw.bb
i32 3, label %sw.bb
i32 4, label %sw.bb
i32 5, label %sw.bb
i32 6, label %sw.bb
i32 7, label %sw.bb.1
i32 8, label %sw.bb.1
i32 9, label %sw.bb.1
i32 10, label %sw.bb.1
i32 11, label %sw.bb.1
i32 12, label %sw.bb.1
i32 13, label %sw.bb.1
i32 14, label %sw.bb.1
i32 15, label %sw.bb.2
i32 16, label %sw.bb.2
i32 17, label %sw.bb.2
i32 18, label %sw.bb.2
i32 19, label %sw.bb.2
i32 20, label %sw.bb.2
i32 21, label %sw.bb.3
i32 22, label %sw.bb.4
i32 23, label %sw.bb.5
]
sw.bb: ; preds = %entry, %entry, %entry, %entry, %entry, %entry, %entry
tail call void @foo0()
br label %sw.epilog
sw.bb.1: ; preds = %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry
tail call void @foo1()
br label %sw.epilog
sw.bb.2: ; preds = %entry, %entry, %entry, %entry, %entry, %entry
tail call void @foo2()
br label %sw.epilog
sw.bb.3: ; preds = %entry
tail call void @foo3()
br label %sw.epilog
sw.bb.4: ; preds = %entry
tail call void @foo4()
br label %sw.epilog
sw.bb.5: ; preds = %entry
tail call void @foo5()
br label %sw.epilog
sw.epilog: ; preds = %entry, %sw.bb.5, %sw.bb.4, %sw.bb.3, %sw.bb.2, %sw.bb.1, %sw.bb
ret void
}
; CHECK-LABEL: bar64:
; CHECK: block {{$}}
; CHECK: i64.const
; CHECK: i64.gt_u
; CHECK: br_if 0
; CHECK: block {{$}}
; CHECK: block {{$}}
; CHECK: block {{$}}
; CHECK: block {{$}}
; CHECK: block {{$}}
; CHECK: block {{$}}
; CHECK: i32.wrap_i64
; CHECK-NEXT: br_table {{[^,]+}}, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 4, 5, 0{{$}}
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK: call foo0{{$}}
; CHECK: .LBB{{[0-9]+}}_3:
; CHECK: call foo1{{$}}
; CHECK: .LBB{{[0-9]+}}_4:
; CHECK: call foo2{{$}}
; CHECK: .LBB{{[0-9]+}}_5:
; CHECK: call foo3{{$}}
; CHECK: .LBB{{[0-9]+}}_6:
; CHECK: call foo4{{$}}
; CHECK: .LBB{{[0-9]+}}_7:
; CHECK: call foo5{{$}}
; CHECK: .LBB{{[0-9]+}}_8:
; CHECK: return{{$}}
define void @bar64(i64 %n) {
entry:
switch i64 %n, label %sw.epilog [
i64 0, label %sw.bb
i64 1, label %sw.bb
i64 2, label %sw.bb
i64 3, label %sw.bb
i64 4, label %sw.bb
i64 5, label %sw.bb
i64 6, label %sw.bb
i64 7, label %sw.bb.1
i64 8, label %sw.bb.1
i64 9, label %sw.bb.1
i64 10, label %sw.bb.1
i64 11, label %sw.bb.1
i64 12, label %sw.bb.1
i64 13, label %sw.bb.1
i64 14, label %sw.bb.1
i64 15, label %sw.bb.2
i64 16, label %sw.bb.2
i64 17, label %sw.bb.2
i64 18, label %sw.bb.2
i64 19, label %sw.bb.2
i64 20, label %sw.bb.2
i64 21, label %sw.bb.3
i64 22, label %sw.bb.4
i64 23, label %sw.bb.5
]
sw.bb: ; preds = %entry, %entry, %entry, %entry, %entry, %entry, %entry
tail call void @foo0()
br label %sw.epilog
sw.bb.1: ; preds = %entry, %entry, %entry, %entry, %entry, %entry, %entry, %entry
tail call void @foo1()
br label %sw.epilog
sw.bb.2: ; preds = %entry, %entry, %entry, %entry, %entry, %entry
tail call void @foo2()
br label %sw.epilog
sw.bb.3: ; preds = %entry
tail call void @foo3()
br label %sw.epilog
sw.bb.4: ; preds = %entry
tail call void @foo4()
br label %sw.epilog
sw.bb.5: ; preds = %entry
tail call void @foo5()
br label %sw.epilog
sw.epilog: ; preds = %entry, %sw.bb.5, %sw.bb.4, %sw.bb.3, %sw.bb.2, %sw.bb.1, %sw.bb
ret void
}
; CHECK-LABEL: truncated:
; CHECK: block
; CHECK: block
; CHECK: block
; CHECK: i32.wrap_i64
; CHECK-NEXT: br_table {{[^,]+}}, 0, 1, 2{{$}}
; CHECK: .LBB{{[0-9]+}}_1
; CHECK: end_block
; CHECK: call foo0{{$}}
; CHECK: return{{$}}
; CHECK: .LBB{{[0-9]+}}_2
; CHECK: end_block
; CHECK: call foo1{{$}}
; CHECK: return{{$}}
; CHECK: .LBB{{[0-9]+}}_3
; CHECK: end_block
; CHECK: call foo2{{$}}
; CHECK: return{{$}}
; CHECK: end_function
define void @truncated(i64 %n) {
entry:
%m = trunc i64 %n to i32
switch i32 %m, label %default [
i32 0, label %bb1
i32 1, label %bb2
]
bb1:
tail call void @foo0()
ret void
bb2:
tail call void @foo1()
ret void
default:
tail call void @foo2()
ret void
}