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.assume(i1) 5declare i32 @llvm.abs.i32(i32, i1) 6declare i8 @llvm.abs.i8(i8, i1) 7declare i1 @llvm.abs.i1(i1, i1) 8 9; If we don't know anything about the argument, we can't do anything. 10 11define i8 @test0(i8 %x) { 12; CHECK-LABEL: @test0( 13; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false) 14; CHECK-NEXT: ret i8 [[R]] 15; 16 %r = call i8 @llvm.abs.i8(i8 %x, i1 0) 17 ret i8 %r 18} 19define i8 @test1(i8 %x) { 20; CHECK-LABEL: @test1( 21; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true) 22; CHECK-NEXT: ret i8 [[R]] 23; 24 %r = call i8 @llvm.abs.i8(i8 %x, i1 1) 25 ret i8 %r 26} 27 28; But if we know that the argument is always positive, we can bypass @llvm.abs. 29 30define i8 @test2(i8 %x) { 31; CHECK-LABEL: @test2( 32; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], -1 33; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 34; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true) 35; CHECK-NEXT: ret i8 [[R]] 36; 37 38 %lim = icmp sge i8 %x, -1 39 call void @llvm.assume(i1 %lim) 40 %r = call i8 @llvm.abs.i8(i8 %x, i1 0) 41 ret i8 %r 42} 43define i8 @test3(i8 %x) { 44; CHECK-LABEL: @test3( 45; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], -1 46; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 47; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true) 48; CHECK-NEXT: ret i8 [[R]] 49; 50 51 %lim = icmp sge i8 %x, -1 52 call void @llvm.assume(i1 %lim) 53 %r = call i8 @llvm.abs.i8(i8 %x, i1 1) 54 ret i8 %r 55} 56 57define i8 @test4(i8 %x) { 58; CHECK-LABEL: @test4( 59; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 0 60; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 61; CHECK-NEXT: ret i8 [[X]] 62; 63 64 %lim = icmp sge i8 %x, 0 65 call void @llvm.assume(i1 %lim) 66 %r = call i8 @llvm.abs.i8(i8 %x, i1 0) 67 ret i8 %r 68} 69define i8 @test5(i8 %x) { 70; CHECK-LABEL: @test5( 71; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 0 72; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 73; CHECK-NEXT: ret i8 [[X]] 74; 75 76 %lim = icmp sge i8 %x, 0 77 call void @llvm.assume(i1 %lim) 78 %r = call i8 @llvm.abs.i8(i8 %x, i1 1) 79 ret i8 %r 80} 81 82define i8 @test6(i8 %x) { 83; CHECK-LABEL: @test6( 84; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 1 85; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 86; CHECK-NEXT: ret i8 [[X]] 87; 88 89 %lim = icmp sge i8 %x, 1 90 call void @llvm.assume(i1 %lim) 91 %r = call i8 @llvm.abs.i8(i8 %x, i1 0) 92 ret i8 %r 93} 94define i8 @test7(i8 %x) { 95; CHECK-LABEL: @test7( 96; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 1 97; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 98; CHECK-NEXT: ret i8 [[X]] 99; 100 101 %lim = icmp sge i8 %x, 1 102 call void @llvm.assume(i1 %lim) 103 %r = call i8 @llvm.abs.i8(i8 %x, i1 1) 104 ret i8 %r 105} 106 107; Likewise, INT_MIN is fine for otherwise-positive value. 108 109define i8 @test8(i8 %x) { 110; CHECK-LABEL: @test8( 111; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], 127 112; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 113; CHECK-NEXT: ret i8 [[X]] 114; 115 116 %lim = icmp ule i8 %x, 127 117 call void @llvm.assume(i1 %lim) 118 %r = call i8 @llvm.abs.i8(i8 %x, i1 0) 119 ret i8 %r 120} 121define i8 @test9(i8 %x) { 122; CHECK-LABEL: @test9( 123; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], 127 124; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 125; CHECK-NEXT: ret i8 [[X]] 126; 127 128 %lim = icmp ule i8 %x, 127 129 call void @llvm.assume(i1 %lim) 130 %r = call i8 @llvm.abs.i8(i8 %x, i1 1) 131 ret i8 %r 132} 133 134define i8 @test10(i8 %x) { 135; CHECK-LABEL: @test10( 136; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], -128 137; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 138; CHECK-NEXT: ret i8 [[X]] 139; 140 141 %lim = icmp ule i8 %x, 128 142 call void @llvm.assume(i1 %lim) 143 %r = call i8 @llvm.abs.i8(i8 %x, i1 0) 144 ret i8 %r 145} 146define i8 @test11(i8 %x) { 147; CHECK-LABEL: @test11( 148; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], -128 149; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 150; CHECK-NEXT: ret i8 [[X]] 151; 152 153 %lim = icmp ule i8 %x, 128 154 call void @llvm.assume(i1 %lim) 155 %r = call i8 @llvm.abs.i8(i8 %x, i1 1) 156 ret i8 %r 157} 158 159define i8 @test12(i8 %x) { 160; CHECK-LABEL: @test12( 161; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], -127 162; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 163; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false) 164; CHECK-NEXT: ret i8 [[R]] 165; 166 167 %lim = icmp ule i8 %x, 129 168 call void @llvm.assume(i1 %lim) 169 %r = call i8 @llvm.abs.i8(i8 %x, i1 0) 170 ret i8 %r 171} 172define i8 @test13(i8 %x) { 173; CHECK-LABEL: @test13( 174; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], -127 175; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 176; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true) 177; CHECK-NEXT: ret i8 [[R]] 178; 179 180 %lim = icmp ule i8 %x, 129 181 call void @llvm.assume(i1 %lim) 182 %r = call i8 @llvm.abs.i8(i8 %x, i1 1) 183 ret i8 %r 184} 185 186; Likewise, if we know that argument is always negative, 187; we can expand @llvm.abs into a direct negation. 188; For negative arguments, we must be careful to include 0 though. 189 190define i8 @test14(i8 %x) { 191; CHECK-LABEL: @test14( 192; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], -1 193; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 194; CHECK-NEXT: [[R1:%.*]] = sub i8 0, [[X]] 195; CHECK-NEXT: ret i8 [[R1]] 196; 197 198 %lim = icmp sle i8 %x, -1 199 call void @llvm.assume(i1 %lim) 200 %r = call i8 @llvm.abs.i8(i8 %x, i1 0) 201 ret i8 %r 202} 203define i8 @test15(i8 %x) { 204; CHECK-LABEL: @test15( 205; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], -1 206; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 207; CHECK-NEXT: [[R1:%.*]] = sub nsw i8 0, [[X]] 208; CHECK-NEXT: ret i8 [[R1]] 209; 210 211 %lim = icmp sle i8 %x, -1 212 call void @llvm.assume(i1 %lim) 213 %r = call i8 @llvm.abs.i8(i8 %x, i1 1) 214 ret i8 %r 215} 216 217define i8 @test16(i8 %x) { 218; CHECK-LABEL: @test16( 219; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 0 220; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 221; CHECK-NEXT: [[R1:%.*]] = sub i8 0, [[X]] 222; CHECK-NEXT: ret i8 [[R1]] 223; 224 225 %lim = icmp sle i8 %x, 0 226 call void @llvm.assume(i1 %lim) 227 %r = call i8 @llvm.abs.i8(i8 %x, i1 0) 228 ret i8 %r 229} 230define i8 @test17(i8 %x) { 231; CHECK-LABEL: @test17( 232; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 0 233; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 234; CHECK-NEXT: [[R1:%.*]] = sub nsw i8 0, [[X]] 235; CHECK-NEXT: ret i8 [[R1]] 236; 237 238 %lim = icmp sle i8 %x, 0 239 call void @llvm.assume(i1 %lim) 240 %r = call i8 @llvm.abs.i8(i8 %x, i1 1) 241 ret i8 %r 242} 243 244define i8 @test18(i8 %x) { 245; CHECK-LABEL: @test18( 246; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 1 247; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 248; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false) 249; CHECK-NEXT: ret i8 [[R]] 250; 251 252 %lim = icmp sle i8 %x, 1 253 call void @llvm.assume(i1 %lim) 254 %r = call i8 @llvm.abs.i8(i8 %x, i1 0) 255 ret i8 %r 256} 257define i8 @test19(i8 %x) { 258; CHECK-LABEL: @test19( 259; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 1 260; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 261; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true) 262; CHECK-NEXT: ret i8 [[R]] 263; 264 265 %lim = icmp sle i8 %x, 1 266 call void @llvm.assume(i1 %lim) 267 %r = call i8 @llvm.abs.i8(i8 %x, i1 1) 268 ret i8 %r 269} 270 271; And again, INT_MIN is also fine for otherwise-negative range. 272 273define i8 @test20(i8 %x) { 274; CHECK-LABEL: @test20( 275; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], 127 276; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 277; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false) 278; CHECK-NEXT: ret i8 [[R]] 279; 280 281 %lim = icmp uge i8 %x, 127 282 call void @llvm.assume(i1 %lim) 283 %r = call i8 @llvm.abs.i8(i8 %x, i1 0) 284 ret i8 %r 285} 286define i8 @test21(i8 %x) { 287; CHECK-LABEL: @test21( 288; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], 127 289; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 290; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true) 291; CHECK-NEXT: ret i8 [[R]] 292; 293 294 %lim = icmp uge i8 %x, 127 295 call void @llvm.assume(i1 %lim) 296 %r = call i8 @llvm.abs.i8(i8 %x, i1 1) 297 ret i8 %r 298} 299 300define i8 @test22(i8 %x) { 301; CHECK-LABEL: @test22( 302; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], -128 303; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 304; CHECK-NEXT: [[R1:%.*]] = sub i8 0, [[X]] 305; CHECK-NEXT: ret i8 [[R1]] 306; 307 308 %lim = icmp uge i8 %x, 128 309 call void @llvm.assume(i1 %lim) 310 %r = call i8 @llvm.abs.i8(i8 %x, i1 0) 311 ret i8 %r 312} 313define i8 @test23(i8 %x) { 314; CHECK-LABEL: @test23( 315; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], -128 316; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 317; CHECK-NEXT: [[R1:%.*]] = sub nsw i8 0, [[X]] 318; CHECK-NEXT: ret i8 [[R1]] 319; 320 321 %lim = icmp uge i8 %x, 128 322 call void @llvm.assume(i1 %lim) 323 %r = call i8 @llvm.abs.i8(i8 %x, i1 1) 324 ret i8 %r 325} 326 327define i8 @test24(i8 %x) { 328; CHECK-LABEL: @test24( 329; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], -127 330; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 331; CHECK-NEXT: [[R1:%.*]] = sub nsw i8 0, [[X]] 332; CHECK-NEXT: ret i8 [[R1]] 333; 334 335 %lim = icmp uge i8 %x, 129 336 call void @llvm.assume(i1 %lim) 337 %r = call i8 @llvm.abs.i8(i8 %x, i1 0) 338 ret i8 %r 339} 340define i8 @test25(i8 %x) { 341; CHECK-LABEL: @test25( 342; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], -127 343; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 344; CHECK-NEXT: [[R1:%.*]] = sub nsw i8 0, [[X]] 345; CHECK-NEXT: ret i8 [[R1]] 346; 347 348 %lim = icmp uge i8 %x, 129 349 call void @llvm.assume(i1 %lim) 350 %r = call i8 @llvm.abs.i8(i8 %x, i1 1) 351 ret i8 %r 352} 353 354; If all else fails, we can sometimes at least inferr NSW. 355 356define i8 @test26(i8 %x) { 357; CHECK-LABEL: @test26( 358; CHECK-NEXT: [[LIM:%.*]] = icmp ne i8 [[X:%.*]], -128 359; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 360; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true) 361; CHECK-NEXT: ret i8 [[R]] 362; 363 %lim = icmp ne i8 %x, 128 364 call void @llvm.assume(i1 %lim) 365 %r = call i8 @llvm.abs.i8(i8 %x, i1 0) 366 ret i8 %r 367} 368define i8 @test27(i8 %x) { 369; CHECK-LABEL: @test27( 370; CHECK-NEXT: [[LIM:%.*]] = icmp ne i8 [[X:%.*]], -128 371; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 372; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true) 373; CHECK-NEXT: ret i8 [[R]] 374; 375 %lim = icmp ne i8 %x, 128 376 call void @llvm.assume(i1 %lim) 377 %r = call i8 @llvm.abs.i8(i8 %x, i1 1) 378 ret i8 %r 379} 380 381define i1 @pr59887(i1 %x, i1 %c) { 382; CHECK-LABEL: @pr59887( 383; CHECK-NEXT: [[RES:%.*]] = select i1 [[C:%.*]], i1 [[X:%.*]], i1 false 384; CHECK-NEXT: ret i1 [[RES]] 385; 386 %abs = call i1 @llvm.abs.i1(i1 %x, i1 false) 387 %res = select i1 %c, i1 %abs, i1 false 388 ret i1 %res 389} 390 391; Because of `undef`, We can't delete `abs`. 392; We can't replace the `abs` argument with true either. 393define i32 @pr68381_undef_abs_false(i1 %c0, i1 %c1, i8 %v1) { 394; CHECK-LABEL: @pr68381_undef_abs_false( 395; CHECK-NEXT: start: 396; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB0:%.*]], label [[BB1:%.*]] 397; CHECK: bb0: 398; CHECK-NEXT: [[V1_I32:%.*]] = zext i8 [[V1:%.*]] to i32 399; CHECK-NEXT: br label [[BB1]] 400; CHECK: bb1: 401; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[V1_I32]], [[BB0]] ], [ undef, [[START:%.*]] ] 402; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB0]], label [[BB2:%.*]] 403; CHECK: bb2: 404; CHECK-NEXT: [[Z:%.*]] = call i32 @llvm.abs.i32(i32 [[X]], i1 false) 405; CHECK-NEXT: ret i32 [[Z]] 406; 407start: 408 br i1 %c0, label %bb0, label %bb1 409 410bb0: 411 %v1_i32 = zext i8 %v1 to i32 412 br label %bb1 413 414bb1: 415 %x = phi i32 [ %v1_i32, %bb0 ], [ undef, %start ] 416 br i1 %c1, label %bb0, label %bb2 417 418bb2: 419 %z = call i32 @llvm.abs.i32(i32 %x, i1 false) 420 ret i32 %z 421} 422 423; Because of `and`, we can delete `abs`. 424define i32 @pr68381_undef_abs_false_and(i1 %c0, i1 %c1, i8 %v1) { 425; CHECK-LABEL: @pr68381_undef_abs_false_and( 426; CHECK-NEXT: start: 427; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB0:%.*]], label [[BB1:%.*]] 428; CHECK: bb0: 429; CHECK-NEXT: [[V1_I32:%.*]] = zext i8 [[V1:%.*]] to i32 430; CHECK-NEXT: br label [[BB1]] 431; CHECK: bb1: 432; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[V1_I32]], [[BB0]] ], [ undef, [[START:%.*]] ] 433; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB0]], label [[BB2:%.*]] 434; CHECK: bb2: 435; CHECK-NEXT: [[Y:%.*]] = and i32 [[X]], 255 436; CHECK-NEXT: ret i32 [[Y]] 437; 438start: 439 br i1 %c0, label %bb0, label %bb1 440 441bb0: 442 %v1_i32 = zext i8 %v1 to i32 443 br label %bb1 444 445bb1: 446 %x = phi i32 [ %v1_i32, %bb0 ], [ undef, %start ] 447 br i1 %c1, label %bb0, label %bb2 448 449bb2: 450 %y = and i32 %x, 255 451 %z = call i32 @llvm.abs.i32(i32 %y, i1 false) 452 ret i32 %z 453} 454 455; Because of `undef`, we can't replace `abs` with `sub`. 456define i32 @pr68381_undef_abs_false_sub(i1 %c0, i1 %c1, i32 %v1, i32 %v2) { 457; CHECK-LABEL: @pr68381_undef_abs_false_sub( 458; CHECK-NEXT: start: 459; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB0:%.*]], label [[BB1:%.*]] 460; CHECK: bb0: 461; CHECK-NEXT: [[V3:%.*]] = add i32 [[V1:%.*]], [[V2:%.*]] 462; CHECK-NEXT: [[LIM:%.*]] = icmp sle i32 [[V3]], -1 463; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) 464; CHECK-NEXT: br label [[BB1]] 465; CHECK: bb1: 466; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[V3]], [[BB0]] ], [ undef, [[START:%.*]] ] 467; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB0]], label [[BB2:%.*]] 468; CHECK: bb2: 469; CHECK-NEXT: [[Z:%.*]] = call i32 @llvm.abs.i32(i32 [[X]], i1 false) 470; CHECK-NEXT: ret i32 [[Z]] 471; 472start: 473 br i1 %c0, label %bb0, label %bb1 474 475bb0: 476 %v3 = add i32 %v1, %v2 477 %lim = icmp sle i32 %v3, -1 478 call void @llvm.assume(i1 %lim) 479 br label %bb1 480 481bb1: 482 %x = phi i32 [ %v3, %bb0 ], [ undef, %start ] 483 br i1 %c1, label %bb0, label %bb2 484 485bb2: 486 %z = call i32 @llvm.abs.i32(i32 %x, i1 false) 487 ret i32 %z 488} 489 490; We can delete `abs`. 491define i32 @pr68381_undef_abs_true(i1 %c0, i1 %c1, i8 %v1) { 492; CHECK-LABEL: @pr68381_undef_abs_true( 493; CHECK-NEXT: start: 494; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB0:%.*]], label [[BB1:%.*]] 495; CHECK: bb0: 496; CHECK-NEXT: [[V1_I32:%.*]] = zext i8 [[V1:%.*]] to i32 497; CHECK-NEXT: br label [[BB1]] 498; CHECK: bb1: 499; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[V1_I32]], [[BB0]] ], [ undef, [[START:%.*]] ] 500; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB0]], label [[BB2:%.*]] 501; CHECK: bb2: 502; CHECK-NEXT: ret i32 [[X]] 503; 504start: 505 br i1 %c0, label %bb0, label %bb1 506 507bb0: 508 %v1_i32 = zext i8 %v1 to i32 509 br label %bb1 510 511bb1: 512 %x = phi i32 [ %v1_i32, %bb0 ], [ undef, %start ] 513 br i1 %c1, label %bb0, label %bb2 514 515bb2: 516 %z = call i32 @llvm.abs.i32(i32 %x, i1 true) 517 ret i32 %z 518} 519