OLD | NEW |
(Empty) | |
| 1 ; RUN: opt %s -expand-small-arguments -S | FileCheck %s |
| 2 |
| 3 @var = global i8 0 |
| 4 |
| 5 |
| 6 define void @small_arg(i8 %val) { |
| 7 store i8 %val, i8* @var |
| 8 ret void |
| 9 } |
| 10 ; CHECK: define void @small_arg(i32 %val) { |
| 11 ; CHECK-NEXT: %val.arg_trunc = trunc i32 %val to i8 |
| 12 ; CHECK-NEXT: store i8 %val.arg_trunc, i8* @var |
| 13 |
| 14 |
| 15 define i8 @small_result() { |
| 16 %val = load i8* @var |
| 17 ret i8 %val |
| 18 } |
| 19 ; CHECK: define i32 @small_result() { |
| 20 ; CHECK-NEXT: %val = load i8* @var |
| 21 ; CHECK-NEXT: %val.ret_ext = zext i8 %val to i32 |
| 22 ; CHECK-NEXT: ret i32 %val.ret_ext |
| 23 |
| 24 define signext i8 @small_result_signext() { |
| 25 %val = load i8* @var |
| 26 ret i8 %val |
| 27 } |
| 28 ; CHECK: define signext i32 @small_result_signext() { |
| 29 ; CHECK-NEXT: %val = load i8* @var |
| 30 ; CHECK-NEXT: %val.ret_ext = sext i8 %val to i32 |
| 31 ; CHECK-NEXT: ret i32 %val.ret_ext |
| 32 |
| 33 |
| 34 define void @call_small_arg() { |
| 35 call void @small_arg(i8 100) |
| 36 ret void |
| 37 } |
| 38 ; CHECK: define void @call_small_arg() { |
| 39 ; CHECK-NEXT: %arg_ext = zext i8 100 to i32 |
| 40 ; CHECK-NEXT: %.arg_cast = bitcast {{.*}} @small_arg |
| 41 ; CHECK-NEXT: call void %.arg_cast(i32 %arg_ext) |
| 42 |
| 43 define void @call_small_arg_signext() { |
| 44 call void @small_arg(i8 signext 100) |
| 45 ret void |
| 46 } |
| 47 ; CHECK: define void @call_small_arg_signext() { |
| 48 ; CHECK-NEXT: %arg_ext = sext i8 100 to i32 |
| 49 ; CHECK-NEXT: %.arg_cast = bitcast {{.*}} @small_arg |
| 50 ; CHECK-NEXT: call void %.arg_cast(i32 signext %arg_ext) |
| 51 |
| 52 |
| 53 define void @call_small_result() { |
| 54 %r = call i8 @small_result() |
| 55 store i8 %r, i8* @var |
| 56 ret void |
| 57 } |
| 58 ; CHECK: define void @call_small_result() { |
| 59 ; CHECK-NEXT: %r.arg_cast = bitcast {{.*}} @small_result |
| 60 ; CHECK-NEXT: %r = call i32 %r.arg_cast() |
| 61 ; CHECK-NEXT: %r.ret_trunc = trunc i32 %r to i8 |
| 62 ; CHECK-NEXT: store i8 %r.ret_trunc, i8* @var |
| 63 |
| 64 |
| 65 ; Check that various attributes are preserved. |
| 66 define i1 @attributes(i8 %arg) nounwind { |
| 67 %r = tail call fastcc i1 @attributes(i8 %arg) nounwind |
| 68 ret i1 %r |
| 69 } |
| 70 ; CHECK: define i32 @attributes(i32 %arg) [[NOUNWIND:#[0-9]+]] { |
| 71 ; CHECK: tail call fastcc i32 {{.*}} [[NOUNWIND]] |
| 72 |
| 73 |
| 74 ; These arguments and results should be left alone. |
| 75 define i64 @larger_arguments(i32 %a, i64 %b, i8* %ptr, double %d) { |
| 76 %r = call i64 @larger_arguments(i32 %a, i64 %b, i8* %ptr, double %d) |
| 77 ret i64 %r |
| 78 } |
| 79 ; CHECK: define i64 @larger_arguments(i32 %a, i64 %b, i8* %ptr, double %d) { |
| 80 ; CHECK-NEXT: %r = call i64 @larger_arguments(i32 %a, i64 %b, i8* %ptr, double %
d) |
| 81 ; CHECK-NEXT: ret i64 %r |
| 82 |
| 83 |
| 84 ; Intrinsics must be left alone since the pass cannot change their types. |
| 85 |
| 86 declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) |
| 87 ; CHECK: declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) |
| 88 |
| 89 define void @intrinsic_call(i8* %ptr) { |
| 90 call void @llvm.memset.p0i8.i32(i8* %ptr, i8 99, i32 256, i32 1, i1 0) |
| 91 ret void |
| 92 } |
| 93 ; CHECK: define void @intrinsic_call |
| 94 ; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* %ptr, i8 99, |
| 95 |
| 96 define void @invoking_small_arg(i8) { |
| 97 invoke void @small_arg(i8 %0) |
| 98 to label %cont unwind label %lpad |
| 99 cont: |
| 100 ret void |
| 101 lpad: |
| 102 %lp = landingpad { i8*, i32 } personality i8* null cleanup |
| 103 ret void |
| 104 } |
| 105 ; CHECK-LABEL: define void @invoking_small_arg(i32) |
| 106 ; CHECK-NEXT: %.arg_trunc = trunc i32 %0 to i8 |
| 107 ; CHECK-NEXT: %arg_ext = zext i8 %.arg_trunc to i32 |
| 108 ; CHECK-NEXT: %.arg_cast = bitcast void (i8)* bitcast (void (i32)* @small_arg
to void (i8)*) to void (i32)* |
| 109 ; CHECK-NEXT: invoke void %.arg_cast(i32 %arg_ext) |
| 110 ; CHECK-NEXT: to label %cont unwind label %lpad |
| 111 |
| 112 ; CHECK: cont: |
| 113 ; CHECK-NEXT: ret void |
| 114 |
| 115 ; CHECK: lpad: |
| 116 ; CHECK-NEXT: %lp = landingpad { i8*, i32 } personality i8* null |
| 117 ; CHECK-NEXT: cleanup |
| 118 ; CHECK-NEXT: ret void |
| 119 |
| 120 define fastcc void @invoking_cc() { |
| 121 invoke fastcc void @invoking_cc() |
| 122 to label %cont unwind label %lpad |
| 123 cont: |
| 124 ret void |
| 125 lpad: |
| 126 %lp = landingpad { i8*, i32 } personality i8* null cleanup |
| 127 ret void |
| 128 } |
| 129 ; CHECK-LABEL: define fastcc void @invoking_cc() |
| 130 ; CHECK-NEXT: invoke fastcc void @invoking_cc() |
| 131 |
| 132 define void @invoking_attrs() noinline { |
| 133 invoke void @invoking_attrs() noinline |
| 134 to label %cont unwind label %lpad |
| 135 cont: |
| 136 ret void |
| 137 lpad: |
| 138 %lp = landingpad { i8*, i32 } personality i8* null cleanup |
| 139 ret void |
| 140 } |
| 141 ; CHECK: define void @invoking_attrs() [[NOINLINE:#[0-9]+]] |
| 142 ; CHECK: invoke void @invoking_attrs() [[NOINLINE]] |
| 143 |
| 144 define void @invoking_critical_edge() { |
| 145 entry: |
| 146 %a = invoke i8 @small_result() |
| 147 to label %loop unwind label %lpad |
| 148 loop: |
| 149 %b = phi i8 [ %a, %entry ], [ %c, %loop ] |
| 150 %c = add i8 1, %b |
| 151 %d = icmp eq i8 %c, 5 |
| 152 br i1 %d, label %exit, label %loop |
| 153 |
| 154 exit: |
| 155 %aa = phi i8 [ 0, %lpad ], [ %c, %loop ] |
| 156 ret void |
| 157 |
| 158 lpad: |
| 159 %lp = landingpad { i8*, i32 } personality i8* null cleanup |
| 160 br label %exit |
| 161 } |
| 162 ; CHECK-LABEL: define void @invoking_critical_edge() |
| 163 ; CHECK: entry: |
| 164 ; CHECK-NEXT: %a.arg_cast = bitcast i8 ()* bitcast (i32 ()* @small_result to
i8 ()*) to i32 ()* |
| 165 ; CHECK-NEXT: %a = invoke i32 %a.arg_cast() |
| 166 ; CHECK-NEXT: to label %entry.loop_crit_edge unwind label %lpad |
| 167 |
| 168 ; CHECK: entry.loop_crit_edge: |
| 169 ; CHECK-NEXT: %a.ret_trunc = trunc i32 %a to i8 |
| 170 ; CHECK-NEXT: br label %loop |
| 171 |
| 172 ; CHECK: loop: |
| 173 ; CHECK-NEXT: %b = phi i8 [ %a.ret_trunc, %entry.loop_crit_edge ], [ %c, %loo
p ] |
| 174 ; CHECK-NEXT: %c = add i8 1, %b |
| 175 ; CHECK-NEXT: %d = icmp eq i8 %c, 5 |
| 176 ; CHECK-NEXT: br i1 %d, label %exit, label %loop |
| 177 |
| 178 ; CHECK: exit: |
| 179 ; CHECK-NEXT: %aa = phi i8 [ 0, %lpad ], [ %c, %loop ] |
| 180 ; CHECK-NEXT: ret void |
| 181 |
| 182 ; CHECK: lpad: |
| 183 ; CHECK-NEXT: %lp = landingpad { i8*, i32 } personality i8* null |
| 184 ; CHECK-NEXT: cleanup |
| 185 ; CHECK-NEXT: br label %exit |
| 186 |
| 187 define i8 @invoking_small_result() { |
| 188 entry: |
| 189 %a = invoke i8 @small_result() |
| 190 to label %cont unwind label %lpad |
| 191 cont: |
| 192 ret i8 %a |
| 193 lpad: |
| 194 %lp = landingpad { i8*, i32 } personality i8* null cleanup |
| 195 ret i8 123 |
| 196 } |
| 197 ; CHECK-LABEL: define i32 @invoking_small_result() |
| 198 ; CHECK: entry: |
| 199 ; CHECK-NEXT: %a.arg_cast = bitcast i8 ()* bitcast (i32 ()* @small_result to
i8 ()*) to i32 ()* |
| 200 ; CHECK-NEXT: %a = invoke i32 %a.arg_cast() |
| 201 ; CHECK-NEXT: to label %cont unwind label %lpad |
| 202 |
| 203 ; CHECK: cont: |
| 204 ; CHECK-NEXT: %a.ret_trunc = trunc i32 %a to i8 |
| 205 ; CHECK-NEXT: %a.ret_trunc.ret_ext = zext i8 %a.ret_trunc to i32 |
| 206 ; CHECK-NEXT: ret i32 %a.ret_trunc.ret_ext |
| 207 |
| 208 ; CHECK: lpad: |
| 209 ; CHECK-NEXT: %lp = landingpad { i8*, i32 } personality i8* null |
| 210 ; CHECK-NEXT: cleanup |
| 211 ; CHECK-NEXT: %.ret_ext = zext i8 123 to i32 |
| 212 ; CHECK-NEXT: ret i32 %.ret_ext |
| 213 |
| 214 |
| 215 ; CHECK: attributes [[NOUNWIND]] = { nounwind } |
| 216 ; CHECK: attributes [[NOINLINE]] = { noinline } |
OLD | NEW |