OLD | NEW |
(Empty) | |
| 1 ; RUN: opt %s -pnacl-sjlj-eh -O2 -S | FileCheck %s |
| 2 |
| 3 ; datalayout must be specified for GVN to work. |
| 4 target datalayout = "p:32:32:32" |
| 5 |
| 6 ; This must be declared for expanding "invoke" and "landingpad" instructions. |
| 7 @__pnacl_eh_stack = external thread_local global i8* |
| 8 |
| 9 declare i1 @might_be_setjmp() |
| 10 declare void @external_func(i32* %ptr) |
| 11 declare void @var_is_nonzero() |
| 12 |
| 13 |
| 14 ; Test for a bug in which PNaClSjLjEH would transform |
| 15 ; @invoke_optimize_test() such that the call to @var_is_nonzero() |
| 16 ; could get optimized away by a later optimization pass. This |
| 17 ; happened because PNaClSjLjEH generated code similar to |
| 18 ; @branch_optimize_test() below. |
| 19 |
| 20 define void @invoke_optimize_test() { |
| 21 %var = alloca i32 |
| 22 store i32 0, i32* %var |
| 23 |
| 24 invoke void @external_func(i32* %var) |
| 25 to label %exit unwind label %lpad |
| 26 |
| 27 lpad: |
| 28 landingpad i32 personality i8* null |
| 29 catch i8* null |
| 30 %value = load i32* %var |
| 31 %is_zero = icmp eq i32 %value, 0 |
| 32 br i1 %is_zero, label %exit, label %do_call |
| 33 |
| 34 do_call: |
| 35 call void @var_is_nonzero() |
| 36 ret void |
| 37 |
| 38 exit: |
| 39 ret void |
| 40 } |
| 41 ; CHECK: define void @invoke_optimize_test() |
| 42 ; CHECK: @var_is_nonzero() |
| 43 |
| 44 |
| 45 ; In @branch_optimize_test(), the optimizer can optimize away the call |
| 46 ; to @var_is_nonzero(), because it can assume that %var always |
| 47 ; contains 0 on the "iffalse" branch. |
| 48 ; |
| 49 ; The passes "-gvn -instcombine" are enough to do this. |
| 50 ; |
| 51 ; The optimizer can do this regardless of whether @might_be_setjmp() |
| 52 ; is setjmp() or a normal function. It doesn't need to know that |
| 53 ; @might_be_setjmp() might return twice, because storing to %var |
| 54 ; between setjmp() and longjmp() leaves %var pointing to an undefined |
| 55 ; value. |
| 56 |
| 57 define void @branch_optimize_test() { |
| 58 %var = alloca i32 |
| 59 store i32 0, i32* %var |
| 60 |
| 61 %cond = call i1 @might_be_setjmp() returns_twice |
| 62 br i1 %cond, label %iftrue, label %iffalse |
| 63 |
| 64 iftrue: |
| 65 call void @external_func(i32* %var) |
| 66 ret void |
| 67 |
| 68 iffalse: |
| 69 %value = load i32* %var |
| 70 %is_zero = icmp eq i32 %value, 0 |
| 71 br i1 %is_zero, label %exit, label %do_call |
| 72 |
| 73 do_call: |
| 74 call void @var_is_nonzero() |
| 75 ret void |
| 76 |
| 77 exit: |
| 78 ret void |
| 79 } |
| 80 ; CHECK: define void @branch_optimize_test() |
| 81 ; CHECK-NOT: @var_is_nonzero |
OLD | NEW |