
Extend jump-threading to allow local defs that are live outside of the threaded block. Allow threading to destinations where the local defs are not live. --------- Signed-off-by: John Lu <John.Lu@amd.com>
196 lines
6.2 KiB
LLVM
196 lines
6.2 KiB
LLVM
; 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
|
|
}
|
|
|