1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv64 -mattr=+m %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 a0, a1, a0 8; CHECK-NEXT: ori a0, a0, 1 9; CHECK-NEXT: slli a0, a0, 48 10; CHECK-NEXT: srli a0, a0, 48 11; CHECK-NEXT: li a1, 1024 12; CHECK-NEXT: bltu a1, a0, .LBB0_2 13; CHECK-NEXT: # %bb.1: 14; CHECK-NEXT: li a0, 5 15; CHECK-NEXT: ret 16; CHECK-NEXT: .LBB0_2: 17; CHECK-NEXT: li a0, 2 18; CHECK-NEXT: ret 19 %add = add i16 %b, %a 20 %or = or i16 %add, 1 21 %cmp = icmp ugt i16 %or, 1024 22 %res = select i1 %cmp, i16 2, i16 5 23 ret i16 %res 24} 25 26define zeroext i16 @overflow_sub(i16 zeroext %a, i16 zeroext %b) { 27; CHECK-LABEL: overflow_sub: 28; CHECK: # %bb.0: 29; CHECK-NEXT: subw a0, a0, a1 30; CHECK-NEXT: ori a0, a0, 1 31; CHECK-NEXT: slli a0, a0, 48 32; CHECK-NEXT: srli a0, a0, 48 33; CHECK-NEXT: li a1, 1024 34; CHECK-NEXT: bltu a1, a0, .LBB1_2 35; CHECK-NEXT: # %bb.1: 36; CHECK-NEXT: li a0, 5 37; CHECK-NEXT: ret 38; CHECK-NEXT: .LBB1_2: 39; CHECK-NEXT: li a0, 2 40; CHECK-NEXT: ret 41 %add = sub i16 %a, %b 42 %or = or i16 %add, 1 43 %cmp = icmp ugt i16 %or, 1024 44 %res = select i1 %cmp, i16 2, i16 5 45 ret i16 %res 46} 47 48define zeroext i16 @overflow_mul(i16 zeroext %a, i16 zeroext %b) { 49; CHECK-LABEL: overflow_mul: 50; CHECK: # %bb.0: 51; CHECK-NEXT: mul a0, a1, a0 52; CHECK-NEXT: ori a0, a0, 1 53; CHECK-NEXT: slli a0, a0, 48 54; CHECK-NEXT: srli a0, a0, 48 55; CHECK-NEXT: li a1, 1024 56; CHECK-NEXT: bltu a1, a0, .LBB2_2 57; CHECK-NEXT: # %bb.1: 58; CHECK-NEXT: li a0, 5 59; CHECK-NEXT: ret 60; CHECK-NEXT: .LBB2_2: 61; CHECK-NEXT: li a0, 2 62; CHECK-NEXT: ret 63 %add = mul i16 %b, %a 64 %or = or i16 %add, 1 65 %cmp = icmp ugt i16 %or, 1024 66 %res = select i1 %cmp, i16 2, i16 5 67 ret i16 %res 68} 69 70define zeroext i16 @overflow_shl(i16 zeroext %a, i16 zeroext %b) { 71; CHECK-LABEL: overflow_shl: 72; CHECK: # %bb.0: 73; CHECK-NEXT: sll a0, a0, a1 74; CHECK-NEXT: ori a0, a0, 1 75; CHECK-NEXT: slli a0, a0, 48 76; CHECK-NEXT: srli a0, a0, 48 77; CHECK-NEXT: li a1, 1024 78; CHECK-NEXT: bltu a1, a0, .LBB3_2 79; CHECK-NEXT: # %bb.1: 80; CHECK-NEXT: li a0, 5 81; CHECK-NEXT: ret 82; CHECK-NEXT: .LBB3_2: 83; CHECK-NEXT: li a0, 2 84; CHECK-NEXT: ret 85 %add = shl i16 %a, %b 86 %or = or i16 %add, 1 87 %cmp = icmp ugt i16 %or, 1024 88 %res = select i1 %cmp, i16 2, i16 5 89 ret i16 %res 90} 91 92define i32 @overflow_add_no_consts(i8 zeroext %a, i8 zeroext %b, i8 zeroext %limit) { 93; CHECK-LABEL: overflow_add_no_consts: 94; CHECK: # %bb.0: 95; CHECK-NEXT: add a0, a1, a0 96; CHECK-NEXT: andi a0, a0, 255 97; CHECK-NEXT: bltu a2, a0, .LBB4_2 98; CHECK-NEXT: # %bb.1: 99; CHECK-NEXT: li a0, 16 100; CHECK-NEXT: ret 101; CHECK-NEXT: .LBB4_2: 102; CHECK-NEXT: li a0, 8 103; CHECK-NEXT: ret 104 %add = add i8 %b, %a 105 %cmp = icmp ugt i8 %add, %limit 106 %res = select i1 %cmp, i32 8, i32 16 107 ret i32 %res 108} 109 110define i32 @overflow_add_const_limit(i8 zeroext %a, i8 zeroext %b) { 111; CHECK-LABEL: overflow_add_const_limit: 112; CHECK: # %bb.0: 113; CHECK-NEXT: add a0, a1, a0 114; CHECK-NEXT: andi a0, a0, 255 115; CHECK-NEXT: li a1, 128 116; CHECK-NEXT: bltu a1, a0, .LBB5_2 117; CHECK-NEXT: # %bb.1: 118; CHECK-NEXT: li a0, 16 119; CHECK-NEXT: ret 120; CHECK-NEXT: .LBB5_2: 121; CHECK-NEXT: li a0, 8 122; CHECK-NEXT: ret 123 %add = add i8 %b, %a 124 %cmp = icmp ugt i8 %add, -128 125 %res = select i1 %cmp, i32 8, i32 16 126 ret i32 %res 127} 128 129define i32 @overflow_add_positive_const_limit(i8 zeroext %a) { 130; CHECK-LABEL: overflow_add_positive_const_limit: 131; CHECK: # %bb.0: 132; CHECK-NEXT: slli a0, a0, 56 133; CHECK-NEXT: srai a0, a0, 56 134; CHECK-NEXT: li a1, -1 135; CHECK-NEXT: blt a0, a1, .LBB6_2 136; CHECK-NEXT: # %bb.1: 137; CHECK-NEXT: li a0, 16 138; CHECK-NEXT: ret 139; CHECK-NEXT: .LBB6_2: 140; CHECK-NEXT: li a0, 8 141; CHECK-NEXT: ret 142 %cmp = icmp slt i8 %a, -1 143 %res = select i1 %cmp, i32 8, i32 16 144 ret i32 %res 145} 146 147define i32 @unsafe_add_underflow(i8 zeroext %a) { 148; CHECK-LABEL: unsafe_add_underflow: 149; CHECK: # %bb.0: 150; CHECK-NEXT: li a1, 1 151; CHECK-NEXT: beq a0, a1, .LBB7_2 152; CHECK-NEXT: # %bb.1: 153; CHECK-NEXT: li a0, 16 154; CHECK-NEXT: ret 155; CHECK-NEXT: .LBB7_2: 156; CHECK-NEXT: li a0, 8 157; CHECK-NEXT: ret 158 %cmp = icmp eq i8 %a, 1 159 %res = select i1 %cmp, i32 8, i32 16 160 ret i32 %res 161} 162 163define i32 @safe_add_underflow(i8 zeroext %a) { 164; CHECK-LABEL: safe_add_underflow: 165; CHECK: # %bb.0: 166; CHECK-NEXT: beqz a0, .LBB8_2 167; CHECK-NEXT: # %bb.1: 168; CHECK-NEXT: li a0, 16 169; CHECK-NEXT: ret 170; CHECK-NEXT: .LBB8_2: 171; CHECK-NEXT: li a0, 8 172; CHECK-NEXT: ret 173 %cmp = icmp eq i8 %a, 0 174 %res = select i1 %cmp, i32 8, i32 16 175 ret i32 %res 176} 177 178define i32 @safe_add_underflow_neg(i8 zeroext %a) { 179; CHECK-LABEL: safe_add_underflow_neg: 180; CHECK: # %bb.0: 181; CHECK-NEXT: addi a0, a0, -2 182; CHECK-NEXT: li a1, 251 183; CHECK-NEXT: bltu a0, a1, .LBB9_2 184; CHECK-NEXT: # %bb.1: 185; CHECK-NEXT: li a0, 16 186; CHECK-NEXT: ret 187; CHECK-NEXT: .LBB9_2: 188; CHECK-NEXT: li a0, 8 189; CHECK-NEXT: ret 190 %add = add i8 %a, -2 191 %cmp = icmp ult i8 %add, -5 192 %res = select i1 %cmp, i32 8, i32 16 193 ret i32 %res 194} 195 196define i32 @overflow_sub_negative_const_limit(i8 zeroext %a) { 197; CHECK-LABEL: overflow_sub_negative_const_limit: 198; CHECK: # %bb.0: 199; CHECK-NEXT: slli a0, a0, 56 200; CHECK-NEXT: srai a0, a0, 56 201; CHECK-NEXT: li a1, -1 202; CHECK-NEXT: blt a0, a1, .LBB10_2 203; CHECK-NEXT: # %bb.1: 204; CHECK-NEXT: li a0, 16 205; CHECK-NEXT: ret 206; CHECK-NEXT: .LBB10_2: 207; CHECK-NEXT: li a0, 8 208; CHECK-NEXT: ret 209 %cmp = icmp slt i8 %a, -1 210 %res = select i1 %cmp, i32 8, i32 16 211 ret i32 %res 212} 213 214; This is valid so long as the icmp immediate is sext. 215define i32 @sext_sub_underflow(i8 zeroext %a) { 216; CHECK-LABEL: sext_sub_underflow: 217; CHECK: # %bb.0: 218; CHECK-NEXT: addi a0, a0, -6 219; CHECK-NEXT: li a1, -6 220; CHECK-NEXT: bltu a1, a0, .LBB11_2 221; CHECK-NEXT: # %bb.1: 222; CHECK-NEXT: li a0, 16 223; CHECK-NEXT: ret 224; CHECK-NEXT: .LBB11_2: 225; CHECK-NEXT: li a0, 8 226; CHECK-NEXT: ret 227 %sub = add i8 %a, -6 228 %cmp = icmp ugt i8 %sub, -6 229 %res = select i1 %cmp, i32 8, i32 16 230 ret i32 %res 231} 232 233define i32 @safe_sub_underflow(i8 zeroext %a) { 234; CHECK-LABEL: safe_sub_underflow: 235; CHECK: # %bb.0: 236; CHECK-NEXT: beqz a0, .LBB12_2 237; CHECK-NEXT: # %bb.1: 238; CHECK-NEXT: li a0, 8 239; CHECK-NEXT: ret 240; CHECK-NEXT: .LBB12_2: 241; CHECK-NEXT: li a0, 16 242; CHECK-NEXT: ret 243 %cmp.not = icmp eq i8 %a, 0 244 %res = select i1 %cmp.not, i32 16, i32 8 245 ret i32 %res 246} 247 248define i32 @safe_sub_underflow_neg(i8 zeroext %a) { 249; CHECK-LABEL: safe_sub_underflow_neg: 250; CHECK: # %bb.0: 251; CHECK-NEXT: addi a0, a0, -4 252; CHECK-NEXT: li a1, 250 253; CHECK-NEXT: bltu a1, a0, .LBB13_2 254; CHECK-NEXT: # %bb.1: 255; CHECK-NEXT: li a0, 16 256; CHECK-NEXT: ret 257; CHECK-NEXT: .LBB13_2: 258; CHECK-NEXT: li a0, 8 259; CHECK-NEXT: ret 260 %sub = add i8 %a, -4 261 %cmp = icmp ugt i8 %sub, -6 262 %res = select i1 %cmp, i32 8, i32 16 263 ret i32 %res 264} 265 266; This is valid so long as the icmp immediate is sext. 267define i32 @sext_sub_underflow_neg(i8 zeroext %a) { 268; CHECK-LABEL: sext_sub_underflow_neg: 269; CHECK: # %bb.0: 270; CHECK-NEXT: addi a0, a0, -4 271; CHECK-NEXT: li a1, -3 272; CHECK-NEXT: bltu a0, a1, .LBB14_2 273; CHECK-NEXT: # %bb.1: 274; CHECK-NEXT: li a0, 16 275; CHECK-NEXT: ret 276; CHECK-NEXT: .LBB14_2: 277; CHECK-NEXT: li a0, 8 278; CHECK-NEXT: ret 279 %sub = add i8 %a, -4 280 %cmp = icmp ult i8 %sub, -3 281 %res = select i1 %cmp, i32 8, i32 16 282 ret i32 %res 283} 284 285define i32 @safe_sub_imm_var(ptr nocapture readonly %b) local_unnamed_addr #1 { 286; CHECK-LABEL: safe_sub_imm_var: 287; CHECK: # %bb.0: # %entry 288; CHECK-NEXT: li a0, 0 289; CHECK-NEXT: ret 290entry: 291 ret i32 0 292} 293 294define i32 @safe_sub_var_imm(ptr nocapture readonly %b) local_unnamed_addr #1 { 295; CHECK-LABEL: safe_sub_var_imm: 296; CHECK: # %bb.0: # %entry 297; CHECK-NEXT: lbu a0, 0(a0) 298; CHECK-NEXT: addi a0, a0, -248 299; CHECK-NEXT: sltiu a0, a0, -3 300; CHECK-NEXT: xori a0, a0, 1 301; CHECK-NEXT: ret 302entry: 303 %0 = load i8, ptr %b, align 1 304 %sub = add nsw i8 %0, 8 305 %cmp = icmp ugt i8 %sub, -4 306 %conv4 = zext i1 %cmp to i32 307 ret i32 %conv4 308} 309 310define i32 @safe_add_imm_var(ptr nocapture readnone %b) { 311; CHECK-LABEL: safe_add_imm_var: 312; CHECK: # %bb.0: # %entry 313; CHECK-NEXT: li a0, 1 314; CHECK-NEXT: ret 315entry: 316 ret i32 1 317} 318 319define i32 @safe_add_var_imm(ptr nocapture readnone %b) { 320; CHECK-LABEL: safe_add_var_imm: 321; CHECK: # %bb.0: # %entry 322; CHECK-NEXT: li a0, 1 323; CHECK-NEXT: ret 324entry: 325 ret i32 1 326} 327 328define i8 @convert_add_order(i8 zeroext %arg) { 329; CHECK-LABEL: convert_add_order: 330; CHECK: # %bb.0: 331; CHECK-NEXT: ori a1, a0, 1 332; CHECK-NEXT: li a2, 50 333; CHECK-NEXT: bltu a1, a2, .LBB19_2 334; CHECK-NEXT: # %bb.1: 335; CHECK-NEXT: li a1, 255 336; CHECK-NEXT: and a0, a1, a0 337; CHECK-NEXT: ret 338; CHECK-NEXT: .LBB19_2: 339; CHECK-NEXT: addi a1, a1, -40 340; CHECK-NEXT: sltiu a1, a1, 20 341; CHECK-NEXT: li a2, 2 342; CHECK-NEXT: sub a1, a2, a1 343; CHECK-NEXT: and a0, a1, a0 344; CHECK-NEXT: ret 345 %shl = or i8 %arg, 1 346 %cmp.0 = icmp ult i8 %shl, 50 347 %sub = add nsw i8 %shl, -40 348 %cmp.1 = icmp ult i8 %sub, 20 349 %mask.sel.v = select i1 %cmp.1, i8 1, i8 2 350 %mask.sel = select i1 %cmp.0, i8 %mask.sel.v, i8 -1 351 %res = and i8 %mask.sel, %arg 352 ret i8 %res 353} 354 355define i8 @underflow_if_sub(i32 %arg, i8 zeroext %arg1) { 356; CHECK-LABEL: underflow_if_sub: 357; CHECK: # %bb.0: 358; CHECK-NEXT: sext.w a2, a0 359; CHECK-NEXT: sgtz a2, a2 360; CHECK-NEXT: and a0, a2, a0 361; CHECK-NEXT: addi a0, a0, 245 362; CHECK-NEXT: bltu a0, a1, .LBB20_2 363; CHECK-NEXT: # %bb.1: 364; CHECK-NEXT: li a0, 100 365; CHECK-NEXT: .LBB20_2: 366; CHECK-NEXT: ret 367 %cmp = icmp sgt i32 %arg, 0 368 %conv = zext i1 %cmp to i32 369 %and = and i32 %conv, %arg 370 %trunc = trunc i32 %and to i8 371 %conv1 = add nuw nsw i8 %trunc, -11 372 %cmp.1 = icmp ult i8 %conv1, %arg1 373 %res = select i1 %cmp.1, i8 %conv1, i8 100 374 ret i8 %res 375} 376 377define i8 @underflow_if_sub_signext(i32 %arg, i8 signext %arg1) { 378; CHECK-LABEL: underflow_if_sub_signext: 379; CHECK: # %bb.0: 380; CHECK-NEXT: sext.w a2, a0 381; CHECK-NEXT: andi a1, a1, 255 382; CHECK-NEXT: sgtz a2, a2 383; CHECK-NEXT: and a0, a2, a0 384; CHECK-NEXT: addi a0, a0, 245 385; CHECK-NEXT: bltu a0, a1, .LBB21_2 386; CHECK-NEXT: # %bb.1: 387; CHECK-NEXT: li a0, 100 388; CHECK-NEXT: .LBB21_2: 389; CHECK-NEXT: ret 390 %cmp = icmp sgt i32 %arg, 0 391 %conv = zext i1 %cmp to i32 392 %and = and i32 %conv, %arg 393 %trunc = trunc i32 %and to i8 394 %conv1 = add nuw nsw i8 %trunc, -11 395 %cmp.1 = icmp ult i8 %conv1, %arg1 396 %res = select i1 %cmp.1, i8 %conv1, i8 100 397 ret i8 %res 398} 399