| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt %s -passes=sccp -S | FileCheck --check-prefix=SCCP %s |
| ; RUN: opt %s -passes=ipsccp -S | FileCheck --check-prefix=IPSCCP %s |
| |
| ; Test different widening scenarios. |
| |
| declare void @use(i1) |
| declare i1 @cond() |
| |
| define void @test_2_incoming_constants(i32 %x) { |
| ; SCCP-LABEL: @test_2_incoming_constants( |
| ; SCCP-NEXT: entry: |
| ; SCCP-NEXT: [[C_1:%.*]] = call i1 @cond() |
| ; SCCP-NEXT: br i1 [[C_1]], label [[BB1:%.*]], label [[EXIT:%.*]] |
| ; SCCP: bb1: |
| ; SCCP-NEXT: br label [[EXIT]] |
| ; SCCP: exit: |
| ; SCCP-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 1, [[BB1]] ] |
| ; SCCP-NEXT: [[A:%.*]] = add i32 [[P]], 1 |
| ; SCCP-NEXT: call void @use(i1 true) |
| ; SCCP-NEXT: call void @use(i1 false) |
| ; SCCP-NEXT: ret void |
| ; |
| ; IPSCCP-LABEL: @test_2_incoming_constants( |
| ; IPSCCP-NEXT: entry: |
| ; IPSCCP-NEXT: [[C_1:%.*]] = call i1 @cond() |
| ; IPSCCP-NEXT: br i1 [[C_1]], label [[BB1:%.*]], label [[EXIT:%.*]] |
| ; IPSCCP: bb1: |
| ; IPSCCP-NEXT: br label [[EXIT]] |
| ; IPSCCP: exit: |
| ; IPSCCP-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 1, [[BB1]] ] |
| ; IPSCCP-NEXT: [[A:%.*]] = add i32 [[P]], 1 |
| ; IPSCCP-NEXT: call void @use(i1 true) |
| ; IPSCCP-NEXT: call void @use(i1 false) |
| ; IPSCCP-NEXT: ret void |
| ; |
| entry: |
| %c.1 = call i1 @cond() |
| br i1 %c.1, label %bb1, label %exit |
| |
| bb1: |
| br label %exit |
| |
| exit: |
| %p = phi i32 [0, %entry], [1, %bb1] |
| %a = add i32 %p, 1 |
| %t.1 = icmp ult i32 %a, 20 |
| call void @use(i1 %t.1) |
| %f.1 = icmp ugt i32 %a, 10 |
| call void @use(i1 %f.1) |
| ret void |
| } |
| |
| define void @test_3_incoming_constants(i32 %x) { |
| ; SCCP-LABEL: @test_3_incoming_constants( |
| ; SCCP-NEXT: entry: |
| ; SCCP-NEXT: [[C_1:%.*]] = call i1 @cond() |
| ; SCCP-NEXT: br i1 [[C_1]], label [[BB1:%.*]], label [[EXIT:%.*]] |
| ; SCCP: bb1: |
| ; SCCP-NEXT: [[C_2:%.*]] = call i1 @cond() |
| ; SCCP-NEXT: br i1 [[C_2]], label [[BB2:%.*]], label [[EXIT]] |
| ; SCCP: bb2: |
| ; SCCP-NEXT: br label [[EXIT]] |
| ; SCCP: exit: |
| ; SCCP-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 1, [[BB1]] ], [ 2, [[BB2]] ] |
| ; SCCP-NEXT: [[A:%.*]] = add i32 [[P]], 1 |
| ; SCCP-NEXT: call void @use(i1 true) |
| ; SCCP-NEXT: call void @use(i1 false) |
| ; SCCP-NEXT: ret void |
| ; |
| ; IPSCCP-LABEL: @test_3_incoming_constants( |
| ; IPSCCP-NEXT: entry: |
| ; IPSCCP-NEXT: [[C_1:%.*]] = call i1 @cond() |
| ; IPSCCP-NEXT: br i1 [[C_1]], label [[BB1:%.*]], label [[EXIT:%.*]] |
| ; IPSCCP: bb1: |
| ; IPSCCP-NEXT: [[C_2:%.*]] = call i1 @cond() |
| ; IPSCCP-NEXT: br i1 [[C_2]], label [[BB2:%.*]], label [[EXIT]] |
| ; IPSCCP: bb2: |
| ; IPSCCP-NEXT: br label [[EXIT]] |
| ; IPSCCP: exit: |
| ; IPSCCP-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 1, [[BB1]] ], [ 2, [[BB2]] ] |
| ; IPSCCP-NEXT: [[A:%.*]] = add i32 [[P]], 1 |
| ; IPSCCP-NEXT: call void @use(i1 true) |
| ; IPSCCP-NEXT: call void @use(i1 false) |
| ; IPSCCP-NEXT: ret void |
| ; |
| entry: |
| %c.1 = call i1 @cond() |
| br i1 %c.1, label %bb1, label %exit |
| |
| bb1: |
| %c.2 = call i1 @cond() |
| br i1 %c.2, label %bb2, label %exit |
| |
| bb2: |
| br label %exit |
| |
| exit: |
| %p = phi i32 [0, %entry], [1, %bb1], [2, %bb2] |
| %a = add i32 %p, 1 |
| %t.1 = icmp ult i32 %a, 20 |
| call void @use(i1 %t.1) |
| %f.1 = icmp ugt i32 %a, 10 |
| call void @use(i1 %f.1) |
| ret void |
| } |
| |
| define void @test_5_incoming_constants(i32 %x) { |
| ; SCCP-LABEL: @test_5_incoming_constants( |
| ; SCCP-NEXT: entry: |
| ; SCCP-NEXT: [[C_1:%.*]] = call i1 @cond() |
| ; SCCP-NEXT: br i1 [[C_1]], label [[BB1:%.*]], label [[EXIT:%.*]] |
| ; SCCP: bb1: |
| ; SCCP-NEXT: [[C_2:%.*]] = call i1 @cond() |
| ; SCCP-NEXT: br i1 [[C_2]], label [[BB2:%.*]], label [[EXIT]] |
| ; SCCP: bb2: |
| ; SCCP-NEXT: [[C_3:%.*]] = call i1 @cond() |
| ; SCCP-NEXT: br i1 [[C_3]], label [[BB3:%.*]], label [[EXIT]] |
| ; SCCP: bb3: |
| ; SCCP-NEXT: [[C_4:%.*]] = call i1 @cond() |
| ; SCCP-NEXT: br i1 [[C_4]], label [[BB4:%.*]], label [[EXIT]] |
| ; SCCP: bb4: |
| ; SCCP-NEXT: br label [[EXIT]] |
| ; SCCP: exit: |
| ; SCCP-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 1, [[BB1]] ], [ 2, [[BB2]] ], [ 3, [[BB3]] ], [ 4, [[BB4]] ] |
| ; SCCP-NEXT: [[A:%.*]] = add i32 [[P]], 1 |
| ; SCCP-NEXT: call void @use(i1 true) |
| ; SCCP-NEXT: call void @use(i1 false) |
| ; SCCP-NEXT: ret void |
| ; |
| ; IPSCCP-LABEL: @test_5_incoming_constants( |
| ; IPSCCP-NEXT: entry: |
| ; IPSCCP-NEXT: [[C_1:%.*]] = call i1 @cond() |
| ; IPSCCP-NEXT: br i1 [[C_1]], label [[BB1:%.*]], label [[EXIT:%.*]] |
| ; IPSCCP: bb1: |
| ; IPSCCP-NEXT: [[C_2:%.*]] = call i1 @cond() |
| ; IPSCCP-NEXT: br i1 [[C_2]], label [[BB2:%.*]], label [[EXIT]] |
| ; IPSCCP: bb2: |
| ; IPSCCP-NEXT: [[C_3:%.*]] = call i1 @cond() |
| ; IPSCCP-NEXT: br i1 [[C_3]], label [[BB3:%.*]], label [[EXIT]] |
| ; IPSCCP: bb3: |
| ; IPSCCP-NEXT: [[C_4:%.*]] = call i1 @cond() |
| ; IPSCCP-NEXT: br i1 [[C_4]], label [[BB4:%.*]], label [[EXIT]] |
| ; IPSCCP: bb4: |
| ; IPSCCP-NEXT: br label [[EXIT]] |
| ; IPSCCP: exit: |
| ; IPSCCP-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ 1, [[BB1]] ], [ 2, [[BB2]] ], [ 3, [[BB3]] ], [ 4, [[BB4]] ] |
| ; IPSCCP-NEXT: [[A:%.*]] = add i32 [[P]], 1 |
| ; IPSCCP-NEXT: call void @use(i1 true) |
| ; IPSCCP-NEXT: call void @use(i1 false) |
| ; IPSCCP-NEXT: ret void |
| ; |
| entry: |
| %c.1 = call i1 @cond() |
| br i1 %c.1, label %bb1, label %exit |
| |
| bb1: |
| %c.2 = call i1 @cond() |
| br i1 %c.2, label %bb2, label %exit |
| |
| bb2: |
| %c.3 = call i1 @cond() |
| br i1 %c.3, label %bb3, label %exit |
| |
| bb3: |
| %c.4 = call i1 @cond() |
| br i1 %c.4, label %bb4, label %exit |
| |
| bb4: |
| br label %exit |
| |
| exit: |
| %p = phi i32 [0, %entry], [1, %bb1], [2, %bb2], [3, %bb3], [4, %bb4] |
| %a = add i32 %p, 1 |
| %t.1 = icmp ult i32 %a, 20 |
| call void @use(i1 %t.1) |
| %f.1 = icmp ugt i32 %a, 10 |
| call void @use(i1 %f.1) |
| ret void |
| } |
| |
| ; For the rotated_loop_* test cases %p and %a are extended on each iteration. |
| |
| define void @rotated_loop_2(i32 %x) { |
| ; SCCP-LABEL: @rotated_loop_2( |
| ; SCCP-NEXT: entry: |
| ; SCCP-NEXT: [[C_1:%.*]] = call i1 @cond() |
| ; SCCP-NEXT: br i1 [[C_1]], label [[EXIT:%.*]], label [[BB1:%.*]] |
| ; SCCP: bb1: |
| ; SCCP-NEXT: [[C_2:%.*]] = call i1 @cond() |
| ; SCCP-NEXT: br i1 [[C_2]], label [[EXIT]], label [[BB2:%.*]] |
| ; SCCP: bb2: |
| ; SCCP-NEXT: [[C_3:%.*]] = call i1 @cond() |
| ; SCCP-NEXT: br i1 [[C_3]], label [[BB3:%.*]], label [[EXIT]] |
| ; SCCP: bb3: |
| ; SCCP-NEXT: br label [[EXIT]] |
| ; SCCP: exit: |
| ; SCCP-NEXT: [[P:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 3, [[BB1]] ], [ 2, [[BB2]] ], [ 5, [[BB3]] ], [ [[A:%.*]], [[EXIT]] ] |
| ; SCCP-NEXT: [[A]] = add i32 [[P]], 1 |
| ; SCCP-NEXT: call void @use(i1 true) |
| ; SCCP-NEXT: call void @use(i1 false) |
| ; SCCP-NEXT: br i1 false, label [[EXIT]], label [[EXIT_1:%.*]] |
| ; SCCP: exit.1: |
| ; SCCP-NEXT: ret void |
| ; |
| ; IPSCCP-LABEL: @rotated_loop_2( |
| ; IPSCCP-NEXT: entry: |
| ; IPSCCP-NEXT: [[C_1:%.*]] = call i1 @cond() |
| ; IPSCCP-NEXT: br i1 [[C_1]], label [[EXIT:%.*]], label [[BB1:%.*]] |
| ; IPSCCP: bb1: |
| ; IPSCCP-NEXT: [[C_2:%.*]] = call i1 @cond() |
| ; IPSCCP-NEXT: br i1 [[C_2]], label [[EXIT]], label [[BB2:%.*]] |
| ; IPSCCP: bb2: |
| ; IPSCCP-NEXT: [[C_3:%.*]] = call i1 @cond() |
| ; IPSCCP-NEXT: br i1 [[C_3]], label [[BB3:%.*]], label [[EXIT]] |
| ; IPSCCP: bb3: |
| ; IPSCCP-NEXT: br label [[EXIT]] |
| ; IPSCCP: exit: |
| ; IPSCCP-NEXT: [[P:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 3, [[BB1]] ], [ 2, [[BB2]] ], [ 5, [[BB3]] ] |
| ; IPSCCP-NEXT: [[A:%.*]] = add i32 [[P]], 1 |
| ; IPSCCP-NEXT: call void @use(i1 true) |
| ; IPSCCP-NEXT: call void @use(i1 false) |
| ; IPSCCP-NEXT: br label [[EXIT_1:%.*]] |
| ; IPSCCP: exit.1: |
| ; IPSCCP-NEXT: ret void |
| ; |
| entry: |
| %c.1 = call i1 @cond() |
| br i1 %c.1, label %exit, label %bb1 |
| |
| bb1: |
| %c.2 = call i1 @cond() |
| br i1 %c.2, label %exit, label %bb2 |
| |
| bb2: |
| %c.3 = call i1 @cond() |
| br i1 %c.3, label %bb3, label %exit |
| |
| bb3: |
| br label %exit |
| |
| exit: |
| %p = phi i32 [1, %entry], [3, %bb1], [2, %bb2], [5, %bb3], [%a, %exit] |
| %a = add i32 %p, 1 |
| %t.1 = icmp ult i32 %a, 20 |
| call void @use(i1 %t.1) |
| %f.1 = icmp ugt i32 %a, 10 |
| call void @use(i1 %f.1) |
| %c.4 = icmp ult i32 %a, 2 |
| br i1 %c.4, label %exit, label %exit.1 |
| |
| exit.1: |
| ret void |
| } |
| |
| define void @rotated_loop_3(i32 %x) { |
| ; SCCP-LABEL: @rotated_loop_3( |
| ; SCCP-NEXT: entry: |
| ; SCCP-NEXT: [[C_1:%.*]] = call i1 @cond() |
| ; SCCP-NEXT: br i1 [[C_1]], label [[EXIT:%.*]], label [[BB1:%.*]] |
| ; SCCP: bb1: |
| ; SCCP-NEXT: [[C_2:%.*]] = call i1 @cond() |
| ; SCCP-NEXT: br i1 [[C_2]], label [[EXIT]], label [[BB2:%.*]] |
| ; SCCP: bb2: |
| ; SCCP-NEXT: [[C_3:%.*]] = call i1 @cond() |
| ; SCCP-NEXT: br i1 [[C_3]], label [[BB3:%.*]], label [[EXIT]] |
| ; SCCP: bb3: |
| ; SCCP-NEXT: br label [[EXIT]] |
| ; SCCP: exit: |
| ; SCCP-NEXT: [[P:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 3, [[BB1]] ], [ 2, [[BB2]] ], [ 5, [[BB3]] ], [ [[A:%.*]], [[EXIT]] ] |
| ; SCCP-NEXT: [[A]] = add i32 [[P]], 1 |
| ; SCCP-NEXT: [[T_1:%.*]] = icmp ult i32 [[A]], 20 |
| ; SCCP-NEXT: call void @use(i1 [[T_1]]) |
| ; SCCP-NEXT: [[F_1:%.*]] = icmp ugt i32 [[A]], 10 |
| ; SCCP-NEXT: call void @use(i1 [[F_1]]) |
| ; SCCP-NEXT: [[C_4:%.*]] = icmp ult i32 [[A]], 3 |
| ; SCCP-NEXT: br i1 [[C_4]], label [[EXIT]], label [[EXIT_1:%.*]] |
| ; SCCP: exit.1: |
| ; SCCP-NEXT: ret void |
| ; |
| ; IPSCCP-LABEL: @rotated_loop_3( |
| ; IPSCCP-NEXT: entry: |
| ; IPSCCP-NEXT: [[C_1:%.*]] = call i1 @cond() |
| ; IPSCCP-NEXT: br i1 [[C_1]], label [[EXIT:%.*]], label [[BB1:%.*]] |
| ; IPSCCP: bb1: |
| ; IPSCCP-NEXT: [[C_2:%.*]] = call i1 @cond() |
| ; IPSCCP-NEXT: br i1 [[C_2]], label [[EXIT]], label [[BB2:%.*]] |
| ; IPSCCP: bb2: |
| ; IPSCCP-NEXT: [[C_3:%.*]] = call i1 @cond() |
| ; IPSCCP-NEXT: br i1 [[C_3]], label [[BB3:%.*]], label [[EXIT]] |
| ; IPSCCP: bb3: |
| ; IPSCCP-NEXT: br label [[EXIT]] |
| ; IPSCCP: exit: |
| ; IPSCCP-NEXT: [[P:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 3, [[BB1]] ], [ 2, [[BB2]] ], [ 5, [[BB3]] ], [ [[A:%.*]], [[EXIT]] ] |
| ; IPSCCP-NEXT: [[A]] = add i32 [[P]], 1 |
| ; IPSCCP-NEXT: [[T_1:%.*]] = icmp ult i32 [[A]], 20 |
| ; IPSCCP-NEXT: call void @use(i1 [[T_1]]) |
| ; IPSCCP-NEXT: [[F_1:%.*]] = icmp ugt i32 [[A]], 10 |
| ; IPSCCP-NEXT: call void @use(i1 [[F_1]]) |
| ; IPSCCP-NEXT: [[C_4:%.*]] = icmp ult i32 [[A]], 3 |
| ; IPSCCP-NEXT: br i1 [[C_4]], label [[EXIT]], label [[EXIT_1:%.*]] |
| ; IPSCCP: exit.1: |
| ; IPSCCP-NEXT: ret void |
| ; |
| entry: |
| %c.1 = call i1 @cond() |
| br i1 %c.1, label %exit, label %bb1 |
| |
| bb1: |
| %c.2 = call i1 @cond() |
| br i1 %c.2, label %exit, label %bb2 |
| |
| bb2: |
| %c.3 = call i1 @cond() |
| br i1 %c.3, label %bb3, label %exit |
| |
| bb3: |
| br label %exit |
| |
| exit: |
| %p = phi i32 [1, %entry], [3, %bb1], [2, %bb2], [5, %bb3], [%a, %exit] |
| %a = add i32 %p, 1 |
| %t.1 = icmp ult i32 %a, 20 |
| call void @use(i1 %t.1) |
| %f.1 = icmp ugt i32 %a, 10 |
| call void @use(i1 %f.1) |
| %c.4 = icmp ult i32 %a, 3 |
| br i1 %c.4, label %exit, label %exit.1 |
| |
| exit.1: |
| ret void |
| } |
| |
| ; For the loop_with_header_* tests, %iv and %a change on each iteration, but we |
| ; can use the range imposed by the condition %c.1 when widening. |
| define void @loop_with_header_1(i32 %x) { |
| ; SCCP-LABEL: @loop_with_header_1( |
| ; SCCP-NEXT: entry: |
| ; SCCP-NEXT: br label [[LOOP_HEADER:%.*]] |
| ; SCCP: loop.header: |
| ; SCCP-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_BODY:%.*]] ] |
| ; SCCP-NEXT: [[C_1:%.*]] = icmp slt i32 [[IV]], 2 |
| ; SCCP-NEXT: br i1 [[C_1]], label [[LOOP_BODY]], label [[EXIT:%.*]] |
| ; SCCP: loop.body: |
| ; SCCP-NEXT: [[T_1:%.*]] = icmp slt i32 [[IV]], 2 |
| ; SCCP-NEXT: call void @use(i1 [[T_1]]) |
| ; SCCP-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1 |
| ; SCCP-NEXT: br label [[LOOP_HEADER]] |
| ; SCCP: exit: |
| ; SCCP-NEXT: ret void |
| ; |
| ; IPSCCP-LABEL: @loop_with_header_1( |
| ; IPSCCP-NEXT: entry: |
| ; IPSCCP-NEXT: br label [[LOOP_HEADER:%.*]] |
| ; IPSCCP: loop.header: |
| ; IPSCCP-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_BODY:%.*]] ] |
| ; IPSCCP-NEXT: [[C_1:%.*]] = icmp slt i32 [[IV]], 2 |
| ; IPSCCP-NEXT: br i1 [[C_1]], label [[LOOP_BODY]], label [[EXIT:%.*]] |
| ; IPSCCP: loop.body: |
| ; IPSCCP-NEXT: call void @use(i1 true) |
| ; IPSCCP-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1 |
| ; IPSCCP-NEXT: br label [[LOOP_HEADER]] |
| ; IPSCCP: exit: |
| ; IPSCCP-NEXT: ret void |
| ; |
| entry: |
| br label %loop.header |
| |
| loop.header: |
| %iv = phi i32 [0, %entry], [%iv.next, %loop.body] |
| %c.1 = icmp slt i32 %iv, 2 |
| br i1 %c.1, label %loop.body, label %exit |
| |
| loop.body: |
| %t.1 = icmp slt i32 %iv, 2 |
| call void @use(i1 %t.1) |
| %iv.next = add nsw i32 %iv, 1 |
| br label %loop.header |
| |
| exit: |
| ret void |
| } |
| |
| define void @loop_with_header_2(i32 %x) { |
| ; SCCP-LABEL: @loop_with_header_2( |
| ; SCCP-NEXT: entry: |
| ; SCCP-NEXT: br label [[LOOP_HEADER:%.*]] |
| ; SCCP: loop.header: |
| ; SCCP-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_BODY:%.*]] ] |
| ; SCCP-NEXT: [[C_1:%.*]] = icmp slt i32 [[IV]], 200 |
| ; SCCP-NEXT: br i1 [[C_1]], label [[LOOP_BODY]], label [[EXIT:%.*]] |
| ; SCCP: loop.body: |
| ; SCCP-NEXT: [[T_1:%.*]] = icmp slt i32 [[IV]], 200 |
| ; SCCP-NEXT: call void @use(i1 [[T_1]]) |
| ; SCCP-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1 |
| ; SCCP-NEXT: br label [[LOOP_HEADER]] |
| ; SCCP: exit: |
| ; SCCP-NEXT: ret void |
| ; |
| ; IPSCCP-LABEL: @loop_with_header_2( |
| ; IPSCCP-NEXT: entry: |
| ; IPSCCP-NEXT: br label [[LOOP_HEADER:%.*]] |
| ; IPSCCP: loop.header: |
| ; IPSCCP-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_BODY:%.*]] ] |
| ; IPSCCP-NEXT: [[C_1:%.*]] = icmp slt i32 [[IV]], 200 |
| ; IPSCCP-NEXT: br i1 [[C_1]], label [[LOOP_BODY]], label [[EXIT:%.*]] |
| ; IPSCCP: loop.body: |
| ; IPSCCP-NEXT: call void @use(i1 true) |
| ; IPSCCP-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1 |
| ; IPSCCP-NEXT: br label [[LOOP_HEADER]] |
| ; IPSCCP: exit: |
| ; IPSCCP-NEXT: ret void |
| ; |
| entry: |
| br label %loop.header |
| |
| loop.header: |
| %iv = phi i32 [0, %entry], [%iv.next, %loop.body] |
| %c.1 = icmp slt i32 %iv, 200 |
| br i1 %c.1, label %loop.body, label %exit |
| |
| loop.body: |
| %t.1 = icmp slt i32 %iv, 200 |
| call void @use(i1 %t.1) |
| %iv.next = add nsw i32 %iv, 1 |
| br label %loop.header |
| |
| exit: |
| ret void |
| } |
| |
| ; In the function below, the condition %c.1 results in a range [7, 6), which |
| ; can be used as a widening bound. It does not fully contain the range we get |
| ; from combining it with the information from %tmp12. |
| define void @foo(i64* %arg) { |
| ; SCCP-LABEL: @foo( |
| ; SCCP-NEXT: bb: |
| ; SCCP-NEXT: [[TMP:%.*]] = zext i8 undef to i32 |
| ; SCCP-NEXT: [[TMP1:%.*]] = getelementptr inbounds i64, i64* [[ARG:%.*]], i32 0 |
| ; SCCP-NEXT: [[TMP2:%.*]] = load i64, i64* [[TMP1]], align 8 |
| ; SCCP-NEXT: switch i32 [[TMP]], label [[BB20:%.*]] [ |
| ; SCCP-NEXT: i32 1, label [[BB3:%.*]] |
| ; SCCP-NEXT: i32 2, label [[BB4:%.*]] |
| ; SCCP-NEXT: i32 4, label [[BB19:%.*]] |
| ; SCCP-NEXT: ] |
| ; SCCP: bb3: |
| ; SCCP-NEXT: unreachable |
| ; SCCP: bb4: |
| ; SCCP-NEXT: [[TMP5:%.*]] = add i64 [[TMP2]], 3 |
| ; SCCP-NEXT: [[TMP6:%.*]] = and i64 [[TMP5]], 3 |
| ; SCCP-NEXT: [[TMP7:%.*]] = sub i64 3, [[TMP6]] |
| ; SCCP-NEXT: [[TMP8:%.*]] = shl i64 [[TMP7]], 1 |
| ; SCCP-NEXT: [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32 |
| ; SCCP-NEXT: [[TMP0:%.*]] = zext i32 [[TMP9]] to i64 |
| ; SCCP-NEXT: br label [[BB11:%.*]] |
| ; SCCP: bb11: |
| ; SCCP-NEXT: [[TMP12:%.*]] = phi i64 [ [[TMP0]], [[BB4]] ], [ [[TMP17:%.*]], [[BB18:%.*]] ] |
| ; SCCP-NEXT: br label [[BB13:%.*]] |
| ; SCCP: bb13: |
| ; SCCP-NEXT: [[C_1:%.*]] = icmp eq i64 [[TMP12]], 6 |
| ; SCCP-NEXT: br i1 [[C_1]], label [[BB15:%.*]], label [[BB16:%.*]] |
| ; SCCP: bb15: |
| ; SCCP-NEXT: unreachable |
| ; SCCP: bb16: |
| ; SCCP-NEXT: [[TMP17]] = add i64 [[TMP12]], 2 |
| ; SCCP-NEXT: br label [[BB18]] |
| ; SCCP: bb18: |
| ; SCCP-NEXT: br label [[BB11]] |
| ; SCCP: bb19: |
| ; SCCP-NEXT: unreachable |
| ; SCCP: bb20: |
| ; SCCP-NEXT: ret void |
| ; |
| ; IPSCCP-LABEL: @foo( |
| ; IPSCCP-NEXT: bb: |
| ; IPSCCP-NEXT: [[TMP:%.*]] = zext i8 undef to i32 |
| ; IPSCCP-NEXT: [[TMP1:%.*]] = getelementptr inbounds i64, i64* [[ARG:%.*]], i32 0 |
| ; IPSCCP-NEXT: [[TMP2:%.*]] = load i64, i64* [[TMP1]], align 8 |
| ; IPSCCP-NEXT: switch i32 [[TMP]], label [[BB20:%.*]] [ |
| ; IPSCCP-NEXT: i32 1, label [[BB3:%.*]] |
| ; IPSCCP-NEXT: i32 2, label [[BB4:%.*]] |
| ; IPSCCP-NEXT: i32 4, label [[BB19:%.*]] |
| ; IPSCCP-NEXT: ] |
| ; IPSCCP: bb3: |
| ; IPSCCP-NEXT: unreachable |
| ; IPSCCP: bb4: |
| ; IPSCCP-NEXT: [[TMP5:%.*]] = add i64 [[TMP2]], 3 |
| ; IPSCCP-NEXT: [[TMP6:%.*]] = and i64 [[TMP5]], 3 |
| ; IPSCCP-NEXT: [[TMP7:%.*]] = sub i64 3, [[TMP6]] |
| ; IPSCCP-NEXT: [[TMP8:%.*]] = shl i64 [[TMP7]], 1 |
| ; IPSCCP-NEXT: [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32 |
| ; IPSCCP-NEXT: [[TMP0:%.*]] = zext i32 [[TMP9]] to i64 |
| ; IPSCCP-NEXT: br label [[BB11:%.*]] |
| ; IPSCCP: bb11: |
| ; IPSCCP-NEXT: [[TMP12:%.*]] = phi i64 [ [[TMP0]], [[BB4]] ], [ [[TMP17:%.*]], [[BB18:%.*]] ] |
| ; IPSCCP-NEXT: br label [[BB13:%.*]] |
| ; IPSCCP: bb13: |
| ; IPSCCP-NEXT: [[C_1:%.*]] = icmp eq i64 [[TMP12]], 6 |
| ; IPSCCP-NEXT: br i1 [[C_1]], label [[BB15:%.*]], label [[BB16:%.*]] |
| ; IPSCCP: bb15: |
| ; IPSCCP-NEXT: unreachable |
| ; IPSCCP: bb16: |
| ; IPSCCP-NEXT: [[TMP17]] = add i64 [[TMP12]], 2 |
| ; IPSCCP-NEXT: br label [[BB18]] |
| ; IPSCCP: bb18: |
| ; IPSCCP-NEXT: br label [[BB11]] |
| ; IPSCCP: bb19: |
| ; IPSCCP-NEXT: unreachable |
| ; IPSCCP: bb20: |
| ; IPSCCP-NEXT: ret void |
| ; |
| bb: |
| %tmp = zext i8 undef to i32 |
| %tmp1 = getelementptr inbounds i64, i64* %arg, i32 0 |
| %tmp2 = load i64, i64* %tmp1, align 8 |
| switch i32 %tmp, label %bb20 [ |
| i32 1, label %bb3 |
| i32 2, label %bb4 |
| i32 4, label %bb19 |
| ] |
| |
| bb3: ; preds = %bb |
| unreachable |
| |
| bb4: ; preds = %bb |
| %tmp5 = add i64 %tmp2, 3 |
| %tmp6 = and i64 %tmp5, 3 |
| %tmp7 = sub i64 3, %tmp6 |
| %tmp8 = shl i64 %tmp7, 1 |
| %tmp9 = trunc i64 %tmp8 to i32 |
| %tmp10 = sext i32 %tmp9 to i64 |
| br label %bb11 |
| |
| bb11: ; preds = %bb18, %bb4 |
| %tmp12 = phi i64 [ %tmp10, %bb4 ], [ %tmp17, %bb18 ] |
| br label %bb13 |
| |
| bb13: ; preds = %bb11 |
| %c.1 = icmp eq i64 %tmp12, 6 |
| br i1 %c.1, label %bb15, label %bb16 |
| |
| bb15: ; preds = %bb13 |
| unreachable |
| |
| bb16: ; preds = %bb13 |
| %tmp17 = add i64 %tmp12, 2 |
| br label %bb18 |
| |
| bb18: ; preds = %bb16 |
| br label %bb11 |
| |
| bb19: ; preds = %bb |
| unreachable |
| |
| bb20: ; preds = %bb |
| ret void |
| } |
| |
| ; The functions below check that widening with an upper bound does correctly |
| ; return whether the range changed. Make sure we do not eliminate %c.2. |
| |
| %struct.baz.1 = type { i32, i32, i8*, i8* } |
| %struct.blam.2 = type <{ %struct.baz.1, i32, [4 x i8] }> |
| |
| @global.11 = linkonce_odr global [4 x i8] zeroinitializer, align 1 |
| |
| declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg) #1 |
| |
| define linkonce_odr dereferenceable(1) i8* @spam(%struct.baz.1* %arg, i32 %arg1) align 2 { |
| ; SCCP-LABEL: @spam( |
| ; SCCP-NEXT: bb: |
| ; SCCP-NEXT: [[TMP:%.*]] = getelementptr inbounds [[STRUCT_BAZ_1:%.*]], %struct.baz.1* [[ARG:%.*]], i32 0, i32 3 |
| ; SCCP-NEXT: [[TMP2:%.*]] = load i8*, i8** [[TMP]], align 8 |
| ; SCCP-NEXT: [[TMP3:%.*]] = sext i32 [[ARG1:%.*]] to i64 |
| ; SCCP-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, i8* [[TMP2]], i64 [[TMP3]] |
| ; SCCP-NEXT: ret i8* [[TMP4]] |
| ; |
| ; IPSCCP-LABEL: @spam( |
| ; IPSCCP-NEXT: bb: |
| ; IPSCCP-NEXT: [[TMP:%.*]] = getelementptr inbounds [[STRUCT_BAZ_1:%.*]], %struct.baz.1* [[ARG:%.*]], i32 0, i32 3 |
| ; IPSCCP-NEXT: [[TMP2:%.*]] = load i8*, i8** [[TMP]], align 8 |
| ; IPSCCP-NEXT: [[TMP3:%.*]] = sext i32 [[ARG1:%.*]] to i64 |
| ; IPSCCP-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, i8* [[TMP2]], i64 [[TMP3]] |
| ; IPSCCP-NEXT: ret i8* [[TMP4]] |
| ; |
| bb: |
| %tmp = getelementptr inbounds %struct.baz.1, %struct.baz.1* %arg, i32 0, i32 3 |
| %tmp2 = load i8*, i8** %tmp, align 8 |
| %tmp3 = sext i32 %arg1 to i64 |
| %tmp4 = getelementptr inbounds i8, i8* %tmp2, i64 %tmp3 |
| ret i8* %tmp4 |
| } |
| |
| define i8* @wobble(%struct.blam.2* %arg, i32 %arg1) align 2 { |
| ; SCCP-LABEL: @wobble( |
| ; SCCP-NEXT: bb: |
| ; SCCP-NEXT: [[TMP:%.*]] = lshr i32 [[ARG1:%.*]], 16 |
| ; SCCP-NEXT: [[TMP2:%.*]] = xor i32 [[TMP]], [[ARG1]] |
| ; SCCP-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 65535 |
| ; SCCP-NEXT: [[TMP4:%.*]] = mul i32 [[ARG1]], 8 |
| ; SCCP-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2:%.*]], %struct.blam.2* [[ARG:%.*]], i32 0, i32 1 |
| ; SCCP-NEXT: [[TMP6:%.*]] = load i32, i32* [[TMP5]], align 8 |
| ; SCCP-NEXT: [[TMP7:%.*]] = and i32 [[TMP4]], [[TMP6]] |
| ; SCCP-NEXT: br label [[BB8:%.*]] |
| ; SCCP: bb8: |
| ; SCCP-NEXT: [[TMP9:%.*]] = phi i8* [ undef, [[BB:%.*]] ], [ [[TMP17:%.*]], [[BB29:%.*]] ] |
| ; SCCP-NEXT: [[TMP10:%.*]] = phi i16* [ undef, [[BB]] ], [ [[TMP18:%.*]], [[BB29]] ] |
| ; SCCP-NEXT: [[TMP11:%.*]] = phi i32 [ 0, [[BB]] ], [ [[TMP30:%.*]], [[BB29]] ] |
| ; SCCP-NEXT: [[C_1:%.*]] = icmp slt i32 [[TMP11]], 8 |
| ; SCCP-NEXT: br i1 [[C_1]], label [[BB13:%.*]], label [[BB31:%.*]] |
| ; SCCP: bb13: |
| ; SCCP-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0 |
| ; SCCP-NEXT: [[TMP15:%.*]] = add i32 [[TMP7]], [[TMP11]] |
| ; SCCP-NEXT: [[TMP16:%.*]] = mul i32 [[TMP15]], 4 |
| ; SCCP-NEXT: [[TMP17]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP14]], i32 [[TMP16]]) |
| ; SCCP-NEXT: [[TMP18]] = bitcast i8* [[TMP17]] to i16* |
| ; SCCP-NEXT: [[TMP19:%.*]] = getelementptr inbounds i8, i8* [[TMP17]], i64 2 |
| ; SCCP-NEXT: [[TMP20:%.*]] = load i8, i8* [[TMP19]], align 1 |
| ; SCCP-NEXT: [[TMP21:%.*]] = zext i8 [[TMP20]] to i32 |
| ; SCCP-NEXT: [[TMP22:%.*]] = icmp eq i32 [[TMP21]], 0 |
| ; SCCP-NEXT: br i1 [[TMP22]], label [[BB23:%.*]], label [[BB25:%.*]] |
| ; SCCP: bb23: |
| ; SCCP-NEXT: [[TMP24:%.*]] = trunc i32 [[TMP3]] to i16 |
| ; SCCP-NEXT: store i16 [[TMP24]], i16* [[TMP18]], align 2 |
| ; SCCP-NEXT: br label [[BB31]] |
| ; SCCP: bb25: |
| ; SCCP-NEXT: [[TMP26:%.*]] = load i16, i16* [[TMP18]], align 2 |
| ; SCCP-NEXT: [[TMP27:%.*]] = zext i16 [[TMP26]] to i32 |
| ; SCCP-NEXT: [[TMP28:%.*]] = icmp eq i32 [[TMP27]], [[TMP3]] |
| ; SCCP-NEXT: br i1 [[TMP28]], label [[BB31]], label [[BB29]] |
| ; SCCP: bb29: |
| ; SCCP-NEXT: [[TMP30]] = add nsw i32 [[TMP11]], 1 |
| ; SCCP-NEXT: br label [[BB8]] |
| ; SCCP: bb31: |
| ; SCCP-NEXT: [[TMP32:%.*]] = phi i8* [ [[TMP17]], [[BB23]] ], [ [[TMP17]], [[BB25]] ], [ [[TMP9]], [[BB8]] ] |
| ; SCCP-NEXT: [[TMP33:%.*]] = phi i16* [ [[TMP18]], [[BB23]] ], [ [[TMP18]], [[BB25]] ], [ [[TMP10]], [[BB8]] ] |
| ; SCCP-NEXT: [[TMP34:%.*]] = icmp eq i32 [[TMP11]], 0 |
| ; SCCP-NEXT: br i1 [[TMP34]], label [[BB35:%.*]], label [[BB37:%.*]] |
| ; SCCP: bb35: |
| ; SCCP-NEXT: [[TMP36:%.*]] = getelementptr inbounds i8, i8* [[TMP32]], i64 1 |
| ; SCCP-NEXT: br label [[BB66:%.*]] |
| ; SCCP: bb37: |
| ; SCCP-NEXT: [[C_2:%.*]] = icmp eq i32 [[TMP11]], 8 |
| ; SCCP-NEXT: br i1 [[C_2]], label [[BB39:%.*]], label [[BB58:%.*]] |
| ; SCCP: bb39: |
| ; SCCP-NEXT: [[TMP40:%.*]] = add nsw i32 [[TMP11]], -1 |
| ; SCCP-NEXT: [[TMP41:%.*]] = trunc i32 [[TMP3]] to i16 |
| ; SCCP-NEXT: store i16 [[TMP41]], i16* bitcast ([4 x i8]* @global.11 to i16*), align 1 |
| ; SCCP-NEXT: [[TMP42:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0 |
| ; SCCP-NEXT: [[TMP43:%.*]] = add i32 [[TMP7]], [[TMP40]] |
| ; SCCP-NEXT: [[TMP44:%.*]] = mul i32 [[TMP43]], 4 |
| ; SCCP-NEXT: [[TMP45:%.*]] = add i32 [[TMP44]], 2 |
| ; SCCP-NEXT: [[TMP46:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP42]], i32 [[TMP45]]) |
| ; SCCP-NEXT: [[TMP47:%.*]] = load i8, i8* [[TMP46]], align 1 |
| ; SCCP-NEXT: [[TMP48:%.*]] = zext i8 [[TMP47]] to i32 |
| ; SCCP-NEXT: [[TMP49:%.*]] = sub i32 [[TMP43]], 1 |
| ; SCCP-NEXT: [[TMP50:%.*]] = mul i32 [[TMP49]], 4 |
| ; SCCP-NEXT: [[TMP51:%.*]] = add i32 [[TMP50]], 2 |
| ; SCCP-NEXT: [[TMP52:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP42]], i32 [[TMP51]]) |
| ; SCCP-NEXT: [[TMP53:%.*]] = load i8, i8* [[TMP52]], align 1 |
| ; SCCP-NEXT: [[TMP54:%.*]] = zext i8 [[TMP53]] to i32 |
| ; SCCP-NEXT: [[TMP55:%.*]] = icmp sgt i32 [[TMP48]], [[TMP54]] |
| ; SCCP-NEXT: br i1 [[TMP55]], label [[BB56:%.*]], label [[BB60:%.*]] |
| ; SCCP: bb56: |
| ; SCCP-NEXT: [[TMP57:%.*]] = add nsw i32 [[TMP40]], -1 |
| ; SCCP-NEXT: br label [[BB60]] |
| ; SCCP: bb58: |
| ; SCCP-NEXT: [[TMP59:%.*]] = bitcast i16* [[TMP33]] to i8* |
| ; SCCP-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 getelementptr inbounds ([4 x i8], [4 x i8]* @global.11, i64 0, i64 0), i8* align 2 [[TMP59]], i64 4, i1 false) |
| ; SCCP-NEXT: br label [[BB60]] |
| ; SCCP: bb60: |
| ; SCCP-NEXT: [[TMP61:%.*]] = phi i32 [ [[TMP57]], [[BB56]] ], [ [[TMP40]], [[BB39]] ], [ [[TMP11]], [[BB58]] ] |
| ; SCCP-NEXT: [[TMP62:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0 |
| ; SCCP-NEXT: [[TMP63:%.*]] = add i32 [[TMP7]], 1 |
| ; SCCP-NEXT: [[TMP64:%.*]] = mul i32 [[TMP63]], 4 |
| ; SCCP-NEXT: [[TMP65:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP62]], i32 [[TMP64]]) |
| ; SCCP-NEXT: br label [[BB66]] |
| ; SCCP: bb66: |
| ; SCCP-NEXT: [[TMP67:%.*]] = phi i8* [ [[TMP36]], [[BB35]] ], [ null, [[BB60]] ] |
| ; SCCP-NEXT: ret i8* [[TMP67]] |
| ; |
| ; IPSCCP-LABEL: @wobble( |
| ; IPSCCP-NEXT: bb: |
| ; IPSCCP-NEXT: [[TMP:%.*]] = lshr i32 [[ARG1:%.*]], 16 |
| ; IPSCCP-NEXT: [[TMP2:%.*]] = xor i32 [[TMP]], [[ARG1]] |
| ; IPSCCP-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 65535 |
| ; IPSCCP-NEXT: [[TMP4:%.*]] = mul i32 [[ARG1]], 8 |
| ; IPSCCP-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2:%.*]], %struct.blam.2* [[ARG:%.*]], i32 0, i32 1 |
| ; IPSCCP-NEXT: [[TMP6:%.*]] = load i32, i32* [[TMP5]], align 8 |
| ; IPSCCP-NEXT: [[TMP7:%.*]] = and i32 [[TMP4]], [[TMP6]] |
| ; IPSCCP-NEXT: br label [[BB8:%.*]] |
| ; IPSCCP: bb8: |
| ; IPSCCP-NEXT: [[TMP9:%.*]] = phi i8* [ undef, [[BB:%.*]] ], [ [[TMP17:%.*]], [[BB29:%.*]] ] |
| ; IPSCCP-NEXT: [[TMP10:%.*]] = phi i16* [ undef, [[BB]] ], [ [[TMP18:%.*]], [[BB29]] ] |
| ; IPSCCP-NEXT: [[TMP11:%.*]] = phi i32 [ 0, [[BB]] ], [ [[TMP30:%.*]], [[BB29]] ] |
| ; IPSCCP-NEXT: [[C_1:%.*]] = icmp slt i32 [[TMP11]], 8 |
| ; IPSCCP-NEXT: br i1 [[C_1]], label [[BB13:%.*]], label [[BB31:%.*]] |
| ; IPSCCP: bb13: |
| ; IPSCCP-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0 |
| ; IPSCCP-NEXT: [[TMP15:%.*]] = add i32 [[TMP7]], [[TMP11]] |
| ; IPSCCP-NEXT: [[TMP16:%.*]] = mul i32 [[TMP15]], 4 |
| ; IPSCCP-NEXT: [[TMP17]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP14]], i32 [[TMP16]]) |
| ; IPSCCP-NEXT: [[TMP18]] = bitcast i8* [[TMP17]] to i16* |
| ; IPSCCP-NEXT: [[TMP19:%.*]] = getelementptr inbounds i8, i8* [[TMP17]], i64 2 |
| ; IPSCCP-NEXT: [[TMP20:%.*]] = load i8, i8* [[TMP19]], align 1 |
| ; IPSCCP-NEXT: [[TMP21:%.*]] = zext i8 [[TMP20]] to i32 |
| ; IPSCCP-NEXT: [[TMP22:%.*]] = icmp eq i32 [[TMP21]], 0 |
| ; IPSCCP-NEXT: br i1 [[TMP22]], label [[BB23:%.*]], label [[BB25:%.*]] |
| ; IPSCCP: bb23: |
| ; IPSCCP-NEXT: [[TMP24:%.*]] = trunc i32 [[TMP3]] to i16 |
| ; IPSCCP-NEXT: store i16 [[TMP24]], i16* [[TMP18]], align 2 |
| ; IPSCCP-NEXT: br label [[BB31]] |
| ; IPSCCP: bb25: |
| ; IPSCCP-NEXT: [[TMP26:%.*]] = load i16, i16* [[TMP18]], align 2 |
| ; IPSCCP-NEXT: [[TMP27:%.*]] = zext i16 [[TMP26]] to i32 |
| ; IPSCCP-NEXT: [[TMP28:%.*]] = icmp eq i32 [[TMP27]], [[TMP3]] |
| ; IPSCCP-NEXT: br i1 [[TMP28]], label [[BB31]], label [[BB29]] |
| ; IPSCCP: bb29: |
| ; IPSCCP-NEXT: [[TMP30]] = add nsw i32 [[TMP11]], 1 |
| ; IPSCCP-NEXT: br label [[BB8]] |
| ; IPSCCP: bb31: |
| ; IPSCCP-NEXT: [[TMP32:%.*]] = phi i8* [ [[TMP17]], [[BB23]] ], [ [[TMP17]], [[BB25]] ], [ [[TMP9]], [[BB8]] ] |
| ; IPSCCP-NEXT: [[TMP33:%.*]] = phi i16* [ [[TMP18]], [[BB23]] ], [ [[TMP18]], [[BB25]] ], [ [[TMP10]], [[BB8]] ] |
| ; IPSCCP-NEXT: [[TMP34:%.*]] = icmp eq i32 [[TMP11]], 0 |
| ; IPSCCP-NEXT: br i1 [[TMP34]], label [[BB35:%.*]], label [[BB37:%.*]] |
| ; IPSCCP: bb35: |
| ; IPSCCP-NEXT: [[TMP36:%.*]] = getelementptr inbounds i8, i8* [[TMP32]], i64 1 |
| ; IPSCCP-NEXT: br label [[BB66:%.*]] |
| ; IPSCCP: bb37: |
| ; IPSCCP-NEXT: [[C_2:%.*]] = icmp eq i32 [[TMP11]], 8 |
| ; IPSCCP-NEXT: br i1 [[C_2]], label [[BB39:%.*]], label [[BB58:%.*]] |
| ; IPSCCP: bb39: |
| ; IPSCCP-NEXT: [[TMP41:%.*]] = trunc i32 [[TMP3]] to i16 |
| ; IPSCCP-NEXT: store i16 [[TMP41]], i16* bitcast ([4 x i8]* @global.11 to i16*), align 1 |
| ; IPSCCP-NEXT: [[TMP42:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0 |
| ; IPSCCP-NEXT: [[TMP43:%.*]] = add i32 [[TMP7]], 7 |
| ; IPSCCP-NEXT: [[TMP44:%.*]] = mul i32 [[TMP43]], 4 |
| ; IPSCCP-NEXT: [[TMP45:%.*]] = add i32 [[TMP44]], 2 |
| ; IPSCCP-NEXT: [[TMP46:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP42]], i32 [[TMP45]]) |
| ; IPSCCP-NEXT: [[TMP47:%.*]] = load i8, i8* [[TMP46]], align 1 |
| ; IPSCCP-NEXT: [[TMP48:%.*]] = zext i8 [[TMP47]] to i32 |
| ; IPSCCP-NEXT: [[TMP49:%.*]] = sub i32 [[TMP43]], 1 |
| ; IPSCCP-NEXT: [[TMP50:%.*]] = mul i32 [[TMP49]], 4 |
| ; IPSCCP-NEXT: [[TMP51:%.*]] = add i32 [[TMP50]], 2 |
| ; IPSCCP-NEXT: [[TMP52:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP42]], i32 [[TMP51]]) |
| ; IPSCCP-NEXT: [[TMP53:%.*]] = load i8, i8* [[TMP52]], align 1 |
| ; IPSCCP-NEXT: [[TMP54:%.*]] = zext i8 [[TMP53]] to i32 |
| ; IPSCCP-NEXT: [[TMP55:%.*]] = icmp sgt i32 [[TMP48]], [[TMP54]] |
| ; IPSCCP-NEXT: br i1 [[TMP55]], label [[BB56:%.*]], label [[BB60:%.*]] |
| ; IPSCCP: bb56: |
| ; IPSCCP-NEXT: br label [[BB60]] |
| ; IPSCCP: bb58: |
| ; IPSCCP-NEXT: [[TMP59:%.*]] = bitcast i16* [[TMP33]] to i8* |
| ; IPSCCP-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 getelementptr inbounds ([4 x i8], [4 x i8]* @global.11, i64 0, i64 0), i8* align 2 [[TMP59]], i64 4, i1 false) |
| ; IPSCCP-NEXT: br label [[BB60]] |
| ; IPSCCP: bb60: |
| ; IPSCCP-NEXT: [[TMP61:%.*]] = phi i32 [ 6, [[BB56]] ], [ 7, [[BB39]] ], [ [[TMP11]], [[BB58]] ] |
| ; IPSCCP-NEXT: [[TMP62:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0 |
| ; IPSCCP-NEXT: [[TMP63:%.*]] = add i32 [[TMP7]], 1 |
| ; IPSCCP-NEXT: [[TMP64:%.*]] = mul i32 [[TMP63]], 4 |
| ; IPSCCP-NEXT: [[TMP65:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP62]], i32 [[TMP64]]) |
| ; IPSCCP-NEXT: br label [[BB66]] |
| ; IPSCCP: bb66: |
| ; IPSCCP-NEXT: [[TMP67:%.*]] = phi i8* [ [[TMP36]], [[BB35]] ], [ null, [[BB60]] ] |
| ; IPSCCP-NEXT: ret i8* [[TMP67]] |
| ; |
| bb: |
| %tmp = lshr i32 %arg1, 16 |
| %tmp2 = xor i32 %tmp, %arg1 |
| %tmp3 = and i32 %tmp2, 65535 |
| %tmp4 = mul i32 %arg1, 8 |
| %tmp5 = getelementptr inbounds %struct.blam.2, %struct.blam.2* %arg, i32 0, i32 1 |
| %tmp6 = load i32, i32* %tmp5, align 8 |
| %tmp7 = and i32 %tmp4, %tmp6 |
| br label %bb8 |
| |
| bb8: ; preds = %bb29, %bb |
| %tmp9 = phi i8* [ undef, %bb ], [ %tmp17, %bb29 ] |
| %tmp10 = phi i16* [ undef, %bb ], [ %tmp18, %bb29 ] |
| %tmp11 = phi i32 [ 0, %bb ], [ %tmp30, %bb29 ] |
| %c.1 = icmp slt i32 %tmp11, 8 |
| br i1 %c.1, label %bb13, label %bb31 |
| |
| bb13: ; preds = %bb8 |
| %tmp14 = getelementptr inbounds %struct.blam.2, %struct.blam.2* %arg, i32 0, i32 0 |
| %tmp15 = add i32 %tmp7, %tmp11 |
| %tmp16 = mul i32 %tmp15, 4 |
| %tmp17 = call dereferenceable(1) i8* @spam(%struct.baz.1* %tmp14, i32 %tmp16) |
| %tmp18 = bitcast i8* %tmp17 to i16* |
| %tmp19 = getelementptr inbounds i8, i8* %tmp17, i64 2 |
| %tmp20 = load i8, i8* %tmp19, align 1 |
| %tmp21 = zext i8 %tmp20 to i32 |
| %tmp22 = icmp eq i32 %tmp21, 0 |
| br i1 %tmp22, label %bb23, label %bb25 |
| |
| bb23: ; preds = %bb13 |
| %tmp24 = trunc i32 %tmp3 to i16 |
| store i16 %tmp24, i16* %tmp18, align 2 |
| br label %bb31 |
| |
| bb25: ; preds = %bb13 |
| %tmp26 = load i16, i16* %tmp18, align 2 |
| %tmp27 = zext i16 %tmp26 to i32 |
| %tmp28 = icmp eq i32 %tmp27, %tmp3 |
| br i1 %tmp28, label %bb31, label %bb29 |
| |
| bb29: ; preds = %bb25 |
| %tmp30 = add nsw i32 %tmp11, 1 |
| br label %bb8 |
| |
| bb31: ; preds = %bb25, %bb23, %bb8 |
| %tmp32 = phi i8* [ %tmp17, %bb23 ], [ %tmp17, %bb25 ], [ %tmp9, %bb8 ] |
| %tmp33 = phi i16* [ %tmp18, %bb23 ], [ %tmp18, %bb25 ], [ %tmp10, %bb8 ] |
| %tmp34 = icmp eq i32 %tmp11, 0 |
| br i1 %tmp34, label %bb35, label %bb37 |
| |
| bb35: ; preds = %bb31 |
| %tmp36 = getelementptr inbounds i8, i8* %tmp32, i64 1 |
| br label %bb66 |
| |
| bb37: ; preds = %bb31 |
| %c.2 = icmp eq i32 %tmp11, 8 |
| br i1 %c.2, label %bb39, label %bb58 |
| |
| bb39: ; preds = %bb37 |
| %tmp40 = add nsw i32 %tmp11, -1 |
| %tmp41 = trunc i32 %tmp3 to i16 |
| store i16 %tmp41, i16* bitcast ([4 x i8]* @global.11 to i16*), align 1 |
| %tmp42 = getelementptr inbounds %struct.blam.2, %struct.blam.2* %arg, i32 0, i32 0 |
| %tmp43 = add i32 %tmp7, %tmp40 |
| %tmp44 = mul i32 %tmp43, 4 |
| %tmp45 = add i32 %tmp44, 2 |
| %tmp46 = call dereferenceable(1) i8* @spam(%struct.baz.1* %tmp42, i32 %tmp45) |
| %tmp47 = load i8, i8* %tmp46, align 1 |
| %tmp48 = zext i8 %tmp47 to i32 |
| %tmp49 = sub i32 %tmp43, 1 |
| %tmp50 = mul i32 %tmp49, 4 |
| %tmp51 = add i32 %tmp50, 2 |
| %tmp52 = call dereferenceable(1) i8* @spam(%struct.baz.1* %tmp42, i32 %tmp51) |
| %tmp53 = load i8, i8* %tmp52, align 1 |
| %tmp54 = zext i8 %tmp53 to i32 |
| %tmp55 = icmp sgt i32 %tmp48, %tmp54 |
| br i1 %tmp55, label %bb56, label %bb60 |
| |
| bb56: ; preds = %bb39 |
| %tmp57 = add nsw i32 %tmp40, -1 |
| br label %bb60 |
| |
| bb58: ; preds = %bb37 |
| %tmp59 = bitcast i16* %tmp33 to i8* |
| call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 getelementptr inbounds ([4 x i8], [4 x i8]* @global.11, i64 0, i64 0), i8* align 2 %tmp59, i64 4, i1 false) |
| br label %bb60 |
| |
| bb60: ; preds = %bb58, %bb56, %bb39 |
| %tmp61 = phi i32 [ %tmp57, %bb56 ], [ %tmp40, %bb39 ], [ %tmp11, %bb58 ] |
| %tmp62 = getelementptr inbounds %struct.blam.2, %struct.blam.2* %arg, i32 0, i32 0 |
| %tmp63 = add i32 %tmp7, 1 |
| %tmp64 = mul i32 %tmp63, 4 |
| %tmp65 = call dereferenceable(1) i8* @spam(%struct.baz.1* %tmp62, i32 %tmp64) |
| br label %bb66 |
| |
| bb66: ; preds = %bb60, %bb35 |
| %tmp67 = phi i8* [ %tmp36, %bb35 ], [ null, %bb60 ] |
| ret i8* %tmp67 |
| } |
| |
| |
| define i32 @loop_with_multiple_euqal_incomings(i32 %N) { |
| ; SCCP-LABEL: @loop_with_multiple_euqal_incomings( |
| ; SCCP-NEXT: entry: |
| ; SCCP-NEXT: br label [[LOOP:%.*]] |
| ; SCCP: loop: |
| ; SCCP-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[P_NEXT:%.*]], [[BB3:%.*]] ], [ 0, [[BB4:%.*]] ], [ 0, [[BB5:%.*]] ], [ 0, [[BB6:%.*]] ] |
| ; SCCP-NEXT: [[C_1:%.*]] = call i1 @cond() |
| ; SCCP-NEXT: br i1 [[C_1]], label [[BB1:%.*]], label [[BB2:%.*]] |
| ; SCCP: bb1: |
| ; SCCP-NEXT: [[C_2:%.*]] = call i1 @cond() |
| ; SCCP-NEXT: br i1 [[C_2]], label [[BB3]], label [[BB4]] |
| ; SCCP: bb2: |
| ; SCCP-NEXT: [[C_4:%.*]] = call i1 @cond() |
| ; SCCP-NEXT: br i1 [[C_4]], label [[BB5]], label [[BB6]] |
| ; SCCP: bb3: |
| ; SCCP-NEXT: [[P_NEXT]] = add i32 [[P]], 1 |
| ; SCCP-NEXT: br label [[LOOP]] |
| ; SCCP: bb4: |
| ; SCCP-NEXT: [[C_3:%.*]] = call i1 @cond() |
| ; SCCP-NEXT: br i1 [[C_3]], label [[LOOP]], label [[END:%.*]] |
| ; SCCP: bb5: |
| ; SCCP-NEXT: br label [[LOOP]] |
| ; SCCP: bb6: |
| ; SCCP-NEXT: br label [[LOOP]] |
| ; SCCP: end: |
| ; SCCP-NEXT: ret i32 [[P]] |
| ; |
| ; IPSCCP-LABEL: @loop_with_multiple_euqal_incomings( |
| ; IPSCCP-NEXT: entry: |
| ; IPSCCP-NEXT: br label [[LOOP:%.*]] |
| ; IPSCCP: loop: |
| ; IPSCCP-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[P_NEXT:%.*]], [[BB3:%.*]] ], [ 0, [[BB4:%.*]] ], [ 0, [[BB5:%.*]] ], [ 0, [[BB6:%.*]] ] |
| ; IPSCCP-NEXT: [[C_1:%.*]] = call i1 @cond() |
| ; IPSCCP-NEXT: br i1 [[C_1]], label [[BB1:%.*]], label [[BB2:%.*]] |
| ; IPSCCP: bb1: |
| ; IPSCCP-NEXT: [[C_2:%.*]] = call i1 @cond() |
| ; IPSCCP-NEXT: br i1 [[C_2]], label [[BB3]], label [[BB4]] |
| ; IPSCCP: bb2: |
| ; IPSCCP-NEXT: [[C_4:%.*]] = call i1 @cond() |
| ; IPSCCP-NEXT: br i1 [[C_4]], label [[BB5]], label [[BB6]] |
| ; IPSCCP: bb3: |
| ; IPSCCP-NEXT: [[P_NEXT]] = add i32 [[P]], 1 |
| ; IPSCCP-NEXT: br label [[LOOP]] |
| ; IPSCCP: bb4: |
| ; IPSCCP-NEXT: [[C_3:%.*]] = call i1 @cond() |
| ; IPSCCP-NEXT: br i1 [[C_3]], label [[LOOP]], label [[END:%.*]] |
| ; IPSCCP: bb5: |
| ; IPSCCP-NEXT: br label [[LOOP]] |
| ; IPSCCP: bb6: |
| ; IPSCCP-NEXT: br label [[LOOP]] |
| ; IPSCCP: end: |
| ; IPSCCP-NEXT: ret i32 [[P]] |
| ; |
| entry: |
| br label %loop |
| |
| loop: |
| %p = phi i32 [ 0, %entry ], [ %p.next, %bb3 ], [ 0, %bb4 ], [ 0, %bb5], [ 0, %bb6 ] |
| %c.1 = call i1 @cond() |
| br i1 %c.1, label %bb1, label %bb2 |
| |
| bb1: |
| %c.2 = call i1 @cond() |
| br i1 %c.2, label %bb3, label %bb4 |
| |
| bb2: |
| %c.4 = call i1 @cond() |
| br i1 %c.4, label %bb5, label %bb6 |
| |
| bb3: |
| %p.next = add i32 %p, 1 |
| br label %loop |
| |
| bb4: |
| %c.3 = call i1 @cond() |
| br i1 %c.3, label %loop, label %end |
| |
| bb5: |
| br label %loop |
| |
| bb6: |
| br label %loop |
| |
| end: |
| ret i32 %p |
| } |