diff options
Diffstat (limited to 'llvm/test/CodeGen/WebAssembly')
-rw-r--r-- | llvm/test/CodeGen/WebAssembly/cfg-stackify.ll | 274 | ||||
-rw-r--r-- | llvm/test/CodeGen/WebAssembly/phi.ll | 5 | ||||
-rw-r--r-- | llvm/test/CodeGen/WebAssembly/switch.ll | 173 |
3 files changed, 448 insertions, 4 deletions
diff --git a/llvm/test/CodeGen/WebAssembly/cfg-stackify.ll b/llvm/test/CodeGen/WebAssembly/cfg-stackify.ll new file mode 100644 index 00000000000..205384e6102 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/cfg-stackify.ll @@ -0,0 +1,274 @@ +; RUN: llc < %s -asm-verbose=false | FileCheck %s + +; Test the CFG stackifier pass. + +target datalayout = "e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +declare void @something() + +; Test that loops are made contiguous, even in the presence of split backedges. + +; CHECK-LABEL: test0 +; CHECK: (loop +; CHECK: (add +; CHECK: (brif +; CHECK: (call +; CHECK: (br $BB0_1) +; CHECK: (return) +define void @test0(i32 %n) { +entry: + br label %header + +header: + %i = phi i32 [ 0, %entry ], [ %i.next, %back ] + %i.next = add i32 %i, 1 + + %c = icmp slt i32 %i.next, %n + br i1 %c, label %back, label %exit + +exit: + ret void + +back: + call void @something() + br label %header +} + +; Same as test0, but the branch condition is reversed. + +; CHECK-LABEL: test1 +; CHECK: (loop +; CHECK: (add +; CHECK: (brif +; CHECK: (call +; CHECK: (br $BB1_1) +; CHECK: (return) +define void @test1(i32 %n) { +entry: + br label %header + +header: + %i = phi i32 [ 0, %entry ], [ %i.next, %back ] + %i.next = add i32 %i, 1 + + %c = icmp sge i32 %i.next, %n + br i1 %c, label %exit, label %back + +exit: + ret void + +back: + call void @something() + br label %header +} + +; Test that a simple loop is handled as expected. + +; CHECK-LABEL: test2 +; CHECK: (block $BB2_2) +; CHECK: (brif $BB2_2 {{.*}}) +; CHECK: BB2_1: +; CHECK: (brif $BB2_1 @14) +; CHECK: BB2_2: +; CHECK: (return) +define void @test2(double* nocapture %p, i32 %n) { +entry: + %cmp.4 = icmp sgt i32 %n, 0 + br i1 %cmp.4, label %for.body.preheader, label %for.end + +for.body.preheader: + br label %for.body + +for.body: + %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ] + %arrayidx = getelementptr inbounds double, double* %p, i32 %i.05 + %0 = load double, double* %arrayidx, align 8 + %mul = fmul double %0, 3.200000e+00 + store double %mul, double* %arrayidx, align 8 + %inc = add nuw nsw i32 %i.05, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.end.loopexit, label %for.body + +for.end.loopexit: + br label %for.end + +for.end: + ret void +} + +; CHECK-LABEL: doublediamond +; CHECK: (block $BB3_5) +; CHECK: (block $BB3_4) +; CHECK: (block $BB3_2) +; CHECK: (brif $BB3_2 @4) +; CHECK: (br $BB3_5) +; CHECK: BB3_2: +; CHECK: (brif $BB3_4 @7) +; CHECK: (br $BB3_5) +; CHECK: BB3_4: +; CHECK: BB3_5: +; CHECK: (return @3) +define i32 @doublediamond(i32 %a, i32 %b, i32* %p) { +entry: + %c = icmp eq i32 %a, 0 + %d = icmp eq i32 %b, 0 + store volatile i32 0, i32* %p + br i1 %c, label %true, label %false +true: + store volatile i32 1, i32* %p + br label %exit +false: + store volatile i32 2, i32* %p + br i1 %d, label %ft, label %ff +ft: + store volatile i32 3, i32* %p + br label %exit +ff: + store volatile i32 4, i32* %p + br label %exit +exit: + store volatile i32 5, i32* %p + ret i32 0 +} + +; CHECK-LABEL: triangle +; CHECK: (block $BB4_2) +; CHECK: (brif $BB4_2 @3) +; CHECK: BB4_2: +; CHECK: (return @2) +define i32 @triangle(i32* %p, i32 %a) { +entry: + %c = icmp eq i32 %a, 0 + store volatile i32 0, i32* %p + br i1 %c, label %true, label %exit +true: + store volatile i32 1, i32* %p + br label %exit +exit: + store volatile i32 2, i32* %p + ret i32 0 +} + +; CHECK-LABEL: diamond +; CHECK: (block $BB5_3) +; CHECK: (block $BB5_2) +; CHECK: (brif $BB5_2 @3) +; CHECK: (br $BB5_3) +; CHECK: BB5_2: +; CHECK: BB5_3: +; CHECK: (return @2) +define i32 @diamond(i32* %p, i32 %a) { +entry: + %c = icmp eq i32 %a, 0 + store volatile i32 0, i32* %p + br i1 %c, label %true, label %false +true: + store volatile i32 1, i32* %p + br label %exit +false: + store volatile i32 2, i32* %p + br label %exit +exit: + store volatile i32 3, i32* %p + ret i32 0 +} + +; CHECK-LABEL: single_block +; CHECK-NOT: br +; CHECK: (return @1) +define i32 @single_block(i32* %p) { +entry: + store volatile i32 0, i32* %p + ret i32 0 +} + +; CHECK-LABEL: minimal_loop +; CHECK-NOT: br +; CHECK: BB7_1: +; CHECK: (store_i32 @0 @2) +; CHECK: (br $BB7_1) +define i32 @minimal_loop(i32* %p) { +entry: + store volatile i32 0, i32* %p + br label %loop +loop: + store volatile i32 1, i32* %p + br label %loop +} + +; CHECK-LABEL: simple_loop +; CHECK-NOT: br +; CHECK: BB8_1: +; CHECK: (loop $BB8_1) +; CHECK: (brif $BB8_1 @4) +; CHECK: (return @2) +define i32 @simple_loop(i32* %p, i32 %a) { +entry: + %c = icmp eq i32 %a, 0 + store volatile i32 0, i32* %p + br label %loop +loop: + store volatile i32 1, i32* %p + br i1 %c, label %loop, label %exit +exit: + store volatile i32 2, i32* %p + ret i32 0 +} + +; CHECK-LABEL: doubletriangle +; CHECK: (block $BB9_4) +; CHECK: (block $BB9_3) +; CHECK: (brif $BB9_4 @4) +; CHECK: (brif $BB9_3 @7) +; CHECK: BB9_3: +; CHECK: BB9_4: +; CHECK: (return @3) +define i32 @doubletriangle(i32 %a, i32 %b, i32* %p) { +entry: + %c = icmp eq i32 %a, 0 + %d = icmp eq i32 %b, 0 + store volatile i32 0, i32* %p + br i1 %c, label %true, label %exit +true: + store volatile i32 2, i32* %p + br i1 %d, label %tt, label %tf +tt: + store volatile i32 3, i32* %p + br label %tf +tf: + store volatile i32 4, i32* %p + br label %exit +exit: + store volatile i32 5, i32* %p + ret i32 0 +} + +; CHECK-LABEL: ifelse_earlyexits +; CHECK: (block $BB10_4) +; CHECK: (block $BB10_2) +; CHECK: (brif $BB10_2 @4) +; CHECK: (br $BB10_4) +; CHECK: BB10_2: +; CHECK: (brif $BB10_4 @7) +; CHECK: BB10_4: +; CHECK: (return @3) +define i32 @ifelse_earlyexits(i32 %a, i32 %b, i32* %p) { +entry: + %c = icmp eq i32 %a, 0 + %d = icmp eq i32 %b, 0 + store volatile i32 0, i32* %p + br i1 %c, label %true, label %false +true: + store volatile i32 1, i32* %p + br label %exit +false: + store volatile i32 2, i32* %p + br i1 %d, label %ft, label %exit +ft: + store volatile i32 3, i32* %p + br label %exit +exit: + store volatile i32 4, i32* %p + ret i32 0 +} diff --git a/llvm/test/CodeGen/WebAssembly/phi.ll b/llvm/test/CodeGen/WebAssembly/phi.ll index f06d9673de5..a4675fba711 100644 --- a/llvm/test/CodeGen/WebAssembly/phi.ll +++ b/llvm/test/CodeGen/WebAssembly/phi.ll @@ -1,8 +1,5 @@ ; RUN: llc < %s -asm-verbose=false | FileCheck %s -; This test depends on branching support, which is not yet checked in. -; XFAIL: * - ; Test that phis are lowered. target datalayout = "e-p:32:32-i64:64-n32:64-S128" @@ -29,7 +26,7 @@ done: ; Swap phis. ; CHECK-LABEL: test1 -; CHECK: BB0_1: +; CHECK: BB1_1: ; CHECK: (setlocal [[REG0:@.*]] [[REG1:@.*]]) ; CHECK: (setlocal [[REG1]] [[REG2:@.*]]) ; CHECK: (setlocal [[REG2]] [[REG0]]) diff --git a/llvm/test/CodeGen/WebAssembly/switch.ll b/llvm/test/CodeGen/WebAssembly/switch.ll new file mode 100644 index 00000000000..8aaa391cb52 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/switch.ll @@ -0,0 +1,173 @@ +; RUN: llc < %s -asm-verbose=false | FileCheck %s + +; Test switch instructions. + +target datalayout = "e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +declare void @foo0() +declare void @foo1() +declare void @foo2() +declare void @foo3() +declare void @foo4() +declare void @foo5() + +; CHECK-LABEL: bar32 +; CHECK: (block $BB0_8) +; CHECK: (block $BB0_7) +; CHECK: (block $BB0_6) +; CHECK: (block $BB0_5) +; CHECK: (block $BB0_4) +; CHECK: (block $BB0_3) +; CHECK: (block $BB0_2) +; CHECK: (switch {{.*}} $BB0_2 $BB0_2 $BB0_2 $BB0_2 $BB0_2 $BB0_2 $BB0_2 $BB0_2 $BB0_3 $BB0_3 $BB0_3 $BB0_3 $BB0_3 $BB0_3 $BB0_3 $BB0_3 $BB0_4 $BB0_4 $BB0_4 $BB0_4 $BB0_4 $BB0_4 $BB0_5 $BB0_6 $BB0_7) +; CHECk: BB0_2: +; CHECK: (setlocal {{.*}} (global $foo0)) +; CHECK: BB0_3: +; CHECK: (setlocal {{.*}} (global $foo1)) +; CHECK: BB0_4: +; CHECK: (setlocal {{.*}} (global $foo2)) +; CHECK: BB0_5: +; CHECK: (setlocal {{.*}} (global $foo3)) +; CHECK: BB0_6: +; CHECK: (setlocal {{.*}} (global $foo4)) +; CHECK: BB0_7: +; CHECK: (setlocal {{.*}} (global $foo5)) +; CHECK: BB0_8: +; 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 $BB1_8) +; CHECK: (block $BB1_7) +; CHECK: (block $BB1_6) +; CHECK: (block $BB1_5) +; CHECK: (block $BB1_4) +; CHECK: (block $BB1_3) +; CHECK: (block $BB1_2) +; CHECK: (switch {{.*}} $BB1_2 $BB1_2 $BB1_2 $BB1_2 $BB1_2 $BB1_2 $BB1_2 $BB1_2 $BB1_3 $BB1_3 $BB1_3 $BB1_3 $BB1_3 $BB1_3 $BB1_3 $BB1_3 $BB1_4 $BB1_4 $BB1_4 $BB1_4 $BB1_4 $BB1_4 $BB1_5 $BB1_6 $BB1_7) +; CHECk: BB1_2: +; CHECK: (setlocal {{.*}} (global $foo0)) +; CHECK: BB1_3: +; CHECK: (setlocal {{.*}} (global $foo1)) +; CHECK: BB1_4: +; CHECK: (setlocal {{.*}} (global $foo2)) +; CHECK: BB1_5: +; CHECK: (setlocal {{.*}} (global $foo3)) +; CHECK: BB1_6: +; CHECK: (setlocal {{.*}} (global $foo4)) +; CHECK: BB1_7: +; CHECK: (setlocal {{.*}} (global $foo5)) +; CHECK: BB1_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 +} |