1; RUN: llc -mtriple=thumbv8 -arm-disable-cgp=false %s -o - | FileCheck %s 2; RUN: llc -mtriple=armv8 -arm-disable-cgp=false %s -o - | FileCheck %s 3 4; Check that the pass doesn't try to promote the immediate parameters. 5; CHECK-LABEL: call_with_imms 6; CHECK-NOT: uxt 7define i8 @call_with_imms(i8* %arg) { 8 %call = tail call arm_aapcs_vfpcc zeroext i8 @dummy2(i8* nonnull %arg, i8 zeroext 0, i8 zeroext 0) 9 %cmp = icmp eq i8 %call, 0 10 %res = select i1 %cmp, i8 %call, i8 1 11 ret i8 %res 12} 13 14; Test that the call result is still extended. 15; CHECK-LABEL: test_call: 16; CHECK: bl 17; CHECK-NEXT: sxtb r1, r0 18define i16 @test_call(i8 zeroext %arg) { 19 %call = call i8 @dummy_i8(i8 %arg) 20 %cmp = icmp ult i8 %call, 128 21 %conv = zext i1 %cmp to i16 22 ret i16 %conv 23} 24 25; CHECK-LABEL: promote_i8_sink_i16_1 26; CHECK: bl dummy_i8 27; CHECK: add{{.*}} r0, #1 28; CHECK-NOT: uxt 29; CHECK: cmp r0 30define i16 @promote_i8_sink_i16_1(i8 zeroext %arg0, i16 zeroext %arg1, i16 zeroext %arg2) { 31 %call = tail call zeroext i8 @dummy_i8(i8 %arg0) 32 %add = add nuw i8 %call, 1 33 %conv = zext i8 %add to i16 34 %cmp = icmp ne i16 %conv, %arg1 35 %sel = select i1 %cmp, i16 %arg1, i16 %arg2 36 %res = tail call zeroext i16 @dummy3(i16 %sel) 37 ret i16 %res 38} 39 40; CHECK-LABEL: promote_i8_sink_i16_2 41; CHECK: bl dummy_i8 42; CHECK: add{{.*}} r0, #1 43; CHECK-NOT: uxt 44; CHECK: cmp r0 45define i16 @promote_i8_sink_i16_2(i8 zeroext %arg0, i8 zeroext %arg1, i16 zeroext %arg2) { 46 %call = tail call zeroext i8 @dummy_i8(i8 %arg0) 47 %add = add nuw i8 %call, 1 48 %cmp = icmp ne i8 %add, %arg1 49 %conv = zext i8 %arg1 to i16 50 %sel = select i1 %cmp, i16 %conv, i16 %arg2 51 %res = tail call zeroext i16 @dummy3(i16 %sel) 52 ret i16 %res 53} 54 55@uc = global i8 42, align 1 56@LL = global i64 0, align 8 57 58; CHECK-LABEL: zext_i64 59; CHECK: ldrb 60; CHECK: strd 61define void @zext_i64() { 62entry: 63 %0 = load i8, i8* @uc, align 1 64 %conv = zext i8 %0 to i64 65 store i64 %conv, i64* @LL, align 8 66 %cmp = icmp eq i8 %0, 42 67 %conv1 = zext i1 %cmp to i32 68 %call = tail call i32 bitcast (i32 (...)* @assert to i32 (i32)*)(i32 %conv1) 69 ret void 70} 71 72@a = global i16* null, align 4 73@b = global i32 0, align 4 74 75; CHECK-LABEL: constexpr 76; CHECK: uxth 77define i32 @constexpr() { 78entry: 79 store i32 ptrtoint (i32* @b to i32), i32* @b, align 4 80 %0 = load i16*, i16** @a, align 4 81 %1 = load i16, i16* %0, align 2 82 %or = or i16 %1, ptrtoint (i32* @b to i16) 83 store i16 %or, i16* %0, align 2 84 %cmp = icmp ne i16 %or, 4 85 %conv3 = zext i1 %cmp to i32 86 %call = tail call i32 bitcast (i32 (...)* @e to i32 (i32)*)(i32 %conv3) #2 87 ret i32 undef 88} 89 90; The call to safe_lshift_func takes two parameters, but they're the same value 91; just one is zext. We do support zext now, so the transformation should 92; trigger and we don't want see uxtb here. 93; CHECK-LABEL: call_zext_i8_i32 94; CHECK-NOT: uxt 95define fastcc i32 @call_zext_i8_i32(i32 %p_45, i8 zeroext %p_46) { 96for.cond8.preheader: 97 %call217 = call fastcc zeroext i8 @safe_mul_func_uint8_t_u_u(i8 zeroext undef) 98 %tobool219 = icmp eq i8 %call217, 0 99 br i1 %tobool219, label %for.end411, label %for.cond273.preheader 100 101for.cond273.preheader: ; preds = %for.cond8.preheader 102 %call217.lcssa = phi i8 [ %call217, %for.cond8.preheader ] 103 %conv218.le = zext i8 %call217.lcssa to i32 104 %call346 = call fastcc zeroext i8 @safe_lshift_func(i8 zeroext %call217.lcssa, i32 %conv218.le) 105 unreachable 106 107for.end411: ; preds = %for.cond8.preheader 108 %call452 = call fastcc i64 @safe_sub_func_int64_t_s_s(i64 undef, i64 4) 109 unreachable 110} 111 112%struct.anon = type { i32 } 113 114@g_57 = hidden local_unnamed_addr global %struct.anon zeroinitializer, align 4 115@g_893 = hidden local_unnamed_addr global %struct.anon zeroinitializer, align 4 116@g_82 = hidden local_unnamed_addr global i32 0, align 4 117 118; Test that the transform bails on finding %conv4, a trunc 119; CHECK-LABEL: call_return_pointer 120; CHECK: sxth 121; CHECK: uxt 122define hidden i32 @call_return_pointer(i8 zeroext %p_13) local_unnamed_addr #0 { 123entry: 124 %conv1 = zext i8 %p_13 to i16 125 %call = tail call i16** @func_62(i8 zeroext undef, i32 undef, i16 signext %conv1, i32* undef) 126 %0 = load i32, i32* getelementptr inbounds (%struct.anon, %struct.anon* @g_893, i32 0, i32 0), align 4 127 %conv2 = trunc i32 %0 to i16 128 br label %for.cond 129 130for.cond: ; preds = %for.cond.backedge, %entry 131 %p_13.addr.0 = phi i8 [ %p_13, %entry ], [ %p_13.addr.0.be, %for.cond.backedge ] 132 %tobool = icmp eq i8 %p_13.addr.0, 0 133 br i1 %tobool, label %for.cond.backedge, label %if.then 134 135for.cond.backedge: ; preds = %for.cond, %if.then 136 %p_13.addr.0.be = phi i8 [ %conv4, %if.then ], [ 0, %for.cond ] 137 br label %for.cond 138 139if.then: ; preds = %for.cond 140 %call3 = tail call fastcc signext i16 @safe_sub_func_int16_t_s_s(i16 signext %conv2) 141 %conv4 = trunc i16 %call3 to i8 142 br label %for.cond.backedge 143} 144 145; Check that d.sroa.0.0.be is promoted passed directly into the tail call. 146; CHECK-LABEL: check_zext_phi_call_arg 147; CHECK-NOT: uxt 148define i32 @check_zext_phi_call_arg() { 149entry: 150 br label %for.cond 151 152for.cond: ; preds = %for.cond.backedge, %entry 153 %d.sroa.0.0 = phi i16 [ 30, %entry ], [ %d.sroa.0.0.be, %for.cond.backedge ] 154 %tobool = icmp eq i16 %d.sroa.0.0, 0 155 br i1 %tobool, label %for.cond.backedge, label %if.then 156 157for.cond.backedge: ; preds = %for.cond, %if.then 158 %d.sroa.0.0.be = phi i16 [ %call, %if.then ], [ 0, %for.cond ] 159 br label %for.cond 160 161if.then: ; preds = %for.cond 162 %d.sroa.0.0.insert.ext = zext i16 %d.sroa.0.0 to i32 163 %call = tail call zeroext i16 bitcast (i16 (...)* @f to i16 (i32)*)(i32 %d.sroa.0.0.insert.ext) #2 164 br label %for.cond.backedge 165} 166 167%struct.atomic_flag = type { i8 } 168 169; CHECK-LABEL: atomic_flag_test_and_set 170; CHECK-NOT: uxt 171define zeroext i1 @atomic_flag_test_and_set(%struct.atomic_flag* %object) { 172entry: 173 %_Value = getelementptr inbounds %struct.atomic_flag, %struct.atomic_flag* %object, i32 0, i32 0 174 %call = tail call arm_aapcscc zeroext i8 @__atomic_exchange_1(i8* %_Value, i8 zeroext 1, i32 5) #1 175 %0 = and i8 %call, 1 176 %tobool = icmp ne i8 %0, 0 177 ret i1 %tobool 178} 179 180; CHECK-LABEL: i1_zeroext_call 181; CHECK: uxt 182define i1 @i1_zeroext_call(i16* %ts, i32 %a, i16* %b, i8* %c) { 183entry: 184 %0 = load i16, i16* %ts, align 2 185 %conv.i860 = trunc i32 %a to i16 186 store i16 %conv.i860, i16* %b, align 2 187 %call.i848 = call zeroext i1 @i1_zeroext(i8* %c, i32 64, i16 zeroext %conv.i860) 188 br i1 %call.i848, label %if.then223, label %if.else227 189 190if.then223: 191 %cmp235 = icmp eq i16 %0, %conv.i860 192 br label %exit 193 194if.else227: 195 %cmp236 = icmp ult i16 %0, %conv.i860 196 br label %exit 197 198exit: 199 %retval = phi i1 [ %cmp235, %if.then223 ], [ %cmp236, %if.else227 ] 200 ret i1 %retval 201} 202 203; CHECK-LABEL: promote_arg_pass_to_call 204; CHECK-NOT: uxt 205define i16 @promote_arg_pass_to_call(i16 zeroext %arg1, i16 zeroext %arg2) { 206 %conv = add nuw i16 %arg1, 15 207 %mul = mul nuw nsw i16 %conv, 3 208 %cmp = icmp ult i16 %mul, %arg2 209 %trunc = trunc i16 %arg1 to i8 210 %res = call zeroext i16 @dummy4(i1 %cmp, i8 %trunc, i16 %arg1) 211 ret i16 %res 212} 213 214 215declare i32 @assert(...) 216declare i8 @dummy_i8(i8) 217declare i8 @dummy2(i8*, i8, i8) 218declare i16 @dummy3(i16) 219declare i16 @dummy4(i1, i8, i16) 220 221declare dso_local i32 @e(...) local_unnamed_addr #1 222declare dso_local zeroext i16 @f(...) local_unnamed_addr #1 223declare dso_local arm_aapcscc i8 @__atomic_exchange_1(i8*, i8, i32) local_unnamed_addr 224 225declare noalias i16** @func_62(i8 zeroext %p_63, i32 %p_64, i16 signext %p_65, i32* nocapture readnone %p_66) 226declare fastcc signext i16 @safe_sub_func_int16_t_s_s(i16 signext %si2) 227declare dso_local fastcc i64 @safe_sub_func_int64_t_s_s(i64, i64) 228declare dso_local fastcc zeroext i8 @safe_lshift_func(i8 zeroext, i32) 229declare dso_local fastcc zeroext i8 @safe_mul_func_uint8_t_u_u(i8 returned zeroext) 230declare i1 @i1_zeroext(i8*, i32, i16 zeroext) 231