| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 |
| ; RUN: opt -passes=simplifycfg -S < %s | FileCheck %s |
| |
| ; Allow jump-threading when values defined in the block are live outside of the block |
| ; to those destinations in which the values are dead. |
| |
| define void @testA(ptr %ptrA, ptr %ptrB, i64 %a, i64 %b) { |
| ; CHECK-LABEL: define void @testA( |
| ; CHECK-SAME: ptr [[PTRA:%.*]], ptr [[PTRB:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) { |
| ; CHECK-NEXT: [[MAINA:.*:]] |
| ; CHECK-NEXT: [[COND:%.*]] = icmp slt i64 [[A]], [[B]] |
| ; CHECK-NEXT: br i1 [[COND]], label %[[IFA:.*]], label %[[MAINC:.*]] |
| ; CHECK: [[IFA]]: |
| ; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[PTRA]], align 4 |
| ; CHECK-NEXT: store i64 [[TMP0]], ptr [[PTRB]], align 4 |
| ; CHECK-NEXT: br label %[[MAINC]] |
| ; CHECK: [[MAINC]]: |
| ; CHECK-NEXT: ret void |
| ; |
| mainA: |
| %cond = icmp slt i64 %a, %b |
| br i1 %cond, label %ifA, label %mainB |
| |
| ifA: |
| %518 = load i64, ptr %ptrA |
| br label %mainB |
| |
| ; %value is live outside of block mainB, but jump-threading |
| ; can still occur to destination mainC, since %value is dead there. |
| ; Subsequent CFG simplifications will create one if block. |
| mainB: |
| %value = phi i64 [ %518, %ifA ], [ zeroinitializer, %mainA ] |
| br i1 %cond, label %ifB, label %mainC |
| |
| ifB: |
| store i64 %value, ptr %ptrB |
| br label %mainC |
| |
| mainC: |
| ret void |
| } |
| |
| |
| define void @testB(ptr %ptrA, ptr %ptrB, i64 %a, i64 %b, i64 %c) { |
| ; CHECK-LABEL: define void @testB( |
| ; CHECK-SAME: ptr [[PTRA:%.*]], ptr [[PTRB:%.*]], i64 [[A:%.*]], i64 [[B:%.*]], i64 [[C:%.*]]) { |
| ; CHECK-NEXT: [[MAINA:.*:]] |
| ; CHECK-NEXT: [[COND:%.*]] = icmp slt i64 [[A]], [[B]] |
| ; CHECK-NEXT: br i1 [[COND]], label %[[IFA:.*]], label %[[MAINC:.*]] |
| ; CHECK: [[IFA]]: |
| ; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[PTRA]], align 4 |
| ; CHECK-NEXT: [[COND2:%.*]] = icmp slt i64 [[A]], [[C]] |
| ; CHECK-NEXT: [[PTR_ARM1:%.*]] = getelementptr i64, ptr [[PTRB]], i64 8 |
| ; CHECK-NEXT: [[PTR_ARM2:%.*]] = getelementptr i64, ptr [[PTRB]], i64 16 |
| ; CHECK-NEXT: [[PTRC:%.*]] = select i1 [[COND2]], ptr [[PTR_ARM1]], ptr [[PTR_ARM2]] |
| ; CHECK-NEXT: store i64 [[TMP0]], ptr [[PTRC]], align 4 |
| ; CHECK-NEXT: br label %[[MAINC]] |
| ; CHECK: [[MAINC]]: |
| ; CHECK-NEXT: ret void |
| ; |
| mainA: |
| %cond = icmp slt i64 %a, %b |
| br i1 %cond, label %ifA, label %mainB |
| |
| ifA: |
| %518 = load i64, ptr %ptrA |
| br label %mainB |
| |
| ; Use of %value is not in either immediate destination of mainB. |
| mainB: |
| %value = phi i64 [ %518, %ifA ], [ zeroinitializer, %mainA ] |
| br i1 %cond, label %ifB, label %mainC |
| |
| ifB: |
| %cond2 = icmp slt i64 %a, %c |
| br i1 %cond2, label %ifB_arm1, label %ifB_arm2 |
| |
| ifB_arm1: |
| %ptr_arm1 = getelementptr i64, ptr %ptrB, i64 8 |
| br label %ifB_join |
| |
| ifB_arm2: |
| %ptr_arm2 = getelementptr i64, ptr %ptrB, i64 16 |
| br label %ifB_join |
| |
| ifB_join: |
| %ptrC = phi ptr [ %ptr_arm1, %ifB_arm1 ], [ %ptr_arm2, %ifB_arm2 ] |
| store i64 %value, ptr %ptrC |
| br label %mainC |
| |
| mainC: |
| ret void |
| } |
| |
| |
| ; Jump-threading is not done since %value is live in both destinations. |
| define void @testA_negative(ptr %ptrA, ptr %ptrB, ptr %ptrD, i64 %a, i64 %b) { |
| ; CHECK-LABEL: define void @testA_negative( |
| ; CHECK-SAME: ptr [[PTRA:%.*]], ptr [[PTRB:%.*]], ptr [[PTRD:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) { |
| ; CHECK-NEXT: [[MAINA:.*]]: |
| ; CHECK-NEXT: [[COND:%.*]] = icmp slt i64 [[A]], [[B]] |
| ; CHECK-NEXT: br i1 [[COND]], label %[[IFA:.*]], label %[[MAINB:.*]] |
| ; CHECK: [[IFA]]: |
| ; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[PTRA]], align 4 |
| ; CHECK-NEXT: br label %[[MAINB]] |
| ; CHECK: [[MAINB]]: |
| ; CHECK-NEXT: [[VALUE:%.*]] = phi i64 [ [[TMP0]], %[[IFA]] ], [ 0, %[[MAINA]] ] |
| ; CHECK-NEXT: br i1 [[COND]], label %[[IFB:.*]], label %[[MAINC:.*]] |
| ; CHECK: [[IFB]]: |
| ; CHECK-NEXT: store i64 [[VALUE]], ptr [[PTRB]], align 4 |
| ; CHECK-NEXT: br label %[[MAINC]] |
| ; CHECK: [[MAINC]]: |
| ; CHECK-NEXT: store i64 [[VALUE]], ptr [[PTRD]], align 4 |
| ; CHECK-NEXT: ret void |
| ; |
| mainA: |
| %cond = icmp slt i64 %a, %b |
| br i1 %cond, label %ifA, label %mainB |
| |
| ifA: |
| %518 = load i64, ptr %ptrA |
| br label %mainB |
| |
| mainB: |
| %value = phi i64 [ %518, %ifA ], [ zeroinitializer, %mainA ] |
| br i1 %cond, label %ifB, label %mainC |
| |
| ifB: |
| store i64 %value, ptr %ptrB |
| br label %mainC |
| |
| mainC: |
| store i64 %value, ptr %ptrD |
| ret void |
| } |
| |
| |
| ; Jump-threading is not done since %value is live in both destinations. |
| define void @testB_negative(ptr %ptrA, ptr %ptrB, ptr %ptrD, i64 %a, i64 %b, i64 %c) { |
| ; CHECK-LABEL: define void @testB_negative( |
| ; CHECK-SAME: ptr [[PTRA:%.*]], ptr [[PTRB:%.*]], ptr [[PTRD:%.*]], i64 [[A:%.*]], i64 [[B:%.*]], i64 [[C:%.*]]) { |
| ; CHECK-NEXT: [[MAINA:.*]]: |
| ; CHECK-NEXT: [[COND:%.*]] = icmp slt i64 [[A]], [[B]] |
| ; CHECK-NEXT: br i1 [[COND]], label %[[IFA:.*]], label %[[MAINB:.*]] |
| ; CHECK: [[IFA]]: |
| ; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[PTRA]], align 4 |
| ; CHECK-NEXT: br label %[[MAINB]] |
| ; CHECK: [[MAINB]]: |
| ; CHECK-NEXT: [[VALUE:%.*]] = phi i64 [ [[TMP0]], %[[IFA]] ], [ 0, %[[MAINA]] ] |
| ; CHECK-NEXT: br i1 [[COND]], label %[[IFB:.*]], label %[[MAINC:.*]] |
| ; CHECK: [[IFB]]: |
| ; CHECK-NEXT: [[COND2:%.*]] = icmp slt i64 [[A]], [[C]] |
| ; CHECK-NEXT: [[PTR_ARM1:%.*]] = getelementptr i64, ptr [[PTRB]], i64 8 |
| ; CHECK-NEXT: [[PTR_ARM2:%.*]] = getelementptr i64, ptr [[PTRB]], i64 16 |
| ; CHECK-NEXT: [[PTRC:%.*]] = select i1 [[COND2]], ptr [[PTR_ARM1]], ptr [[PTR_ARM2]] |
| ; CHECK-NEXT: store i64 [[VALUE]], ptr [[PTRC]], align 4 |
| ; CHECK-NEXT: br label %[[MAINC]] |
| ; CHECK: [[MAINC]]: |
| ; CHECK-NEXT: store i64 [[VALUE]], ptr [[PTRD]], align 4 |
| ; CHECK-NEXT: ret void |
| ; |
| mainA: |
| %cond = icmp slt i64 %a, %b |
| br i1 %cond, label %ifA, label %mainB |
| |
| ifA: |
| %518 = load i64, ptr %ptrA |
| br label %mainB |
| |
| mainB: |
| %value = phi i64 [ %518, %ifA ], [ zeroinitializer, %mainA ] |
| br i1 %cond, label %ifB, label %mainC |
| |
| ifB: |
| %cond2 = icmp slt i64 %a, %c |
| br i1 %cond2, label %ifB_arm1, label %ifB_arm2 |
| |
| ifB_arm1: |
| %ptr_arm1 = getelementptr i64, ptr %ptrB, i64 8 |
| br label %ifB_join |
| |
| ifB_arm2: |
| %ptr_arm2 = getelementptr i64, ptr %ptrB, i64 16 |
| br label %ifB_join |
| |
| ifB_join: |
| %ptrC = phi ptr [ %ptr_arm1, %ifB_arm1 ], [ %ptr_arm2, %ifB_arm2 ] |
| store i64 %value, ptr %ptrC |
| br label %mainC |
| |
| mainC: |
| store i64 %value, ptr %ptrD |
| ret void |
| } |
| |