1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=aarch64 %s -o - | FileCheck %s 3 4define zeroext i16 @overflow_add(i16 zeroext %a, i16 zeroext %b) { 5; CHECK-LABEL: overflow_add: 6; CHECK: // %bb.0: 7; CHECK-NEXT: add w9, w1, w0 8; CHECK-NEXT: mov w8, #5 // =0x5 9; CHECK-NEXT: orr w9, w9, #0x1 10; CHECK-NEXT: and w9, w9, #0xffff 11; CHECK-NEXT: cmp w9, #1024 12; CHECK-NEXT: mov w9, #2 // =0x2 13; CHECK-NEXT: csel w0, w9, w8, hi 14; CHECK-NEXT: ret 15 %add = add i16 %b, %a 16 %or = or i16 %add, 1 17 %cmp = icmp ugt i16 %or, 1024 18 %res = select i1 %cmp, i16 2, i16 5 19 ret i16 %res 20} 21 22define zeroext i16 @overflow_sub(i16 zeroext %a, i16 zeroext %b) { 23; CHECK-LABEL: overflow_sub: 24; CHECK: // %bb.0: 25; CHECK-NEXT: sub w9, w0, w1 26; CHECK-NEXT: mov w8, #5 // =0x5 27; CHECK-NEXT: orr w9, w9, #0x1 28; CHECK-NEXT: and w9, w9, #0xffff 29; CHECK-NEXT: cmp w9, #1024 30; CHECK-NEXT: mov w9, #2 // =0x2 31; CHECK-NEXT: csel w0, w9, w8, hi 32; CHECK-NEXT: ret 33 %add = sub i16 %a, %b 34 %or = or i16 %add, 1 35 %cmp = icmp ugt i16 %or, 1024 36 %res = select i1 %cmp, i16 2, i16 5 37 ret i16 %res 38} 39 40define zeroext i16 @overflow_mul(i16 zeroext %a, i16 zeroext %b) { 41; CHECK-LABEL: overflow_mul: 42; CHECK: // %bb.0: 43; CHECK-NEXT: mul w9, w1, w0 44; CHECK-NEXT: mov w8, #5 // =0x5 45; CHECK-NEXT: orr w9, w9, #0x1 46; CHECK-NEXT: and w9, w9, #0xffff 47; CHECK-NEXT: cmp w9, #1024 48; CHECK-NEXT: mov w9, #2 // =0x2 49; CHECK-NEXT: csel w0, w9, w8, hi 50; CHECK-NEXT: ret 51 %add = mul i16 %b, %a 52 %or = or i16 %add, 1 53 %cmp = icmp ugt i16 %or, 1024 54 %res = select i1 %cmp, i16 2, i16 5 55 ret i16 %res 56} 57 58define zeroext i16 @overflow_shl(i16 zeroext %a, i16 zeroext %b) { 59; CHECK-LABEL: overflow_shl: 60; CHECK: // %bb.0: 61; CHECK-NEXT: lsl w9, w0, w1 62; CHECK-NEXT: mov w8, #5 // =0x5 63; CHECK-NEXT: orr w9, w9, #0x1 64; CHECK-NEXT: and w9, w9, #0xffff 65; CHECK-NEXT: cmp w9, #1024 66; CHECK-NEXT: mov w9, #2 // =0x2 67; CHECK-NEXT: csel w0, w9, w8, hi 68; CHECK-NEXT: ret 69 %add = shl i16 %a, %b 70 %or = or i16 %add, 1 71 %cmp = icmp ugt i16 %or, 1024 72 %res = select i1 %cmp, i16 2, i16 5 73 ret i16 %res 74} 75 76define i32 @overflow_add_no_consts(i8 zeroext %a, i8 zeroext %b, i8 zeroext %limit) { 77; CHECK-LABEL: overflow_add_no_consts: 78; CHECK: // %bb.0: 79; CHECK-NEXT: add w8, w1, w0 80; CHECK-NEXT: mov w9, #8 // =0x8 81; CHECK-NEXT: cmp w2, w8, uxtb 82; CHECK-NEXT: mov w8, #16 // =0x10 83; CHECK-NEXT: csel w0, w9, w8, lo 84; CHECK-NEXT: ret 85 %add = add i8 %b, %a 86 %cmp = icmp ugt i8 %add, %limit 87 %res = select i1 %cmp, i32 8, i32 16 88 ret i32 %res 89} 90 91define i32 @overflow_add_const_limit(i8 zeroext %a, i8 zeroext %b) { 92; CHECK-LABEL: overflow_add_const_limit: 93; CHECK: // %bb.0: 94; CHECK-NEXT: add w9, w1, w0 95; CHECK-NEXT: mov w8, #16 // =0x10 96; CHECK-NEXT: and w9, w9, #0xff 97; CHECK-NEXT: cmp w9, #128 98; CHECK-NEXT: mov w9, #8 // =0x8 99; CHECK-NEXT: csel w0, w9, w8, hi 100; CHECK-NEXT: ret 101 %add = add i8 %b, %a 102 %cmp = icmp ugt i8 %add, -128 103 %res = select i1 %cmp, i32 8, i32 16 104 ret i32 %res 105} 106 107define i32 @overflow_add_positive_const_limit(i8 zeroext %a) { 108; CHECK-LABEL: overflow_add_positive_const_limit: 109; CHECK: // %bb.0: 110; CHECK-NEXT: sxtb w9, w0 111; CHECK-NEXT: mov w8, #16 // =0x10 112; CHECK-NEXT: cmn w9, #1 113; CHECK-NEXT: mov w9, #8 // =0x8 114; CHECK-NEXT: csel w0, w9, w8, lt 115; CHECK-NEXT: ret 116 %cmp = icmp slt i8 %a, -1 117 %res = select i1 %cmp, i32 8, i32 16 118 ret i32 %res 119} 120 121define i32 @unsafe_add_underflow(i8 zeroext %a) { 122; CHECK-LABEL: unsafe_add_underflow: 123; CHECK: // %bb.0: 124; CHECK-NEXT: mov w8, #16 // =0x10 125; CHECK-NEXT: cmp w0, #1 126; CHECK-NEXT: mov w9, #8 // =0x8 127; CHECK-NEXT: csel w0, w9, w8, eq 128; CHECK-NEXT: ret 129 %cmp = icmp eq i8 %a, 1 130 %res = select i1 %cmp, i32 8, i32 16 131 ret i32 %res 132} 133 134define i32 @safe_add_underflow(i8 zeroext %a) { 135; CHECK-LABEL: safe_add_underflow: 136; CHECK: // %bb.0: 137; CHECK-NEXT: mov w8, #16 // =0x10 138; CHECK-NEXT: cmp w0, #0 139; CHECK-NEXT: mov w9, #8 // =0x8 140; CHECK-NEXT: csel w0, w9, w8, eq 141; CHECK-NEXT: ret 142 %cmp = icmp eq i8 %a, 0 143 %res = select i1 %cmp, i32 8, i32 16 144 ret i32 %res 145} 146 147define i32 @safe_add_underflow_neg(i8 zeroext %a) { 148; CHECK-LABEL: safe_add_underflow_neg: 149; CHECK: // %bb.0: 150; CHECK-NEXT: sub w9, w0, #2 151; CHECK-NEXT: mov w8, #16 // =0x10 152; CHECK-NEXT: cmp w9, #251 153; CHECK-NEXT: mov w9, #8 // =0x8 154; CHECK-NEXT: csel w0, w9, w8, lo 155; CHECK-NEXT: ret 156 %add = add i8 %a, -2 157 %cmp = icmp ult i8 %add, -5 158 %res = select i1 %cmp, i32 8, i32 16 159 ret i32 %res 160} 161 162define i32 @overflow_sub_negative_const_limit(i8 zeroext %a) { 163; CHECK-LABEL: overflow_sub_negative_const_limit: 164; CHECK: // %bb.0: 165; CHECK-NEXT: sxtb w9, w0 166; CHECK-NEXT: mov w8, #16 // =0x10 167; CHECK-NEXT: cmn w9, #1 168; CHECK-NEXT: mov w9, #8 // =0x8 169; CHECK-NEXT: csel w0, w9, w8, lt 170; CHECK-NEXT: ret 171 %cmp = icmp slt i8 %a, -1 172 %res = select i1 %cmp, i32 8, i32 16 173 ret i32 %res 174} 175 176; This is valid so long as the icmp immediate is sext. 177define i32 @sext_sub_underflow(i8 zeroext %a) { 178; CHECK-LABEL: sext_sub_underflow: 179; CHECK: // %bb.0: 180; CHECK-NEXT: sub w9, w0, #6 181; CHECK-NEXT: mov w8, #16 // =0x10 182; CHECK-NEXT: cmn w9, #6 183; CHECK-NEXT: mov w9, #8 // =0x8 184; CHECK-NEXT: csel w0, w9, w8, hi 185; CHECK-NEXT: ret 186 %sub = add i8 %a, -6 187 %cmp = icmp ugt i8 %sub, -6 188 %res = select i1 %cmp, i32 8, i32 16 189 ret i32 %res 190} 191 192define i32 @safe_sub_underflow(i8 zeroext %a) { 193; CHECK-LABEL: safe_sub_underflow: 194; CHECK: // %bb.0: 195; CHECK-NEXT: mov w8, #8 // =0x8 196; CHECK-NEXT: cmp w0, #0 197; CHECK-NEXT: mov w9, #16 // =0x10 198; CHECK-NEXT: csel w0, w9, w8, eq 199; CHECK-NEXT: ret 200 %cmp.not = icmp eq i8 %a, 0 201 %res = select i1 %cmp.not, i32 16, i32 8 202 ret i32 %res 203} 204 205define i32 @safe_sub_underflow_neg(i8 zeroext %a) { 206; CHECK-LABEL: safe_sub_underflow_neg: 207; CHECK: // %bb.0: 208; CHECK-NEXT: sub w9, w0, #4 209; CHECK-NEXT: mov w8, #16 // =0x10 210; CHECK-NEXT: cmp w9, #250 211; CHECK-NEXT: mov w9, #8 // =0x8 212; CHECK-NEXT: csel w0, w9, w8, hi 213; CHECK-NEXT: ret 214 %sub = add i8 %a, -4 215 %cmp = icmp ugt i8 %sub, -6 216 %res = select i1 %cmp, i32 8, i32 16 217 ret i32 %res 218} 219 220; This is valid so long as the icmp immediate is sext. 221define i32 @sext_sub_underflow_neg(i8 zeroext %a) { 222; CHECK-LABEL: sext_sub_underflow_neg: 223; CHECK: // %bb.0: 224; CHECK-NEXT: sub w9, w0, #4 225; CHECK-NEXT: mov w8, #16 // =0x10 226; CHECK-NEXT: cmn w9, #3 227; CHECK-NEXT: mov w9, #8 // =0x8 228; CHECK-NEXT: csel w0, w9, w8, lo 229; CHECK-NEXT: ret 230 %sub = add i8 %a, -4 231 %cmp = icmp ult i8 %sub, -3 232 %res = select i1 %cmp, i32 8, i32 16 233 ret i32 %res 234} 235 236define i32 @safe_sub_imm_var(ptr nocapture readonly %b) local_unnamed_addr #1 { 237; CHECK-LABEL: safe_sub_imm_var: 238; CHECK: // %bb.0: // %entry 239; CHECK-NEXT: mov w0, wzr 240; CHECK-NEXT: ret 241entry: 242 ret i32 0 243} 244 245define i32 @safe_sub_var_imm(ptr nocapture readonly %b) local_unnamed_addr #1 { 246; CHECK-LABEL: safe_sub_var_imm: 247; CHECK: // %bb.0: // %entry 248; CHECK-NEXT: ldrb w8, [x0] 249; CHECK-NEXT: sub w8, w8, #248 250; CHECK-NEXT: cmn w8, #4 251; CHECK-NEXT: cset w0, hi 252; CHECK-NEXT: ret 253entry: 254 %0 = load i8, ptr %b, align 1 255 %sub = add nsw i8 %0, 8 256 %cmp = icmp ugt i8 %sub, -4 257 %conv4 = zext i1 %cmp to i32 258 ret i32 %conv4 259} 260 261define i32 @safe_add_imm_var(ptr nocapture readnone %b) { 262; CHECK-LABEL: safe_add_imm_var: 263; CHECK: // %bb.0: // %entry 264; CHECK-NEXT: mov w0, #1 // =0x1 265; CHECK-NEXT: ret 266entry: 267 ret i32 1 268} 269 270define i32 @safe_add_var_imm(ptr nocapture readnone %b) { 271; CHECK-LABEL: safe_add_var_imm: 272; CHECK: // %bb.0: // %entry 273; CHECK-NEXT: mov w0, #1 // =0x1 274; CHECK-NEXT: ret 275entry: 276 ret i32 1 277} 278 279define i8 @convert_add_order(i8 zeroext %arg) { 280; CHECK-LABEL: convert_add_order: 281; CHECK: // %bb.0: 282; CHECK-NEXT: orr w9, w0, #0x1 283; CHECK-NEXT: mov w8, #1 // =0x1 284; CHECK-NEXT: sub w10, w9, #40 285; CHECK-NEXT: cmp w10, #20 286; CHECK-NEXT: cinc w8, w8, hs 287; CHECK-NEXT: cmp w9, #50 288; CHECK-NEXT: mov w9, #255 // =0xff 289; CHECK-NEXT: csel w8, w8, w9, lo 290; CHECK-NEXT: and w0, w8, w0 291; CHECK-NEXT: ret 292 %shl = or i8 %arg, 1 293 %cmp.0 = icmp ult i8 %shl, 50 294 %sub = add nsw i8 %shl, -40 295 %cmp.1 = icmp ult i8 %sub, 20 296 %mask.sel.v = select i1 %cmp.1, i8 1, i8 2 297 %mask.sel = select i1 %cmp.0, i8 %mask.sel.v, i8 -1 298 %res = and i8 %mask.sel, %arg 299 ret i8 %res 300} 301 302define i8 @underflow_if_sub(i32 %arg, i8 zeroext %arg1) { 303; CHECK-LABEL: underflow_if_sub: 304; CHECK: // %bb.0: 305; CHECK-NEXT: cmp w0, #0 306; CHECK-NEXT: mov w8, #100 // =0x64 307; CHECK-NEXT: cset w9, gt 308; CHECK-NEXT: and w9, w9, w0 309; CHECK-NEXT: add w9, w9, #245 310; CHECK-NEXT: cmp w9, w1 311; CHECK-NEXT: csel w0, w9, w8, lo 312; CHECK-NEXT: ret 313 %cmp = icmp sgt i32 %arg, 0 314 %conv = zext i1 %cmp to i32 315 %and = and i32 %conv, %arg 316 %trunc = trunc i32 %and to i8 317 %conv1 = add nuw nsw i8 %trunc, -11 318 %cmp.1 = icmp ult i8 %conv1, %arg1 319 %res = select i1 %cmp.1, i8 %conv1, i8 100 320 ret i8 %res 321} 322 323define i8 @underflow_if_sub_signext(i32 %arg, i8 signext %arg1) { 324; CHECK-LABEL: underflow_if_sub_signext: 325; CHECK: // %bb.0: 326; CHECK-NEXT: cmp w0, #0 327; CHECK-NEXT: mov w8, #100 // =0x64 328; CHECK-NEXT: cset w9, gt 329; CHECK-NEXT: and w9, w9, w0 330; CHECK-NEXT: add w9, w9, #245 331; CHECK-NEXT: cmp w9, w1, uxtb 332; CHECK-NEXT: csel w0, w9, w8, lo 333; CHECK-NEXT: ret 334 %cmp = icmp sgt i32 %arg, 0 335 %conv = zext i1 %cmp to i32 336 %and = and i32 %conv, %arg 337 %trunc = trunc i32 %and to i8 338 %conv1 = add nuw nsw i8 %trunc, -11 339 %cmp.1 = icmp ult i8 %conv1, %arg1 340 %res = select i1 %cmp.1, i8 %conv1, i8 100 341 ret i8 %res 342} 343