| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s |
| |
| declare void @llvm.assume(i1) |
| declare i32 @llvm.abs.i32(i32, i1) |
| declare i8 @llvm.abs.i8(i8, i1) |
| declare i1 @llvm.abs.i1(i1, i1) |
| |
| ; If we don't know anything about the argument, we can't do anything. |
| |
| define i8 @test0(i8 %x) { |
| ; CHECK-LABEL: @test0( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 0) |
| ret i8 %r |
| } |
| define i8 @test1(i8 %x) { |
| ; CHECK-LABEL: @test1( |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 1) |
| ret i8 %r |
| } |
| |
| ; But if we know that the argument is always positive, we can bypass @llvm.abs. |
| |
| define i8 @test2(i8 %x) { |
| ; CHECK-LABEL: @test2( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], -1 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| |
| %lim = icmp sge i8 %x, -1 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 0) |
| ret i8 %r |
| } |
| define i8 @test3(i8 %x) { |
| ; CHECK-LABEL: @test3( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], -1 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| |
| %lim = icmp sge i8 %x, -1 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 1) |
| ret i8 %r |
| } |
| |
| define i8 @test4(i8 %x) { |
| ; CHECK-LABEL: @test4( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 0 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: ret i8 [[X]] |
| ; |
| |
| %lim = icmp sge i8 %x, 0 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 0) |
| ret i8 %r |
| } |
| define i8 @test5(i8 %x) { |
| ; CHECK-LABEL: @test5( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 0 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: ret i8 [[X]] |
| ; |
| |
| %lim = icmp sge i8 %x, 0 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 1) |
| ret i8 %r |
| } |
| |
| define i8 @test6(i8 %x) { |
| ; CHECK-LABEL: @test6( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 1 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: ret i8 [[X]] |
| ; |
| |
| %lim = icmp sge i8 %x, 1 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 0) |
| ret i8 %r |
| } |
| define i8 @test7(i8 %x) { |
| ; CHECK-LABEL: @test7( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp sge i8 [[X:%.*]], 1 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: ret i8 [[X]] |
| ; |
| |
| %lim = icmp sge i8 %x, 1 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 1) |
| ret i8 %r |
| } |
| |
| ; Likewise, INT_MIN is fine for otherwise-positive value. |
| |
| define i8 @test8(i8 %x) { |
| ; CHECK-LABEL: @test8( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], 127 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: ret i8 [[X]] |
| ; |
| |
| %lim = icmp ule i8 %x, 127 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 0) |
| ret i8 %r |
| } |
| define i8 @test9(i8 %x) { |
| ; CHECK-LABEL: @test9( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], 127 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: ret i8 [[X]] |
| ; |
| |
| %lim = icmp ule i8 %x, 127 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 1) |
| ret i8 %r |
| } |
| |
| define i8 @test10(i8 %x) { |
| ; CHECK-LABEL: @test10( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], -128 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: ret i8 [[X]] |
| ; |
| |
| %lim = icmp ule i8 %x, 128 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 0) |
| ret i8 %r |
| } |
| define i8 @test11(i8 %x) { |
| ; CHECK-LABEL: @test11( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], -128 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: ret i8 [[X]] |
| ; |
| |
| %lim = icmp ule i8 %x, 128 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 1) |
| ret i8 %r |
| } |
| |
| define i8 @test12(i8 %x) { |
| ; CHECK-LABEL: @test12( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], -127 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| |
| %lim = icmp ule i8 %x, 129 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 0) |
| ret i8 %r |
| } |
| define i8 @test13(i8 %x) { |
| ; CHECK-LABEL: @test13( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp ule i8 [[X:%.*]], -127 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| |
| %lim = icmp ule i8 %x, 129 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 1) |
| ret i8 %r |
| } |
| |
| ; Likewise, if we know that argument is always negative, |
| ; we can expand @llvm.abs into a direct negation. |
| ; For negative arguments, we must be careful to include 0 though. |
| |
| define i8 @test14(i8 %x) { |
| ; CHECK-LABEL: @test14( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], -1 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R1:%.*]] = sub i8 0, [[X]] |
| ; CHECK-NEXT: ret i8 [[R1]] |
| ; |
| |
| %lim = icmp sle i8 %x, -1 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 0) |
| ret i8 %r |
| } |
| define i8 @test15(i8 %x) { |
| ; CHECK-LABEL: @test15( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], -1 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R1:%.*]] = sub nsw i8 0, [[X]] |
| ; CHECK-NEXT: ret i8 [[R1]] |
| ; |
| |
| %lim = icmp sle i8 %x, -1 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 1) |
| ret i8 %r |
| } |
| |
| define i8 @test16(i8 %x) { |
| ; CHECK-LABEL: @test16( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 0 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R1:%.*]] = sub i8 0, [[X]] |
| ; CHECK-NEXT: ret i8 [[R1]] |
| ; |
| |
| %lim = icmp sle i8 %x, 0 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 0) |
| ret i8 %r |
| } |
| define i8 @test17(i8 %x) { |
| ; CHECK-LABEL: @test17( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 0 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R1:%.*]] = sub nsw i8 0, [[X]] |
| ; CHECK-NEXT: ret i8 [[R1]] |
| ; |
| |
| %lim = icmp sle i8 %x, 0 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 1) |
| ret i8 %r |
| } |
| |
| define i8 @test18(i8 %x) { |
| ; CHECK-LABEL: @test18( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 1 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| |
| %lim = icmp sle i8 %x, 1 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 0) |
| ret i8 %r |
| } |
| define i8 @test19(i8 %x) { |
| ; CHECK-LABEL: @test19( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp sle i8 [[X:%.*]], 1 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| |
| %lim = icmp sle i8 %x, 1 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 1) |
| ret i8 %r |
| } |
| |
| ; And again, INT_MIN is also fine for otherwise-negative range. |
| |
| define i8 @test20(i8 %x) { |
| ; CHECK-LABEL: @test20( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], 127 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| |
| %lim = icmp uge i8 %x, 127 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 0) |
| ret i8 %r |
| } |
| define i8 @test21(i8 %x) { |
| ; CHECK-LABEL: @test21( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], 127 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| |
| %lim = icmp uge i8 %x, 127 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 1) |
| ret i8 %r |
| } |
| |
| define i8 @test22(i8 %x) { |
| ; CHECK-LABEL: @test22( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], -128 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R1:%.*]] = sub i8 0, [[X]] |
| ; CHECK-NEXT: ret i8 [[R1]] |
| ; |
| |
| %lim = icmp uge i8 %x, 128 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 0) |
| ret i8 %r |
| } |
| define i8 @test23(i8 %x) { |
| ; CHECK-LABEL: @test23( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], -128 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R1:%.*]] = sub nsw i8 0, [[X]] |
| ; CHECK-NEXT: ret i8 [[R1]] |
| ; |
| |
| %lim = icmp uge i8 %x, 128 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 1) |
| ret i8 %r |
| } |
| |
| define i8 @test24(i8 %x) { |
| ; CHECK-LABEL: @test24( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], -127 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R1:%.*]] = sub nsw i8 0, [[X]] |
| ; CHECK-NEXT: ret i8 [[R1]] |
| ; |
| |
| %lim = icmp uge i8 %x, 129 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 0) |
| ret i8 %r |
| } |
| define i8 @test25(i8 %x) { |
| ; CHECK-LABEL: @test25( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp uge i8 [[X:%.*]], -127 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R1:%.*]] = sub nsw i8 0, [[X]] |
| ; CHECK-NEXT: ret i8 [[R1]] |
| ; |
| |
| %lim = icmp uge i8 %x, 129 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 1) |
| ret i8 %r |
| } |
| |
| ; If all else fails, we can sometimes at least inferr NSW. |
| |
| define i8 @test26(i8 %x) { |
| ; CHECK-LABEL: @test26( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp ne i8 [[X:%.*]], -128 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %lim = icmp ne i8 %x, 128 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 0) |
| ret i8 %r |
| } |
| define i8 @test27(i8 %x) { |
| ; CHECK-LABEL: @test27( |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp ne i8 [[X:%.*]], -128 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 true) |
| ; CHECK-NEXT: ret i8 [[R]] |
| ; |
| %lim = icmp ne i8 %x, 128 |
| call void @llvm.assume(i1 %lim) |
| %r = call i8 @llvm.abs.i8(i8 %x, i1 1) |
| ret i8 %r |
| } |
| |
| define i1 @pr59887(i1 %x, i1 %c) { |
| ; CHECK-LABEL: @pr59887( |
| ; CHECK-NEXT: [[RES:%.*]] = select i1 [[C:%.*]], i1 [[X:%.*]], i1 false |
| ; CHECK-NEXT: ret i1 [[RES]] |
| ; |
| %abs = call i1 @llvm.abs.i1(i1 %x, i1 false) |
| %res = select i1 %c, i1 %abs, i1 false |
| ret i1 %res |
| } |
| |
| ; Because of `undef`, We can't delete `abs`. |
| ; We can't replace the `abs` argument with true either. |
| define i32 @pr68381_undef_abs_false(i1 %c0, i1 %c1, i8 %v1) { |
| ; CHECK-LABEL: @pr68381_undef_abs_false( |
| ; CHECK-NEXT: start: |
| ; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB0:%.*]], label [[BB1:%.*]] |
| ; CHECK: bb0: |
| ; CHECK-NEXT: [[V1_I32:%.*]] = zext i8 [[V1:%.*]] to i32 |
| ; CHECK-NEXT: br label [[BB1]] |
| ; CHECK: bb1: |
| ; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[V1_I32]], [[BB0]] ], [ undef, [[START:%.*]] ] |
| ; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB0]], label [[BB2:%.*]] |
| ; CHECK: bb2: |
| ; CHECK-NEXT: [[Z:%.*]] = call i32 @llvm.abs.i32(i32 [[X]], i1 false) |
| ; CHECK-NEXT: ret i32 [[Z]] |
| ; |
| start: |
| br i1 %c0, label %bb0, label %bb1 |
| |
| bb0: |
| %v1_i32 = zext i8 %v1 to i32 |
| br label %bb1 |
| |
| bb1: |
| %x = phi i32 [ %v1_i32, %bb0 ], [ undef, %start ] |
| br i1 %c1, label %bb0, label %bb2 |
| |
| bb2: |
| %z = call i32 @llvm.abs.i32(i32 %x, i1 false) |
| ret i32 %z |
| } |
| |
| ; Because of `and`, we can delete `abs`. |
| define i32 @pr68381_undef_abs_false_and(i1 %c0, i1 %c1, i8 %v1) { |
| ; CHECK-LABEL: @pr68381_undef_abs_false_and( |
| ; CHECK-NEXT: start: |
| ; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB0:%.*]], label [[BB1:%.*]] |
| ; CHECK: bb0: |
| ; CHECK-NEXT: [[V1_I32:%.*]] = zext i8 [[V1:%.*]] to i32 |
| ; CHECK-NEXT: br label [[BB1]] |
| ; CHECK: bb1: |
| ; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[V1_I32]], [[BB0]] ], [ undef, [[START:%.*]] ] |
| ; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB0]], label [[BB2:%.*]] |
| ; CHECK: bb2: |
| ; CHECK-NEXT: [[Y:%.*]] = and i32 [[X]], 255 |
| ; CHECK-NEXT: ret i32 [[Y]] |
| ; |
| start: |
| br i1 %c0, label %bb0, label %bb1 |
| |
| bb0: |
| %v1_i32 = zext i8 %v1 to i32 |
| br label %bb1 |
| |
| bb1: |
| %x = phi i32 [ %v1_i32, %bb0 ], [ undef, %start ] |
| br i1 %c1, label %bb0, label %bb2 |
| |
| bb2: |
| %y = and i32 %x, 255 |
| %z = call i32 @llvm.abs.i32(i32 %y, i1 false) |
| ret i32 %z |
| } |
| |
| ; Because of `undef`, we can't replace `abs` with `sub`. |
| define i32 @pr68381_undef_abs_false_sub(i1 %c0, i1 %c1, i32 %v1, i32 %v2) { |
| ; CHECK-LABEL: @pr68381_undef_abs_false_sub( |
| ; CHECK-NEXT: start: |
| ; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB0:%.*]], label [[BB1:%.*]] |
| ; CHECK: bb0: |
| ; CHECK-NEXT: [[V3:%.*]] = add i32 [[V1:%.*]], [[V2:%.*]] |
| ; CHECK-NEXT: [[LIM:%.*]] = icmp sle i32 [[V3]], -1 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]]) |
| ; CHECK-NEXT: br label [[BB1]] |
| ; CHECK: bb1: |
| ; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[V3]], [[BB0]] ], [ undef, [[START:%.*]] ] |
| ; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB0]], label [[BB2:%.*]] |
| ; CHECK: bb2: |
| ; CHECK-NEXT: [[Z:%.*]] = call i32 @llvm.abs.i32(i32 [[X]], i1 false) |
| ; CHECK-NEXT: ret i32 [[Z]] |
| ; |
| start: |
| br i1 %c0, label %bb0, label %bb1 |
| |
| bb0: |
| %v3 = add i32 %v1, %v2 |
| %lim = icmp sle i32 %v3, -1 |
| call void @llvm.assume(i1 %lim) |
| br label %bb1 |
| |
| bb1: |
| %x = phi i32 [ %v3, %bb0 ], [ undef, %start ] |
| br i1 %c1, label %bb0, label %bb2 |
| |
| bb2: |
| %z = call i32 @llvm.abs.i32(i32 %x, i1 false) |
| ret i32 %z |
| } |
| |
| ; We can delete `abs`. |
| define i32 @pr68381_undef_abs_true(i1 %c0, i1 %c1, i8 %v1) { |
| ; CHECK-LABEL: @pr68381_undef_abs_true( |
| ; CHECK-NEXT: start: |
| ; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB0:%.*]], label [[BB1:%.*]] |
| ; CHECK: bb0: |
| ; CHECK-NEXT: [[V1_I32:%.*]] = zext i8 [[V1:%.*]] to i32 |
| ; CHECK-NEXT: br label [[BB1]] |
| ; CHECK: bb1: |
| ; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[V1_I32]], [[BB0]] ], [ undef, [[START:%.*]] ] |
| ; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB0]], label [[BB2:%.*]] |
| ; CHECK: bb2: |
| ; CHECK-NEXT: ret i32 [[X]] |
| ; |
| start: |
| br i1 %c0, label %bb0, label %bb1 |
| |
| bb0: |
| %v1_i32 = zext i8 %v1 to i32 |
| br label %bb1 |
| |
| bb1: |
| %x = phi i32 [ %v1_i32, %bb0 ], [ undef, %start ] |
| br i1 %c1, label %bb0, label %bb2 |
| |
| bb2: |
| %z = call i32 @llvm.abs.i32(i32 %x, i1 true) |
| ret i32 %z |
| } |