1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=correlated-propagation < %s | FileCheck %s 3 4declare void @llvm.trap() 5declare {i8, i1} @llvm.uadd.with.overflow(i8, i8) 6declare {i8, i1} @llvm.sadd.with.overflow(i8, i8) 7declare {i8, i1} @llvm.usub.with.overflow(i8, i8) 8declare {i8, i1} @llvm.ssub.with.overflow(i8, i8) 9declare {i8, i1} @llvm.umul.with.overflow(i8, i8) 10declare {i8, i1} @llvm.smul.with.overflow(i8, i8) 11 12define i1 @uadd_ov_false(i8 %x, i8* %px, i1* %pc) { 13; CHECK-LABEL: @uadd_ov_false( 14; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 [[X:%.*]], i8 100) 15; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 16; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]], align 1 17; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 18; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] 19; CHECK: no_overflow: 20; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], -102 21; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 22; CHECK-NEXT: ret i1 false 23; CHECK: trap: 24; CHECK-NEXT: call void @llvm.trap() 25; CHECK-NEXT: unreachable 26; 27 %val_ov = call {i8, i1} @llvm.uadd.with.overflow(i8 %x, i8 100) 28 %val = extractvalue {i8, i1} %val_ov, 0 29 store i8 %val, i8* %px 30 %ov = extractvalue {i8, i1} %val_ov, 1 31 br i1 %ov, label %trap, label %no_overflow 32 33no_overflow: 34 %c1 = icmp ugt i8 %x, 154 35 store i1 %c1, i1* %pc 36 %c2 = icmp ugt i8 %x, 155 37 ret i1 %c2 38 39trap: 40 call void @llvm.trap() 41 unreachable 42} 43 44define i1 @uadd_ov_true(i8 %x, i8* %px, i1* %pc) { 45; CHECK-LABEL: @uadd_ov_true( 46; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 [[X:%.*]], i8 100) 47; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 48; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]], align 1 49; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 50; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]] 51; CHECK: overflow: 52; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], -100 53; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 54; CHECK-NEXT: ret i1 true 55; CHECK: trap: 56; CHECK-NEXT: call void @llvm.trap() 57; CHECK-NEXT: unreachable 58; 59 %val_ov = call {i8, i1} @llvm.uadd.with.overflow(i8 %x, i8 100) 60 %val = extractvalue {i8, i1} %val_ov, 0 61 store i8 %val, i8* %px 62 %ov = extractvalue {i8, i1} %val_ov, 1 63 br i1 %ov, label %overflow, label %trap 64 65overflow: 66 %c1 = icmp ugt i8 %x, 156 67 store i1 %c1, i1* %pc 68 %c2 = icmp ugt i8 %x, 155 69 ret i1 %c2 70 71trap: 72 call void @llvm.trap() 73 unreachable 74} 75 76define i1 @sadd_ov_false(i8 %x, i8* %px, i1* %pc) { 77; CHECK-LABEL: @sadd_ov_false( 78; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 100) 79; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 80; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]], align 1 81; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 82; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] 83; CHECK: no_overflow: 84; CHECK-NEXT: [[C1:%.*]] = icmp sgt i8 [[X]], 26 85; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 86; CHECK-NEXT: ret i1 false 87; CHECK: trap: 88; CHECK-NEXT: call void @llvm.trap() 89; CHECK-NEXT: unreachable 90; 91 %val_ov = call {i8, i1} @llvm.sadd.with.overflow(i8 %x, i8 100) 92 %val = extractvalue {i8, i1} %val_ov, 0 93 store i8 %val, i8* %px 94 %ov = extractvalue {i8, i1} %val_ov, 1 95 br i1 %ov, label %trap, label %no_overflow 96 97no_overflow: 98 %c1 = icmp sgt i8 %x, 26 99 store i1 %c1, i1* %pc 100 %c2 = icmp sgt i8 %x, 27 101 ret i1 %c2 102 103trap: 104 call void @llvm.trap() 105 unreachable 106} 107 108define i1 @sadd_ov_true(i8 %x, i8* %px, i1* %pc) { 109; CHECK-LABEL: @sadd_ov_true( 110; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 100) 111; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 112; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]], align 1 113; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 114; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]] 115; CHECK: overflow: 116; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], 28 117; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 118; CHECK-NEXT: ret i1 true 119; CHECK: trap: 120; CHECK-NEXT: call void @llvm.trap() 121; CHECK-NEXT: unreachable 122; 123 %val_ov = call {i8, i1} @llvm.sadd.with.overflow(i8 %x, i8 100) 124 %val = extractvalue {i8, i1} %val_ov, 0 125 store i8 %val, i8* %px 126 %ov = extractvalue {i8, i1} %val_ov, 1 127 br i1 %ov, label %overflow, label %trap 128 129overflow: 130 %c1 = icmp sgt i8 %x, 28 131 store i1 %c1, i1* %pc 132 %c2 = icmp sgt i8 %x, 27 133 ret i1 %c2 134 135trap: 136 call void @llvm.trap() 137 unreachable 138} 139 140define i1 @usub_ov_false(i8 %x, i8* %px, i1* %pc) { 141; CHECK-LABEL: @usub_ov_false( 142; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[X:%.*]], i8 100) 143; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 144; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]], align 1 145; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 146; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] 147; CHECK: no_overflow: 148; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[X]], 101 149; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 150; CHECK-NEXT: ret i1 false 151; CHECK: trap: 152; CHECK-NEXT: call void @llvm.trap() 153; CHECK-NEXT: unreachable 154; 155 %val_ov = call {i8, i1} @llvm.usub.with.overflow(i8 %x, i8 100) 156 %val = extractvalue {i8, i1} %val_ov, 0 157 store i8 %val, i8* %px 158 %ov = extractvalue {i8, i1} %val_ov, 1 159 br i1 %ov, label %trap, label %no_overflow 160 161no_overflow: 162 %c1 = icmp ult i8 %x, 101 163 store i1 %c1, i1* %pc 164 %c2 = icmp ult i8 %x, 100 165 ret i1 %c2 166 167trap: 168 call void @llvm.trap() 169 unreachable 170} 171 172define i1 @usub_ov_true(i8 %x, i8* %px, i1* %pc) { 173; CHECK-LABEL: @usub_ov_true( 174; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[X:%.*]], i8 100) 175; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 176; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]], align 1 177; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 178; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]] 179; CHECK: overflow: 180; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[X]], 99 181; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 182; CHECK-NEXT: ret i1 true 183; CHECK: trap: 184; CHECK-NEXT: call void @llvm.trap() 185; CHECK-NEXT: unreachable 186; 187 %val_ov = call {i8, i1} @llvm.usub.with.overflow(i8 %x, i8 100) 188 %val = extractvalue {i8, i1} %val_ov, 0 189 store i8 %val, i8* %px 190 %ov = extractvalue {i8, i1} %val_ov, 1 191 br i1 %ov, label %overflow, label %trap 192 193overflow: 194 %c1 = icmp ult i8 %x, 99 195 store i1 %c1, i1* %pc 196 %c2 = icmp ult i8 %x, 100 197 ret i1 %c2 198 199trap: 200 call void @llvm.trap() 201 unreachable 202} 203 204define i1 @ssub_ov_false(i8 %x, i8* %px, i1* %pc) { 205; CHECK-LABEL: @ssub_ov_false( 206; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 100) 207; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 208; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]], align 1 209; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 210; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] 211; CHECK: no_overflow: 212; CHECK-NEXT: [[C1:%.*]] = icmp slt i8 [[X]], -27 213; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 214; CHECK-NEXT: ret i1 false 215; CHECK: trap: 216; CHECK-NEXT: call void @llvm.trap() 217; CHECK-NEXT: unreachable 218; 219 %val_ov = call {i8, i1} @llvm.ssub.with.overflow(i8 %x, i8 100) 220 %val = extractvalue {i8, i1} %val_ov, 0 221 store i8 %val, i8* %px 222 %ov = extractvalue {i8, i1} %val_ov, 1 223 br i1 %ov, label %trap, label %no_overflow 224 225no_overflow: 226 %c1 = icmp slt i8 %x, -27 227 store i1 %c1, i1* %pc 228 %c2 = icmp slt i8 %x, -28 229 ret i1 %c2 230 231trap: 232 call void @llvm.trap() 233 unreachable 234} 235 236define i1 @ssub_ov_true(i8 %x, i8* %px, i1* %pc) { 237; CHECK-LABEL: @ssub_ov_true( 238; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 100) 239; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 240; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]], align 1 241; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 242; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]] 243; CHECK: overflow: 244; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[X]], -29 245; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 246; CHECK-NEXT: ret i1 true 247; CHECK: trap: 248; CHECK-NEXT: call void @llvm.trap() 249; CHECK-NEXT: unreachable 250; 251 %val_ov = call {i8, i1} @llvm.ssub.with.overflow(i8 %x, i8 100) 252 %val = extractvalue {i8, i1} %val_ov, 0 253 store i8 %val, i8* %px 254 %ov = extractvalue {i8, i1} %val_ov, 1 255 br i1 %ov, label %overflow, label %trap 256 257overflow: 258 %c1 = icmp slt i8 %x, -29 259 store i1 %c1, i1* %pc 260 %c2 = icmp slt i8 %x, -28 261 ret i1 %c2 262 263trap: 264 call void @llvm.trap() 265 unreachable 266} 267 268define i1 @umul_ov_false(i8 %x, i8* %px, i1* %pc) { 269; CHECK-LABEL: @umul_ov_false( 270; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 10) 271; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 272; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]], align 1 273; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 274; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] 275; CHECK: no_overflow: 276; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], 24 277; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 278; CHECK-NEXT: ret i1 false 279; CHECK: trap: 280; CHECK-NEXT: call void @llvm.trap() 281; CHECK-NEXT: unreachable 282; 283 %val_ov = call {i8, i1} @llvm.umul.with.overflow(i8 %x, i8 10) 284 %val = extractvalue {i8, i1} %val_ov, 0 285 store i8 %val, i8* %px 286 %ov = extractvalue {i8, i1} %val_ov, 1 287 br i1 %ov, label %trap, label %no_overflow 288 289no_overflow: 290 %c1 = icmp ugt i8 %x, 24 291 store i1 %c1, i1* %pc 292 %c2 = icmp ugt i8 %x, 25 293 ret i1 %c2 294 295trap: 296 call void @llvm.trap() 297 unreachable 298} 299 300define i1 @umul_ov_true(i8 %x, i8* %px, i1* %pc) { 301; CHECK-LABEL: @umul_ov_true( 302; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 10) 303; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 304; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]], align 1 305; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 306; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]] 307; CHECK: overflow: 308; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[X]], 26 309; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 310; CHECK-NEXT: ret i1 true 311; CHECK: trap: 312; CHECK-NEXT: call void @llvm.trap() 313; CHECK-NEXT: unreachable 314; 315 %val_ov = call {i8, i1} @llvm.umul.with.overflow(i8 %x, i8 10) 316 %val = extractvalue {i8, i1} %val_ov, 0 317 store i8 %val, i8* %px 318 %ov = extractvalue {i8, i1} %val_ov, 1 319 br i1 %ov, label %overflow, label %trap 320 321overflow: 322 %c1 = icmp ugt i8 %x, 26 323 store i1 %c1, i1* %pc 324 %c2 = icmp ugt i8 %x, 25 325 ret i1 %c2 326 327trap: 328 call void @llvm.trap() 329 unreachable 330} 331 332; Signed mul is constrained from both sides. 333define i1 @smul_ov_false_bound1(i8 %x, i8* %px, i1* %pc) { 334; CHECK-LABEL: @smul_ov_false_bound1( 335; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10) 336; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 337; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]], align 1 338; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 339; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] 340; CHECK: no_overflow: 341; CHECK-NEXT: [[C1:%.*]] = icmp slt i8 [[X]], -11 342; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 343; CHECK-NEXT: ret i1 false 344; CHECK: trap: 345; CHECK-NEXT: call void @llvm.trap() 346; CHECK-NEXT: unreachable 347; 348 %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10) 349 %val = extractvalue {i8, i1} %val_ov, 0 350 store i8 %val, i8* %px 351 %ov = extractvalue {i8, i1} %val_ov, 1 352 br i1 %ov, label %trap, label %no_overflow 353 354no_overflow: 355 %c1 = icmp slt i8 %x, -11 356 store i1 %c1, i1* %pc 357 %c2 = icmp slt i8 %x, -12 358 ret i1 %c2 359 360trap: 361 call void @llvm.trap() 362 unreachable 363} 364 365define i1 @smul_ov_false_bound2(i8 %x, i8* %px, i1* %pc) { 366; CHECK-LABEL: @smul_ov_false_bound2( 367; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10) 368; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 369; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]], align 1 370; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 371; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] 372; CHECK: no_overflow: 373; CHECK-NEXT: [[C1:%.*]] = icmp sgt i8 [[X]], 11 374; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 375; CHECK-NEXT: ret i1 false 376; CHECK: trap: 377; CHECK-NEXT: call void @llvm.trap() 378; CHECK-NEXT: unreachable 379; 380 %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10) 381 %val = extractvalue {i8, i1} %val_ov, 0 382 store i8 %val, i8* %px 383 %ov = extractvalue {i8, i1} %val_ov, 1 384 br i1 %ov, label %trap, label %no_overflow 385 386no_overflow: 387 %c1 = icmp sgt i8 %x, 11 388 store i1 %c1, i1* %pc 389 %c2 = icmp sgt i8 %x, 12 390 ret i1 %c2 391 392trap: 393 call void @llvm.trap() 394 unreachable 395} 396 397; Can't use slt/sgt to test for a hole in the range, check equality instead. 398define i1 @smul_ov_true_bound1(i8 %x, i8* %px, i1* %pc) { 399; CHECK-LABEL: @smul_ov_true_bound1( 400; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10) 401; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 402; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]], align 1 403; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 404; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]] 405; CHECK: overflow: 406; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X]], -13 407; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 408; CHECK-NEXT: ret i1 false 409; CHECK: trap: 410; CHECK-NEXT: call void @llvm.trap() 411; CHECK-NEXT: unreachable 412; 413 %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10) 414 %val = extractvalue {i8, i1} %val_ov, 0 415 store i8 %val, i8* %px 416 %ov = extractvalue {i8, i1} %val_ov, 1 417 br i1 %ov, label %overflow, label %trap 418 419overflow: 420 %c1 = icmp eq i8 %x, -13 421 store i1 %c1, i1* %pc 422 %c2 = icmp eq i8 %x, -12 423 ret i1 %c2 424 425trap: 426 call void @llvm.trap() 427 unreachable 428} 429 430define i1 @smul_ov_true_bound2(i8 %x, i8* %px, i1* %pc) { 431; CHECK-LABEL: @smul_ov_true_bound2( 432; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10) 433; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 434; CHECK-NEXT: store i8 [[VAL]], i8* [[PX:%.*]], align 1 435; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 436; CHECK-NEXT: br i1 [[OV]], label [[OVERFLOW:%.*]], label [[TRAP:%.*]] 437; CHECK: overflow: 438; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X]], 13 439; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 440; CHECK-NEXT: ret i1 false 441; CHECK: trap: 442; CHECK-NEXT: call void @llvm.trap() 443; CHECK-NEXT: unreachable 444; 445 %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10) 446 %val = extractvalue {i8, i1} %val_ov, 0 447 store i8 %val, i8* %px 448 %ov = extractvalue {i8, i1} %val_ov, 1 449 br i1 %ov, label %overflow, label %trap 450 451overflow: 452 %c1 = icmp eq i8 %x, 13 453 store i1 %c1, i1* %pc 454 %c2 = icmp eq i8 %x, 12 455 ret i1 %c2 456 457trap: 458 call void @llvm.trap() 459 unreachable 460} 461 462define i1 @uadd_val(i8 %x, i1* %pc) { 463; CHECK-LABEL: @uadd_val( 464; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 [[X:%.*]], i8 100) 465; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 466; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] 467; CHECK: no_overflow: 468; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 469; CHECK-NEXT: [[C1:%.*]] = icmp ugt i8 [[VAL]], 100 470; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 471; CHECK-NEXT: ret i1 true 472; CHECK: trap: 473; CHECK-NEXT: call void @llvm.trap() 474; CHECK-NEXT: unreachable 475; 476 %val_ov = call {i8, i1} @llvm.uadd.with.overflow(i8 %x, i8 100) 477 %ov = extractvalue {i8, i1} %val_ov, 1 478 br i1 %ov, label %trap, label %no_overflow 479 480no_overflow: 481 %val = extractvalue {i8, i1} %val_ov, 0 482 %c1 = icmp ugt i8 %val, 100 483 store i1 %c1, i1* %pc 484 %c2 = icmp uge i8 %val, 100 485 ret i1 %c2 486 487trap: 488 call void @llvm.trap() 489 unreachable 490} 491 492define i1 @sadd_val(i8 %x, i1* %pc) { 493; CHECK-LABEL: @sadd_val( 494; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 100) 495; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 496; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] 497; CHECK: no_overflow: 498; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 499; CHECK-NEXT: [[C1:%.*]] = icmp sgt i8 [[VAL]], -28 500; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 501; CHECK-NEXT: ret i1 true 502; CHECK: trap: 503; CHECK-NEXT: call void @llvm.trap() 504; CHECK-NEXT: unreachable 505; 506 %val_ov = call {i8, i1} @llvm.sadd.with.overflow(i8 %x, i8 100) 507 %ov = extractvalue {i8, i1} %val_ov, 1 508 br i1 %ov, label %trap, label %no_overflow 509 510no_overflow: 511 %val = extractvalue {i8, i1} %val_ov, 0 512 %c1 = icmp sgt i8 %val, -28 513 store i1 %c1, i1* %pc 514 %c2 = icmp sge i8 %val, -28 515 ret i1 %c2 516 517trap: 518 call void @llvm.trap() 519 unreachable 520} 521 522define i1 @usub_val(i8 %x, i1* %pc) { 523; CHECK-LABEL: @usub_val( 524; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[X:%.*]], i8 100) 525; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 526; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] 527; CHECK: no_overflow: 528; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 529; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[VAL]], -101 530; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 531; CHECK-NEXT: ret i1 true 532; CHECK: trap: 533; CHECK-NEXT: call void @llvm.trap() 534; CHECK-NEXT: unreachable 535; 536 %val_ov = call {i8, i1} @llvm.usub.with.overflow(i8 %x, i8 100) 537 %ov = extractvalue {i8, i1} %val_ov, 1 538 br i1 %ov, label %trap, label %no_overflow 539 540no_overflow: 541 %val = extractvalue {i8, i1} %val_ov, 0 542 %c1 = icmp ult i8 %val, 155 543 store i1 %c1, i1* %pc 544 %c2 = icmp ule i8 %val, 155 545 ret i1 %c2 546 547trap: 548 call void @llvm.trap() 549 unreachable 550} 551 552define i1 @ssub_val(i8 %x, i1* %pc) { 553; CHECK-LABEL: @ssub_val( 554; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 100) 555; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 556; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] 557; CHECK: no_overflow: 558; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 559; CHECK-NEXT: [[C1:%.*]] = icmp slt i8 [[VAL]], 27 560; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 561; CHECK-NEXT: ret i1 true 562; CHECK: trap: 563; CHECK-NEXT: call void @llvm.trap() 564; CHECK-NEXT: unreachable 565; 566 %val_ov = call {i8, i1} @llvm.ssub.with.overflow(i8 %x, i8 100) 567 %ov = extractvalue {i8, i1} %val_ov, 1 568 br i1 %ov, label %trap, label %no_overflow 569 570no_overflow: 571 %val = extractvalue {i8, i1} %val_ov, 0 572 %c1 = icmp slt i8 %val, 27 573 store i1 %c1, i1* %pc 574 %c2 = icmp sle i8 %val, 27 575 ret i1 %c2 576 577trap: 578 call void @llvm.trap() 579 unreachable 580} 581 582define i1 @umul_val(i8 %x, i1* %pc) { 583; CHECK-LABEL: @umul_val( 584; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 10) 585; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 586; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] 587; CHECK: no_overflow: 588; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 589; CHECK-NEXT: [[C1:%.*]] = icmp ult i8 [[VAL]], -6 590; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 591; CHECK-NEXT: ret i1 true 592; CHECK: trap: 593; CHECK-NEXT: call void @llvm.trap() 594; CHECK-NEXT: unreachable 595; 596 %val_ov = call {i8, i1} @llvm.umul.with.overflow(i8 %x, i8 10) 597 %ov = extractvalue {i8, i1} %val_ov, 1 598 br i1 %ov, label %trap, label %no_overflow 599 600no_overflow: 601 %val = extractvalue {i8, i1} %val_ov, 0 602 %c1 = icmp ult i8 %val, 250 603 store i1 %c1, i1* %pc 604 %c2 = icmp ule i8 %val, 250 605 ret i1 %c2 606 607trap: 608 call void @llvm.trap() 609 unreachable 610} 611 612define i1 @smul_val_bound1(i8 %x, i1* %pc) { 613; CHECK-LABEL: @smul_val_bound1( 614; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10) 615; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 616; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] 617; CHECK: no_overflow: 618; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 619; CHECK-NEXT: [[C1:%.*]] = icmp slt i8 [[VAL]], 120 620; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 621; CHECK-NEXT: ret i1 true 622; CHECK: trap: 623; CHECK-NEXT: call void @llvm.trap() 624; CHECK-NEXT: unreachable 625; 626 %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10) 627 %ov = extractvalue {i8, i1} %val_ov, 1 628 br i1 %ov, label %trap, label %no_overflow 629 630no_overflow: 631 %val = extractvalue {i8, i1} %val_ov, 0 632 %c1 = icmp slt i8 %val, 120 633 store i1 %c1, i1* %pc 634 %c2 = icmp sle i8 %val, 120 635 ret i1 %c2 636 637trap: 638 call void @llvm.trap() 639 unreachable 640} 641 642define i1 @smul_val_bound2(i8 %x, i1* %pc) { 643; CHECK-LABEL: @smul_val_bound2( 644; CHECK-NEXT: [[VAL_OV:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 10) 645; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 1 646; CHECK-NEXT: br i1 [[OV]], label [[TRAP:%.*]], label [[NO_OVERFLOW:%.*]] 647; CHECK: no_overflow: 648; CHECK-NEXT: [[VAL:%.*]] = extractvalue { i8, i1 } [[VAL_OV]], 0 649; CHECK-NEXT: [[C1:%.*]] = icmp sgt i8 [[VAL]], -120 650; CHECK-NEXT: store i1 [[C1]], i1* [[PC:%.*]], align 1 651; CHECK-NEXT: ret i1 true 652; CHECK: trap: 653; CHECK-NEXT: call void @llvm.trap() 654; CHECK-NEXT: unreachable 655; 656 %val_ov = call {i8, i1} @llvm.smul.with.overflow(i8 %x, i8 10) 657 %ov = extractvalue {i8, i1} %val_ov, 1 658 br i1 %ov, label %trap, label %no_overflow 659 660no_overflow: 661 %val = extractvalue {i8, i1} %val_ov, 0 662 %c1 = icmp sgt i8 %val, -120 663 store i1 %c1, i1* %pc 664 %c2 = icmp sge i8 %val, -120 665 ret i1 %c2 666 667trap: 668 call void @llvm.trap() 669 unreachable 670} 671