1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -correlated-propagation < %s | FileCheck %s 3 4; Check that debug locations are preserved. For more info see: 5; https://llvm.org/docs/SourceLevelDebugging.html#fixing-errors 6; RUN: opt < %s -enable-debugify -correlated-propagation -S 2>&1 | \ 7; RUN: FileCheck %s -check-prefix=DEBUG 8; DEBUG: CheckModuleDebugify: PASS 9 10declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) 11 12declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32) 13 14declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) 15 16declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) 17 18declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32) 19 20declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32) 21 22declare { i8, i1 } @llvm.umul.with.overflow.i8(i8, i8) 23 24declare { <2 x i32>, <2 x i1> } @llvm.uadd.with.overflow.v2i32(<2 x i32>, <2 x i32>) 25 26declare i8 @llvm.uadd.sat.i8(i8, i8) 27declare i8 @llvm.sadd.sat.i8(i8, i8) 28declare i8 @llvm.usub.sat.i8(i8, i8) 29declare i8 @llvm.ssub.sat.i8(i8, i8) 30declare <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8>, <2 x i8>) 31 32declare void @llvm.trap() 33 34 35define i32 @signed_add(i32 %x, i32 %y) { 36; CHECK-LABEL: @signed_add( 37; CHECK-NEXT: entry: 38; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[Y:%.*]], 0 39; CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LOR_LHS_FALSE:%.*]] 40; CHECK: land.lhs.true: 41; CHECK-NEXT: [[TMP0:%.*]] = sub nuw nsw i32 2147483647, [[Y]] 42; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0 43; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 44; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[CONT:%.*]] 45; CHECK: trap: 46; CHECK-NEXT: tail call void @llvm.trap() 47; CHECK-NEXT: unreachable 48; CHECK: cont: 49; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0 50; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[TMP3]], [[X:%.*]] 51; CHECK-NEXT: br i1 [[CMP1]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]] 52; CHECK: lor.lhs.false: 53; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[Y]], 0 54; CHECK-NEXT: br i1 [[CMP2]], label [[LAND_LHS_TRUE3:%.*]], label [[COND_FALSE]] 55; CHECK: land.lhs.true3: 56; CHECK-NEXT: [[TMP4:%.*]] = sub nsw i32 -2147483648, [[Y]] 57; CHECK-NEXT: [[TMP5:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP4]], 0 58; CHECK-NEXT: [[TMP6:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 59; CHECK-NEXT: br i1 [[TMP6]], label [[TRAP]], label [[CONT4:%.*]] 60; CHECK: cont4: 61; CHECK-NEXT: [[TMP7:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 62; CHECK-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[TMP7]], [[X]] 63; CHECK-NEXT: br i1 [[CMP5]], label [[COND_END]], label [[COND_FALSE]] 64; CHECK: cond.false: 65; CHECK-NEXT: [[TMP8:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X]], i32 [[Y]]) 66; CHECK-NEXT: [[TMP9:%.*]] = extractvalue { i32, i1 } [[TMP8]], 0 67; CHECK-NEXT: [[TMP10:%.*]] = extractvalue { i32, i1 } [[TMP8]], 1 68; CHECK-NEXT: br i1 [[TMP10]], label [[TRAP]], label [[COND_END]] 69; CHECK: cond.end: 70; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[CONT4]] ], [ 0, [[CONT]] ], [ [[TMP9]], [[COND_FALSE]] ] 71; CHECK-NEXT: ret i32 [[COND]] 72; 73entry: 74 %cmp = icmp sgt i32 %y, 0 75 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false 76 77land.lhs.true: ; preds = %entry 78 %0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 2147483647, i32 %y) 79 %1 = extractvalue { i32, i1 } %0, 1 80 br i1 %1, label %trap, label %cont 81 82trap: ; preds = %land.lhs.true, %land.lhs.true3, %cond.false 83 tail call void @llvm.trap() 84 unreachable 85 86cont: ; preds = %land.lhs.true 87 %2 = extractvalue { i32, i1 } %0, 0 88 %cmp1 = icmp slt i32 %2, %x 89 br i1 %cmp1, label %cond.end, label %cond.false 90 91lor.lhs.false: ; preds = %entry 92 %cmp2 = icmp slt i32 %y, 0 93 br i1 %cmp2, label %land.lhs.true3, label %cond.false 94 95land.lhs.true3: ; preds = %lor.lhs.false 96 %3 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 -2147483648, i32 %y) 97 %4 = extractvalue { i32, i1 } %3, 1 98 br i1 %4, label %trap, label %cont4 99 100cont4: ; preds = %land.lhs.true3 101 %5 = extractvalue { i32, i1 } %3, 0 102 %cmp5 = icmp sgt i32 %5, %x 103 br i1 %cmp5, label %cond.end, label %cond.false 104 105cond.false: ; preds = %cont, %cont4, %lor.lhs.false 106 %6 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 %y) 107 %7 = extractvalue { i32, i1 } %6, 0 108 %8 = extractvalue { i32, i1 } %6, 1 109 br i1 %8, label %trap, label %cond.end 110 111cond.end: ; preds = %cond.false, %cont, %cont4 112 %cond = phi i32 [ 0, %cont4 ], [ 0, %cont ], [ %7, %cond.false ] 113 ret i32 %cond 114} 115 116define i32 @unsigned_add(i32 %x, i32 %y) { 117; CHECK-LABEL: @unsigned_add( 118; CHECK-NEXT: entry: 119; CHECK-NEXT: [[TMP0:%.*]] = sub nuw nsw i32 -1, [[Y:%.*]] 120; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0 121; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 122; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[CONT:%.*]] 123; CHECK: trap: 124; CHECK-NEXT: tail call void @llvm.trap() 125; CHECK-NEXT: unreachable 126; CHECK: cont: 127; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0 128; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[TMP3]], [[X:%.*]] 129; CHECK-NEXT: br i1 [[CMP1]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]] 130; CHECK: cond.false: 131; CHECK-NEXT: [[TMP4:%.*]] = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X]], i32 [[Y]]) 132; CHECK-NEXT: [[TMP5:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 133; CHECK-NEXT: [[TMP6:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 134; CHECK-NEXT: br i1 [[TMP6]], label [[TRAP]], label [[COND_END]] 135; CHECK: cond.end: 136; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[CONT]] ], [ [[TMP5]], [[COND_FALSE]] ] 137; CHECK-NEXT: ret i32 [[COND]] 138; 139entry: 140 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 -1, i32 %y) 141 %1 = extractvalue { i32, i1 } %0, 1 142 br i1 %1, label %trap, label %cont 143 144trap: ; preds = %cond.false, %entry 145 tail call void @llvm.trap() 146 unreachable 147 148cont: ; preds = %entry 149 %2 = extractvalue { i32, i1 } %0, 0 150 %cmp1 = icmp ult i32 %2, %x 151 br i1 %cmp1, label %cond.end, label %cond.false 152 153cond.false: ; preds = %cont 154 %3 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y) 155 %4 = extractvalue { i32, i1 } %3, 0 156 %5 = extractvalue { i32, i1 } %3, 1 157 br i1 %5, label %trap, label %cond.end 158 159cond.end: ; preds = %cond.false, %cont 160 %cond = phi i32 [ 0, %cont ], [ %4, %cond.false ] 161 ret i32 %cond 162} 163 164define i32 @signed_sub(i32 %x, i32 %y) { 165; CHECK-LABEL: @signed_sub( 166; CHECK-NEXT: entry: 167; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[Y:%.*]], 0 168; CHECK-NEXT: br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LOR_LHS_FALSE:%.*]] 169; CHECK: land.lhs.true: 170; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[Y]], 2147483647 171; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0 172; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 173; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[CONT:%.*]] 174; CHECK: trap: 175; CHECK-NEXT: tail call void @llvm.trap() 176; CHECK-NEXT: unreachable 177; CHECK: cont: 178; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0 179; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[TMP3]], [[X:%.*]] 180; CHECK-NEXT: br i1 [[CMP1]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]] 181; CHECK: lor.lhs.false: 182; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[Y]], 0 183; CHECK-NEXT: br i1 [[CMP2]], label [[COND_FALSE]], label [[LAND_LHS_TRUE3:%.*]] 184; CHECK: land.lhs.true3: 185; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i32 [[Y]], -2147483648 186; CHECK-NEXT: [[TMP5:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP4]], 0 187; CHECK-NEXT: [[TMP6:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1 188; CHECK-NEXT: br i1 [[TMP6]], label [[TRAP]], label [[CONT4:%.*]] 189; CHECK: cont4: 190; CHECK-NEXT: [[TMP7:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0 191; CHECK-NEXT: [[CMP5:%.*]] = icmp sgt i32 [[TMP7]], [[X]] 192; CHECK-NEXT: br i1 [[CMP5]], label [[COND_END]], label [[COND_FALSE]] 193; CHECK: cond.false: 194; CHECK-NEXT: [[TMP8:%.*]] = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 [[X]], i32 [[Y]]) 195; CHECK-NEXT: [[TMP9:%.*]] = extractvalue { i32, i1 } [[TMP8]], 0 196; CHECK-NEXT: [[TMP10:%.*]] = extractvalue { i32, i1 } [[TMP8]], 1 197; CHECK-NEXT: br i1 [[TMP10]], label [[TRAP]], label [[COND_END]] 198; CHECK: cond.end: 199; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[CONT4]] ], [ 0, [[CONT]] ], [ [[TMP9]], [[COND_FALSE]] ] 200; CHECK-NEXT: ret i32 [[COND]] 201; 202entry: 203 %cmp = icmp slt i32 %y, 0 204 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false 205 206land.lhs.true: ; preds = %entry 207 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %y, i32 2147483647) 208 %1 = extractvalue { i32, i1 } %0, 1 209 br i1 %1, label %trap, label %cont 210 211trap: ; preds = %land.lhs.true, %land.lhs.true3, %cond.false 212 tail call void @llvm.trap() 213 unreachable 214 215cont: ; preds = %land.lhs.true 216 %2 = extractvalue { i32, i1 } %0, 0 217 %cmp1 = icmp slt i32 %2, %x 218 br i1 %cmp1, label %cond.end, label %cond.false 219 220lor.lhs.false: ; preds = %entry 221 %cmp2 = icmp eq i32 %y, 0 222 br i1 %cmp2, label %cond.false, label %land.lhs.true3 223 224land.lhs.true3: ; preds = %lor.lhs.false 225 %3 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %y, i32 -2147483648) 226 %4 = extractvalue { i32, i1 } %3, 1 227 br i1 %4, label %trap, label %cont4 228 229cont4: ; preds = %land.lhs.true3 230 %5 = extractvalue { i32, i1 } %3, 0 231 %cmp5 = icmp sgt i32 %5, %x 232 br i1 %cmp5, label %cond.end, label %cond.false 233 234cond.false: ; preds = %lor.lhs.false, %cont, %cont4 235 %6 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %x, i32 %y) 236 %7 = extractvalue { i32, i1 } %6, 0 237 %8 = extractvalue { i32, i1 } %6, 1 238 br i1 %8, label %trap, label %cond.end 239 240cond.end: ; preds = %cond.false, %cont, %cont4 241 %cond = phi i32 [ 0, %cont4 ], [ 0, %cont ], [ %7, %cond.false ] 242 ret i32 %cond 243} 244 245define i32 @unsigned_sub(i32 %x, i32 %y) { 246; CHECK-LABEL: @unsigned_sub( 247; CHECK-NEXT: entry: 248; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]] 249; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]] 250; CHECK: cond.false: 251; CHECK-NEXT: [[TMP0:%.*]] = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 [[X]], i32 [[Y]]) 252; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0 253; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1 254; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[COND_END]] 255; CHECK: trap: 256; CHECK-NEXT: tail call void @llvm.trap() 257; CHECK-NEXT: unreachable 258; CHECK: cond.end: 259; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP1]], [[COND_FALSE]] ] 260; CHECK-NEXT: ret i32 [[COND]] 261; 262entry: 263 %cmp = icmp ult i32 %x, %y 264 br i1 %cmp, label %cond.end, label %cond.false 265 266cond.false: ; preds = %entry 267 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %x, i32 %y) 268 %1 = extractvalue { i32, i1 } %0, 0 269 %2 = extractvalue { i32, i1 } %0, 1 270 br i1 %2, label %trap, label %cond.end 271 272trap: ; preds = %cond.false 273 tail call void @llvm.trap() 274 unreachable 275 276cond.end: ; preds = %cond.false, %entry 277 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ] 278 ret i32 %cond 279} 280 281define i32 @signed_add_r1(i32 %x) { 282; CHECK-LABEL: @signed_add_r1( 283; CHECK-NEXT: entry: 284; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 2147483647 285; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]] 286; CHECK: cond.false: 287; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[X]], 1 288; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0 289; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0 290; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 291; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]] 292; CHECK: trap: 293; CHECK-NEXT: tail call void @llvm.trap() 294; CHECK-NEXT: unreachable 295; CHECK: cond.end: 296; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ] 297; CHECK-NEXT: ret i32 [[COND]] 298; 299entry: 300 %cmp = icmp eq i32 %x, 2147483647 301 br i1 %cmp, label %cond.end, label %cond.false 302 303cond.false: ; preds = %entry 304 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 1) 305 %1 = extractvalue { i32, i1 } %0, 0 306 %2 = extractvalue { i32, i1 } %0, 1 307 br i1 %2, label %trap, label %cond.end 308 309trap: ; preds = %cond.false 310 tail call void @llvm.trap() 311 unreachable 312 313cond.end: ; preds = %cond.false, %entry 314 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ] 315 ret i32 %cond 316} 317 318define i32 @unsigned_add_r1(i32 %x) { 319; CHECK-LABEL: @unsigned_add_r1( 320; CHECK-NEXT: entry: 321; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], -1 322; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]] 323; CHECK: cond.false: 324; CHECK-NEXT: [[TMP0:%.*]] = add nuw i32 [[X]], 1 325; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0 326; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0 327; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 328; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]] 329; CHECK: trap: 330; CHECK-NEXT: tail call void @llvm.trap() 331; CHECK-NEXT: unreachable 332; CHECK: cond.end: 333; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ] 334; CHECK-NEXT: ret i32 [[COND]] 335; 336entry: 337 %cmp = icmp eq i32 %x, -1 338 br i1 %cmp, label %cond.end, label %cond.false 339 340cond.false: ; preds = %entry 341 %0 = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 1) 342 %1 = extractvalue { i32, i1 } %0, 0 343 %2 = extractvalue { i32, i1 } %0, 1 344 br i1 %2, label %trap, label %cond.end 345 346trap: ; preds = %cond.false 347 tail call void @llvm.trap() 348 unreachable 349 350cond.end: ; preds = %cond.false, %entry 351 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ] 352 ret i32 %cond 353} 354 355define i32 @signed_sub_r1(i32 %x) { 356; CHECK-LABEL: @signed_sub_r1( 357; CHECK-NEXT: entry: 358; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], -2147483648 359; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]] 360; CHECK: cond.false: 361; CHECK-NEXT: [[TMP0:%.*]] = sub nsw i32 [[X]], 1 362; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0 363; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0 364; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 365; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]] 366; CHECK: trap: 367; CHECK-NEXT: tail call void @llvm.trap() 368; CHECK-NEXT: unreachable 369; CHECK: cond.end: 370; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ] 371; CHECK-NEXT: ret i32 [[COND]] 372; 373entry: 374 %cmp = icmp eq i32 %x, -2147483648 375 br i1 %cmp, label %cond.end, label %cond.false 376 377cond.false: ; preds = %entry 378 %0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %x, i32 1) 379 %1 = extractvalue { i32, i1 } %0, 0 380 %2 = extractvalue { i32, i1 } %0, 1 381 br i1 %2, label %trap, label %cond.end 382 383trap: ; preds = %cond.false 384 tail call void @llvm.trap() 385 unreachable 386 387cond.end: ; preds = %cond.false, %entry 388 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ] 389 ret i32 %cond 390} 391 392define i32 @unsigned_sub_r1(i32 %x) { 393; CHECK-LABEL: @unsigned_sub_r1( 394; CHECK-NEXT: entry: 395; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 0 396; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]] 397; CHECK: cond.false: 398; CHECK-NEXT: [[TMP0:%.*]] = sub nuw i32 [[X]], 1 399; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0 400; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0 401; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 402; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]] 403; CHECK: trap: 404; CHECK-NEXT: tail call void @llvm.trap() 405; CHECK-NEXT: unreachable 406; CHECK: cond.end: 407; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ] 408; CHECK-NEXT: ret i32 [[COND]] 409; 410entry: 411 %cmp = icmp eq i32 %x, 0 412 br i1 %cmp, label %cond.end, label %cond.false 413 414cond.false: ; preds = %entry 415 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %x, i32 1) 416 %1 = extractvalue { i32, i1 } %0, 0 417 %2 = extractvalue { i32, i1 } %0, 1 418 br i1 %2, label %trap, label %cond.end 419 420trap: ; preds = %cond.false 421 tail call void @llvm.trap() 422 unreachable 423 424cond.end: ; preds = %cond.false, %entry 425 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ] 426 ret i32 %cond 427} 428 429define i32 @signed_add_rn1(i32 %x) { 430; CHECK-LABEL: @signed_add_rn1( 431; CHECK-NEXT: entry: 432; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], -2147483648 433; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]] 434; CHECK: cond.false: 435; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[X]], -1 436; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0 437; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0 438; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 439; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]] 440; CHECK: trap: 441; CHECK-NEXT: tail call void @llvm.trap() 442; CHECK-NEXT: unreachable 443; CHECK: cond.end: 444; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ] 445; CHECK-NEXT: ret i32 [[COND]] 446; 447entry: 448 %cmp = icmp eq i32 %x, -2147483648 449 br i1 %cmp, label %cond.end, label %cond.false 450 451cond.false: ; preds = %entry 452 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 -1) 453 %1 = extractvalue { i32, i1 } %0, 0 454 %2 = extractvalue { i32, i1 } %0, 1 455 br i1 %2, label %trap, label %cond.end 456 457trap: ; preds = %cond.false 458 tail call void @llvm.trap() 459 unreachable 460 461cond.end: ; preds = %cond.false, %entry 462 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ] 463 ret i32 %cond 464} 465 466define i32 @signed_sub_rn1(i32 %x) { 467; CHECK-LABEL: @signed_sub_rn1( 468; CHECK-NEXT: entry: 469; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], 2147483647 470; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]] 471; CHECK: cond.false: 472; CHECK-NEXT: [[TMP0:%.*]] = sub nsw i32 [[X]], -1 473; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0 474; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0 475; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 476; CHECK-NEXT: br i1 [[TMP3]], label [[TRAP:%.*]], label [[COND_END]] 477; CHECK: trap: 478; CHECK-NEXT: tail call void @llvm.trap() 479; CHECK-NEXT: unreachable 480; CHECK: cond.end: 481; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2]], [[COND_FALSE]] ] 482; CHECK-NEXT: ret i32 [[COND]] 483; 484entry: 485 %cmp = icmp eq i32 %x, 2147483647 486 br i1 %cmp, label %cond.end, label %cond.false 487 488cond.false: ; preds = %entry 489 %0 = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %x, i32 -1) 490 %1 = extractvalue { i32, i1 } %0, 0 491 %2 = extractvalue { i32, i1 } %0, 1 492 br i1 %2, label %trap, label %cond.end 493 494trap: ; preds = %cond.false 495 tail call void @llvm.trap() 496 unreachable 497 498cond.end: ; preds = %cond.false, %entry 499 %cond = phi i32 [ 0, %entry ], [ %1, %cond.false ] 500 ret i32 %cond 501} 502 503define i32 @unsigned_mul(i32 %x) { 504; CHECK-LABEL: @unsigned_mul( 505; CHECK-NEXT: entry: 506; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], 10000 507; CHECK-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]] 508; CHECK: cond.false: 509; CHECK-NEXT: [[MULO1:%.*]] = mul nuw nsw i32 [[X]], 100 510; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[MULO1]], 0 511; CHECK-NEXT: [[RES:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0 512; CHECK-NEXT: [[OV:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1 513; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[COND_END]] 514; CHECK: trap: 515; CHECK-NEXT: tail call void @llvm.trap() 516; CHECK-NEXT: unreachable 517; CHECK: cond.end: 518; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RES]], [[COND_FALSE]] ] 519; CHECK-NEXT: ret i32 [[COND]] 520; 521entry: 522 %cmp = icmp ugt i32 %x, 10000 523 br i1 %cmp, label %cond.end, label %cond.false 524 525cond.false: ; preds = %entry 526 %mulo = tail call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 100) 527 %res = extractvalue { i32, i1 } %mulo, 0 528 %ov = extractvalue { i32, i1 } %mulo, 1 529 br i1 %ov, label %trap, label %cond.end 530 531trap: ; preds = %cond.false 532 tail call void @llvm.trap() 533 unreachable 534 535cond.end: ; preds = %cond.false, %entry 536 %cond = phi i32 [ 0, %entry ], [ %res, %cond.false ] 537 ret i32 %cond 538} 539 540define i32 @signed_mul(i32 %x) { 541; CHECK-LABEL: @signed_mul( 542; CHECK-NEXT: entry: 543; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[X:%.*]], 10000 544; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], -10000 545; CHECK-NEXT: [[CMP3:%.*]] = or i1 [[CMP1]], [[CMP2]] 546; CHECK-NEXT: br i1 [[CMP3]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]] 547; CHECK: cond.false: 548; CHECK-NEXT: [[MULO1:%.*]] = mul nsw i32 [[X]], 100 549; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[MULO1]], 0 550; CHECK-NEXT: [[RES:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0 551; CHECK-NEXT: [[OV:%.*]] = extractvalue { i32, i1 } [[TMP0]], 1 552; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[COND_END]] 553; CHECK: trap: 554; CHECK-NEXT: tail call void @llvm.trap() 555; CHECK-NEXT: unreachable 556; CHECK: cond.end: 557; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[RES]], [[COND_FALSE]] ] 558; CHECK-NEXT: ret i32 [[COND]] 559; 560entry: 561 %cmp1 = icmp sgt i32 %x, 10000 562 %cmp2 = icmp slt i32 %x, -10000 563 %cmp3 = or i1 %cmp1, %cmp2 564 br i1 %cmp3, label %cond.end, label %cond.false 565 566cond.false: ; preds = %entry 567 %mulo = tail call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %x, i32 100) 568 %res = extractvalue { i32, i1 } %mulo, 0 569 %ov = extractvalue { i32, i1 } %mulo, 1 570 br i1 %ov, label %trap, label %cond.end 571 572trap: ; preds = %cond.false 573 tail call void @llvm.trap() 574 unreachable 575 576cond.end: ; preds = %cond.false, %entry 577 %cond = phi i32 [ 0, %entry ], [ %res, %cond.false ] 578 ret i32 %cond 579} 580 581declare i32 @bar(i32) 582 583define void @unsigned_loop(i32 %i) { 584; CHECK-LABEL: @unsigned_loop( 585; CHECK-NEXT: entry: 586; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[I:%.*]], 0 587; CHECK-NEXT: br i1 [[CMP3]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]] 588; CHECK: while.body.preheader: 589; CHECK-NEXT: br label [[WHILE_BODY:%.*]] 590; CHECK: while.body: 591; CHECK-NEXT: [[I_ADDR_04:%.*]] = phi i32 [ [[TMP3:%.*]], [[CONT:%.*]] ], [ [[I]], [[WHILE_BODY_PREHEADER]] ] 592; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @bar(i32 [[I_ADDR_04]]) 593; CHECK-NEXT: [[TMP0:%.*]] = sub nuw i32 [[I_ADDR_04]], 1 594; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0 595; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 596; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[CONT]] 597; CHECK: trap: 598; CHECK-NEXT: tail call void @llvm.trap() 599; CHECK-NEXT: unreachable 600; CHECK: cont: 601; CHECK-NEXT: [[TMP3]] = extractvalue { i32, i1 } [[TMP1]], 0 602; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP3]], 0 603; CHECK-NEXT: br i1 [[CMP]], label [[WHILE_END]], label [[WHILE_BODY]] 604; CHECK: while.end: 605; CHECK-NEXT: ret void 606; 607entry: 608 %cmp3 = icmp eq i32 %i, 0 609 br i1 %cmp3, label %while.end, label %while.body.preheader 610 611while.body.preheader: ; preds = %entry 612 br label %while.body 613 614while.body: ; preds = %while.body.preheader, %cont 615 %i.addr.04 = phi i32 [ %2, %cont ], [ %i, %while.body.preheader ] 616 %call = tail call i32 @bar(i32 %i.addr.04) 617 %0 = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %i.addr.04, i32 1) 618 %1 = extractvalue { i32, i1 } %0, 1 619 br i1 %1, label %trap, label %cont 620 621trap: ; preds = %while.body 622 tail call void @llvm.trap() 623 unreachable 624 625cont: ; preds = %while.body 626 %2 = extractvalue { i32, i1 } %0, 0 627 %cmp = icmp eq i32 %2, 0 628 br i1 %cmp, label %while.end, label %while.body 629 630while.end: ; preds = %cont, %entry 631 ret void 632} 633 634define void @intrinsic_into_phi(i32 %n) { 635; CHECK-LABEL: @intrinsic_into_phi( 636; CHECK-NEXT: entry: 637; CHECK-NEXT: br label [[CONT:%.*]] 638; CHECK: for.cond: 639; CHECK-NEXT: [[TMP0:%.*]] = add nsw i32 [[DOTLCSSA:%.*]], 1 640; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[TMP0]], 0 641; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1 642; CHECK-NEXT: br i1 [[TMP2]], label [[TRAP:%.*]], label [[CONT]] 643; CHECK: trap: 644; CHECK-NEXT: tail call void @llvm.trap() 645; CHECK-NEXT: unreachable 646; CHECK: cont: 647; CHECK-NEXT: [[TMP3:%.*]] = phi { i32, i1 } [ zeroinitializer, [[ENTRY:%.*]] ], [ [[TMP1]], [[FOR_COND:%.*]] ] 648; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i32, i1 } [[TMP3]], 0 649; CHECK-NEXT: [[CALL9:%.*]] = tail call i32 @bar(i32 [[TMP4]]) 650; CHECK-NEXT: [[TOBOOL10:%.*]] = icmp eq i32 [[CALL9]], 0 651; CHECK-NEXT: br i1 [[TOBOOL10]], label [[WHILE_END:%.*]], label [[WHILE_BODY_PREHEADER:%.*]] 652; CHECK: while.body.preheader: 653; CHECK-NEXT: br label [[WHILE_BODY:%.*]] 654; CHECK: while.cond: 655; CHECK-NEXT: [[TMP5:%.*]] = extractvalue { i32, i1 } [[TMP7:%.*]], 0 656; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @bar(i32 [[TMP5]]) 657; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[CALL]], 0 658; CHECK-NEXT: br i1 [[TOBOOL]], label [[WHILE_END]], label [[WHILE_BODY]] 659; CHECK: while.body: 660; CHECK-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP5]], [[WHILE_COND:%.*]] ], [ [[TMP4]], [[WHILE_BODY_PREHEADER]] ] 661; CHECK-NEXT: [[TMP7]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[TMP6]], i32 1) 662; CHECK-NEXT: [[TMP8:%.*]] = extractvalue { i32, i1 } [[TMP7]], 1 663; CHECK-NEXT: br i1 [[TMP8]], label [[TRAP]], label [[WHILE_COND]] 664; CHECK: while.end: 665; CHECK-NEXT: [[DOTLCSSA]] = phi i32 [ [[TMP4]], [[CONT]] ], [ [[TMP5]], [[WHILE_COND]] ] 666; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[DOTLCSSA]], [[N:%.*]] 667; CHECK-NEXT: br i1 [[CMP]], label [[FOR_COND]], label [[CLEANUP2:%.*]] 668; CHECK: cleanup2: 669; CHECK-NEXT: ret void 670; 671entry: 672 br label %cont 673 674for.cond: ; preds = %while.end 675 %0 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %.lcssa, i32 1) 676 %1 = extractvalue { i32, i1 } %0, 1 677 br i1 %1, label %trap, label %cont 678 679trap: ; preds = %for.cond, %while.body 680 tail call void @llvm.trap() 681 unreachable 682 683cont: ; preds = %entry, %for.cond 684 %2 = phi { i32, i1 } [ zeroinitializer, %entry ], [ %0, %for.cond ] 685 %3 = extractvalue { i32, i1 } %2, 0 686 %call9 = tail call i32 @bar(i32 %3) 687 %tobool10 = icmp eq i32 %call9, 0 688 br i1 %tobool10, label %while.end, label %while.body.preheader 689 690while.body.preheader: ; preds = %cont 691 br label %while.body 692 693while.cond: ; preds = %while.body 694 %4 = extractvalue { i32, i1 } %6, 0 695 %call = tail call i32 @bar(i32 %4) 696 %tobool = icmp eq i32 %call, 0 697 br i1 %tobool, label %while.end, label %while.body 698 699while.body: ; preds = %while.body.preheader, %while.cond 700 %5 = phi i32 [ %4, %while.cond ], [ %3, %while.body.preheader ] 701 %6 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %5, i32 1) 702 %7 = extractvalue { i32, i1 } %6, 1 703 br i1 %7, label %trap, label %while.cond 704 705while.end: ; preds = %while.cond, %cont 706 %.lcssa = phi i32 [ %3, %cont ], [ %4, %while.cond ] 707 %cmp = icmp slt i32 %.lcssa, %n 708 br i1 %cmp, label %for.cond, label %cleanup2 709 710cleanup2: ; preds = %while.end 711 ret void 712} 713 714define { i8, i1 } @signed_mul_constant_folding() { 715; CHECK-LABEL: @signed_mul_constant_folding( 716; CHECK-NEXT: ret { i8, i1 } { i8 2, i1 false } 717; 718 %mul = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 1, i8 2) 719 ret { i8, i1 } %mul 720} 721 722define { <2 x i32>, <2 x i1> } @uaddo_vec(<2 x i32> %a) { 723; CHECK-LABEL: @uaddo_vec( 724; CHECK-NEXT: [[ADD:%.*]] = call { <2 x i32>, <2 x i1> } @llvm.uadd.with.overflow.v2i32(<2 x i32> [[A:%.*]], <2 x i32> <i32 1, i32 1>) 725; CHECK-NEXT: ret { <2 x i32>, <2 x i1> } [[ADD]] 726; 727 %add = call { <2 x i32>, <2 x i1> } @llvm.uadd.with.overflow.v2i32(<2 x i32> %a, <2 x i32> <i32 1, i32 1>) 728 ret { <2 x i32>, <2 x i1> } %add 729} 730 731 732define i8 @uadd_sat_no_unsigned_overflow(i8 %x) { 733; CHECK-LABEL: @uadd_sat_no_unsigned_overflow( 734; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], 100 735; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]] 736; CHECK: trap: 737; CHECK-NEXT: call void @llvm.trap() 738; CHECK-NEXT: unreachable 739; CHECK: cont: 740; CHECK-NEXT: [[RES1:%.*]] = add nuw i8 [[X]], 100 741; CHECK-NEXT: ret i8 [[RES1]] 742; 743 %cmp = icmp ugt i8 %x, 100 744 br i1 %cmp, label %trap, label %cont 745 746trap: 747 call void @llvm.trap() 748 unreachable 749 750cont: 751 %res = call i8 @llvm.uadd.sat.i8(i8 %x, i8 100) 752 ret i8 %res 753} 754 755define i8 @uadd_sat_no_overflow(i8 %x) { 756; CHECK-LABEL: @uadd_sat_no_overflow( 757; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], 27 758; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]] 759; CHECK: trap: 760; CHECK-NEXT: call void @llvm.trap() 761; CHECK-NEXT: unreachable 762; CHECK: cont: 763; CHECK-NEXT: [[RES1:%.*]] = add nuw nsw i8 [[X]], 100 764; CHECK-NEXT: ret i8 [[RES1]] 765; 766 %cmp = icmp ugt i8 %x, 27 767 br i1 %cmp, label %trap, label %cont 768 769trap: 770 call void @llvm.trap() 771 unreachable 772 773cont: 774 %res = call i8 @llvm.uadd.sat.i8(i8 %x, i8 100) 775 ret i8 %res 776} 777 778define i8 @sadd_sat_no_signed_overflow(i8 %x) { 779; CHECK-LABEL: @sadd_sat_no_signed_overflow( 780; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], 100 781; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]] 782; CHECK: trap: 783; CHECK-NEXT: call void @llvm.trap() 784; CHECK-NEXT: unreachable 785; CHECK: cont: 786; CHECK-NEXT: [[RES1:%.*]] = add nsw i8 [[X]], 20 787; CHECK-NEXT: ret i8 [[RES1]] 788; 789 %cmp = icmp sgt i8 %x, 100 790 br i1 %cmp, label %trap, label %cont 791 792trap: 793 call void @llvm.trap() 794 unreachable 795 796cont: 797 %res = call i8 @llvm.sadd.sat.i8(i8 %x, i8 20) 798 ret i8 %res 799} 800 801define i8 @sadd_sat_no_overflow(i8 %x) { 802; CHECK-LABEL: @sadd_sat_no_overflow( 803; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], 107 804; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]] 805; CHECK: trap: 806; CHECK-NEXT: call void @llvm.trap() 807; CHECK-NEXT: unreachable 808; CHECK: cont: 809; CHECK-NEXT: [[RES1:%.*]] = add nuw nsw i8 [[X]], 20 810; CHECK-NEXT: ret i8 [[RES1]] 811; 812 %cmp = icmp ugt i8 %x, 107 813 br i1 %cmp, label %trap, label %cont 814 815trap: 816 call void @llvm.trap() 817 unreachable 818 819cont: 820 %res = call i8 @llvm.sadd.sat.i8(i8 %x, i8 20) 821 ret i8 %res 822} 823 824define i8 @usub_sat_no_unsigned_overflow(i8 %x) { 825; CHECK-LABEL: @usub_sat_no_unsigned_overflow( 826; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], 100 827; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]] 828; CHECK: trap: 829; CHECK-NEXT: call void @llvm.trap() 830; CHECK-NEXT: unreachable 831; CHECK: cont: 832; CHECK-NEXT: [[RES1:%.*]] = sub nuw i8 [[X]], 100 833; CHECK-NEXT: ret i8 [[RES1]] 834; 835 %cmp = icmp ult i8 %x, 100 836 br i1 %cmp, label %trap, label %cont 837 838trap: 839 call void @llvm.trap() 840 unreachable 841 842cont: 843 %res = call i8 @llvm.usub.sat.i8(i8 %x, i8 100) 844 ret i8 %res 845} 846 847define i8 @usub_sat_no_overflow(i8 %x) { 848; CHECK-LABEL: @usub_sat_no_overflow( 849; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], -28 850; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]] 851; CHECK: trap: 852; CHECK-NEXT: call void @llvm.trap() 853; CHECK-NEXT: unreachable 854; CHECK: cont: 855; CHECK-NEXT: [[RES1:%.*]] = sub nuw nsw i8 [[X]], 100 856; CHECK-NEXT: ret i8 [[RES1]] 857; 858 %cmp = icmp ult i8 %x, 228 859 br i1 %cmp, label %trap, label %cont 860 861trap: 862 call void @llvm.trap() 863 unreachable 864 865cont: 866 %res = call i8 @llvm.usub.sat.i8(i8 %x, i8 100) 867 ret i8 %res 868} 869 870define i8 @ssub_sat_no_signed_overflow(i8 %x) { 871; CHECK-LABEL: @ssub_sat_no_signed_overflow( 872; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], -100 873; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]] 874; CHECK: trap: 875; CHECK-NEXT: call void @llvm.trap() 876; CHECK-NEXT: unreachable 877; CHECK: cont: 878; CHECK-NEXT: [[RES1:%.*]] = sub nsw i8 [[X]], 20 879; CHECK-NEXT: ret i8 [[RES1]] 880; 881 %cmp = icmp slt i8 %x, -100 882 br i1 %cmp, label %trap, label %cont 883 884trap: 885 call void @llvm.trap() 886 unreachable 887 888cont: 889 %res = call i8 @llvm.ssub.sat.i8(i8 %x, i8 20) 890 ret i8 %res 891} 892 893define i8 @ssub_sat_no_overflow(i8 %x) { 894; CHECK-LABEL: @ssub_sat_no_overflow( 895; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], -108 896; CHECK-NEXT: br i1 [[CMP]], label [[TRAP:%.*]], label [[CONT:%.*]] 897; CHECK: trap: 898; CHECK-NEXT: call void @llvm.trap() 899; CHECK-NEXT: unreachable 900; CHECK: cont: 901; CHECK-NEXT: [[RES1:%.*]] = sub nuw nsw i8 [[X]], 20 902; CHECK-NEXT: ret i8 [[RES1]] 903; 904 %cmp = icmp ult i8 %x, 148 905 br i1 %cmp, label %trap, label %cont 906 907trap: 908 call void @llvm.trap() 909 unreachable 910 911cont: 912 %res = call i8 @llvm.ssub.sat.i8(i8 %x, i8 20) 913 ret i8 %res 914} 915 916define <2 x i8> @uadd_sat_vec(<2 x i8> %a) { 917; CHECK-LABEL: @uadd_sat_vec( 918; CHECK-NEXT: [[ADD:%.*]] = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 1, i8 1>) 919; CHECK-NEXT: ret <2 x i8> [[ADD]] 920; 921 %add = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 1, i8 1>) 922 ret <2 x i8> %add 923} 924 925; In the following tests, we should first simplify a with.overflow intrinsic 926; to a simple arithmetic operation and insertvalue, but also simplify the 927; subsequent comparison that is based on it. 928 929define i1 @sadd_and_cmp(i32 %x, i32 %y) #0 { 930; CHECK-LABEL: @sadd_and_cmp( 931; CHECK-NEXT: entry: 932; CHECK-NEXT: [[X_OFFSET:%.*]] = add i32 [[X:%.*]], 9 933; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X_OFFSET]], 19 934; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]] 935; CHECK: cont1: 936; CHECK-NEXT: [[Y_OFFSET:%.*]] = add i32 [[Y:%.*]], 9 937; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y_OFFSET]], 19 938; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]] 939; CHECK: cont2: 940; CHECK-NEXT: [[RES1:%.*]] = add nsw i32 [[X]], [[Y]] 941; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[RES1]], 0 942; CHECK-NEXT: [[ADD:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0 943; CHECK-NEXT: br label [[OUT]] 944; CHECK: out: 945; CHECK-NEXT: ret i1 true 946; 947entry: 948 %x.offset = add i32 %x, 9 949 %cmp1 = icmp ult i32 %x.offset, 19 950 br i1 %cmp1, label %cont1, label %out 951 952cont1: 953 %y.offset = add i32 %y, 9 954 %cmp2 = icmp ult i32 %y.offset, 19 955 br i1 %cmp2, label %cont2, label %out 956 957cont2: 958 ; x = [-9,10), y = [-9,10) 959 %res = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 %y) 960 %add = extractvalue { i32, i1 } %res, 0 961 ; add = [-18,19) 962 %cmp3 = icmp slt i32 %add, 19 963 br label %out 964 965out: 966 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont2 ] 967 ret i1 %ret 968} 969 970 971define i1 @uadd_and_cmp(i32 %x, i32 %y) #0 { 972; CHECK-LABEL: @uadd_and_cmp( 973; CHECK-NEXT: entry: 974; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 10 975; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]] 976; CHECK: cont1: 977; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 10 978; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]] 979; CHECK: cont2: 980; CHECK-NEXT: [[RES1:%.*]] = add nuw nsw i32 [[X]], [[Y]] 981; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[RES1]], 0 982; CHECK-NEXT: [[ADD:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0 983; CHECK-NEXT: br label [[OUT]] 984; CHECK: out: 985; CHECK-NEXT: ret i1 true 986; 987entry: 988 %cmp1 = icmp ult i32 %x, 10 989 br i1 %cmp1, label %cont1, label %out 990 991cont1: 992 %cmp2 = icmp ult i32 %y, 10 993 br i1 %cmp2, label %cont2, label %out 994 995cont2: 996 %res = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y) 997 %add = extractvalue { i32, i1 } %res, 0 998 %cmp3 = icmp ult i32 %add, 19 999 br label %out 1000 1001out: 1002 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont2 ] 1003 ret i1 %ret 1004} 1005 1006define i1 @ssub_and_cmp(i32 %x, i32 %y) #0 { 1007; CHECK-LABEL: @ssub_and_cmp( 1008; CHECK-NEXT: entry: 1009; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 10 1010; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]] 1011; CHECK: cont1: 1012; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 10 1013; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]] 1014; CHECK: cont2: 1015; CHECK-NEXT: [[OFFSET:%.*]] = add nuw nsw i32 [[X]], 9 1016; CHECK-NEXT: [[RES1:%.*]] = sub nuw nsw i32 [[OFFSET]], [[Y]] 1017; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[RES1]], 0 1018; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0 1019; CHECK-NEXT: br label [[OUT]] 1020; CHECK: out: 1021; CHECK-NEXT: ret i1 true 1022; 1023entry: 1024 %cmp1 = icmp ult i32 %x, 10 1025 br i1 %cmp1, label %cont1, label %out 1026 1027cont1: 1028 %cmp2 = icmp ult i32 %y, 10 1029 br i1 %cmp2, label %cont2, label %out 1030 1031cont2: 1032 %offset = add i32 %x, 9 1033 ; x = [0,10), y = [0,10), offset = [9,19) 1034 %res = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %offset, i32 %y) 1035 %sub = extractvalue { i32, i1 } %res, 0 1036 %cmp3 = icmp ult i32 %sub, 19 1037 br label %out 1038 1039out: 1040 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont2 ] 1041 ret i1 %ret 1042} 1043 1044define i1 @usub_and_cmp(i32 %x, i32 %y) #0 { 1045; CHECK-LABEL: @usub_and_cmp( 1046; CHECK-NEXT: entry: 1047; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 10 1048; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]] 1049; CHECK: cont1: 1050; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 10 1051; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]] 1052; CHECK: cont2: 1053; CHECK-NEXT: [[OFFSET:%.*]] = add nuw nsw i32 [[X]], 9 1054; CHECK-NEXT: [[RES1:%.*]] = sub nuw nsw i32 [[OFFSET]], [[Y]] 1055; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[RES1]], 0 1056; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0 1057; CHECK-NEXT: br label [[OUT]] 1058; CHECK: out: 1059; CHECK-NEXT: ret i1 true 1060; 1061entry: 1062 %cmp1 = icmp ult i32 %x, 10 1063 br i1 %cmp1, label %cont1, label %out 1064 1065cont1: 1066 %cmp2 = icmp ult i32 %y, 10 1067 br i1 %cmp2, label %cont2, label %out 1068 1069cont2: 1070 %offset = add i32 %x, 9 1071 ; x = [0,10), y = [0,10), offset = [9,19) 1072 %res = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %offset, i32 %y) 1073 %sub = extractvalue { i32, i1 } %res, 0 1074 %cmp3 = icmp ult i32 %sub, 19 1075 br label %out 1076 1077out: 1078 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont2 ] 1079 ret i1 %ret 1080} 1081 1082define i1 @smul_and_cmp(i32 %x, i32 %y) #0 { 1083; CHECK-LABEL: @smul_and_cmp( 1084; CHECK-NEXT: entry: 1085; CHECK-NEXT: [[X_OFFSET:%.*]] = add i32 [[X:%.*]], 9 1086; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X_OFFSET]], 19 1087; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]] 1088; CHECK: cont1: 1089; CHECK-NEXT: [[Y_OFFSET:%.*]] = add i32 [[Y:%.*]], 9 1090; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y_OFFSET]], 19 1091; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]] 1092; CHECK: cont2: 1093; CHECK-NEXT: [[RES1:%.*]] = mul nsw i32 [[X]], [[Y]] 1094; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[RES1]], 0 1095; CHECK-NEXT: [[MUL:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0 1096; CHECK-NEXT: br label [[OUT]] 1097; CHECK: out: 1098; CHECK-NEXT: ret i1 true 1099; 1100entry: 1101 %x.offset = add i32 %x, 9 1102 %cmp1 = icmp ult i32 %x.offset, 19 1103 br i1 %cmp1, label %cont1, label %out 1104 1105cont1: 1106 %y.offset = add i32 %y, 9 1107 %cmp2 = icmp ult i32 %y.offset, 19 1108 br i1 %cmp2, label %cont2, label %out 1109 1110cont2: 1111 ; x = [-9,10), y = [-9,10) 1112 %res = tail call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %x, i32 %y) 1113 %mul = extractvalue { i32, i1 } %res, 0 1114 %cmp3 = icmp sle i32 %mul, 81 1115 %cmp4 = icmp sge i32 %mul, -81 1116 %cmp5 = and i1 %cmp3, %cmp4 1117 br label %out 1118 1119out: 1120 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp5, %cont2 ] 1121 ret i1 %ret 1122} 1123 1124define i1 @umul_and_cmp(i32 %x, i32 %y) #0 { 1125; CHECK-LABEL: @umul_and_cmp( 1126; CHECK-NEXT: entry: 1127; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[X:%.*]], 100 1128; CHECK-NEXT: br i1 [[CMP1]], label [[CONT1:%.*]], label [[OUT:%.*]] 1129; CHECK: cont1: 1130; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[Y:%.*]], 100 1131; CHECK-NEXT: br i1 [[CMP2]], label [[CONT2:%.*]], label [[OUT]] 1132; CHECK: cont2: 1133; CHECK-NEXT: [[RES1:%.*]] = mul nuw nsw i32 [[X]], [[Y]] 1134; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i32, i1 } { i32 undef, i1 false }, i32 [[RES1]], 0 1135; CHECK-NEXT: [[MUL:%.*]] = extractvalue { i32, i1 } [[TMP0]], 0 1136; CHECK-NEXT: br label [[OUT]] 1137; CHECK: out: 1138; CHECK-NEXT: ret i1 true 1139; 1140entry: 1141 %cmp1 = icmp ult i32 %x, 100 1142 br i1 %cmp1, label %cont1, label %out 1143 1144cont1: 1145 %cmp2 = icmp ult i32 %y, 100 1146 br i1 %cmp2, label %cont2, label %out 1147 1148cont2: 1149 %res = tail call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y) 1150 %mul = extractvalue { i32, i1 } %res, 0 1151 %cmp3 = icmp ule i32 %mul, 9801 1152 br label %out 1153 1154out: 1155 %ret = phi i1 [ true, %entry], [ true, %cont1 ], [ %cmp3, %cont2 ] 1156 ret i1 %ret 1157} 1158