This option was added in D89854. It prevents GVN from performing load PRE in a loop, if doing so would require critical edge splitting on the backedge. From the review: > I know that GVN Load PRE negatively impacts peeling, > loop predication, so the passes expecting that latch has > a conditional branch. In the PhaseOrdering test in this patch, splitting the backedge negatively affects vectorization: After critical edge splitting, the loop gets rotated, effectively peeling off the first loop iteration. The effect is that the first element is handled separately, then the bulk of the elements use a vectorized reduction (but using unaligned, off-by-one memory accesses) and then a tail of 15 elements is handled separately again. It's probably worth noting that the loop load PRE from D99926 is not affected by this change (as it does not need backedge splitting). This is about normal load PRE that happens to occur inside a loop. Differential Revision: https://reviews.llvm.org/D126382
1039 lines
47 KiB
LLVM
1039 lines
47 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -passes='require<domtree>,loop(loop-simplifycfg),gvn' -enable-split-backedge-in-load-pre -S %s | FileCheck %s
|
|
|
|
define i32 @test_pointer_phi_select_same_object(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_same_object(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: [[L_2_PRE:%.*]] = load i32, i32* [[PTR]], align 4
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_same_object_lcssa(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_same_object_lcssa(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: [[L_2_PRE:%.*]] = load i32, i32* [[PTR]], align 4
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%lcssa.min = phi i32* [ %min.select, %loop ]
|
|
%res = load i32, i32* %lcssa.min, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_different_objects(i32* %A, i32 *%B, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_different_objects(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[L_2_PRE:%.*]] = load i32, i32* [[B:%.*]], align 4
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[A:%.*]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[B]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %A, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %B, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_same_object_multiple_loads_1(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_same_object_multiple_loads_1(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: [[L_2_PRE:%.*]] = load i32, i32* [[PTR]], align 4
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%l.3 = load i32, i32* %min.ptr, align 4
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_same_object_multiple_loads_2(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_same_object_multiple_loads_2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: [[L_2_PRE:%.*]] = load i32, i32* [[PTR]], align 4
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%l.3 = load i32, i32* %ptr.iv, align 4
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_load_after(i32* %A, i32 *%B, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_load_after(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[L_2_PRE:%.*]] = load i32, i32* [[B:%.*]], align 4
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[L_3:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[A:%.*]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[B]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[L_3]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i32 [[L_3]]
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret i32 [[L_3]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %A, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %B, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%l.3 = load i32, i32* %min.select, align 4
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i32 %l.3
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_same_object_split_edge(i32* %ptr, i32* %end, i1 %c) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_same_object_split_edge(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
|
|
; CHECK: loop.preheader:
|
|
; CHECK-NEXT: [[L_2_PRE:%.*]] = load i32, i32* [[PTR]], align 4
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[L_2:%.*]] = phi i32 [ [[TMP0:%.*]], [[LOOP]] ], [ [[L_2_PRE]], [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ], [ [[START_PTR]], [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[MIN_SELECT:%.*]], [[LOOP]] ], [ [[PTR]], [[LOOP_PREHEADER]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[LOOP_EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: loop.exit:
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[LCSSA_PHI_2:%.*]] = phi i32* [ [[END]], [[ENTRY:%.*]] ], [ [[MIN_SELECT]], [[LOOP_EXIT]] ]
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[LCSSA_PHI_2]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br i1 %c, label %exit, label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %loop.exit, label %loop
|
|
|
|
loop.exit:
|
|
%lcssa.phi.1 = phi i32* [ %min.select, %loop ]
|
|
br label %exit
|
|
|
|
exit:
|
|
%lcssa.phi.2 = phi i32* [ %end, %entry ], [ %lcssa.phi.1, %loop.exit ]
|
|
%res = load i32, i32* %lcssa.phi.2, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
|
|
declare void @may_throw() readonly
|
|
|
|
define i32 @test_pointer_phi_select_load_may_not_execute_1(i32* %A, i32 *%B, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_load_may_not_execute_1(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[A:%.*]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[B:%.*]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: call void @may_throw()
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[L_2:%.*]] = load i32, i32* [[MIN_PTR]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %A, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %B, %entry ], [ %min.select, %loop ]
|
|
call void @may_throw()
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_load_may_not_execute_2(i32* %A, i32 *%B, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_load_may_not_execute_2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[A:%.*]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[B:%.*]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: call void @may_throw()
|
|
; CHECK-NEXT: [[L_2:%.*]] = load i32, i32* [[MIN_PTR]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %A, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %B, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
call void @may_throw()
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_same_object_store_1(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_same_object_store_1(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: store i32 3, i32* [[MIN_PTR]], align 4
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], 3
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
store i32 3, i32* %min.ptr
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_same_object_store_2(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_same_object_store_2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[L_2:%.*]] = load i32, i32* [[MIN_PTR]], align 4
|
|
; CHECK-NEXT: store i32 3, i32* [[MIN_PTR]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
store i32 3, i32* %min.ptr
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_same_object_store_3(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_same_object_store_3(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[L_2:%.*]] = load i32, i32* [[MIN_PTR]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: store i32 3, i32* [[MIN_PTR]], align 4
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
store i32 3, i32* %min.ptr
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
declare void @may_write()
|
|
|
|
define i32 @test_pointer_phi_select_same_object_may_write_call_1(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_same_object_may_write_call_1(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: call void @may_write()
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[L_2:%.*]] = load i32, i32* [[MIN_PTR]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
call void @may_write()
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_same_object_may_write_call_2(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_same_object_may_write_call_2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[L_2:%.*]] = load i32, i32* [[MIN_PTR]], align 4
|
|
; CHECK-NEXT: call void @may_write()
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
call void @may_write()
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_same_object_may_write_call_3(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_same_object_may_write_call_3(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[L_2:%.*]] = load i32, i32* [[MIN_PTR]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: call void @may_write()
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
call void @may_write()
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_same_object_header_exit(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_same_object_header_exit(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
|
|
; CHECK: loop.header:
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP_LATCH]] ]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
|
|
; CHECK: loop.latch:
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[L_2:%.*]] = load i32, i32* [[MIN_PTR]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: br label [[LOOP_HEADER]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_PTR]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop.header
|
|
|
|
loop.header:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop.latch ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop.latch ]
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop.latch
|
|
|
|
loop.latch:
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
br label %loop.header
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.ptr, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_same_object_ptr_use_cycle(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_same_object_ptr_use_cycle(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: [[L_2_PRE:%.*]] = load i32, i32* [[PTR]], align 4
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT_PREHEADER:%.*]], label [[LOOP]]
|
|
; CHECK: exit.preheader:
|
|
; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[P:%.*]] = phi i32* [ [[P_NEXT:%.*]], [[EXIT]] ], [ [[MIN_SELECT]], [[EXIT_PREHEADER]] ]
|
|
; CHECK-NEXT: store i32 0, i32* [[P]], align 4
|
|
; CHECK-NEXT: [[P_NEXT]] = getelementptr inbounds i32, i32* [[P]], i64 1
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%p = phi i32* [ %min.select, %loop ], [ %p.next, %exit ]
|
|
store i32 0, i32* %p
|
|
%p.next = getelementptr inbounds i32, i32* %p, i64 1
|
|
br label %exit
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_same_object_maybe_clobbered_in_exit(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_same_object_maybe_clobbered_in_exit(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: [[L_2_PRE:%.*]] = load i32, i32* [[PTR]], align 4
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: store i32 0, i32* [[START_PTR]], align 4
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
store i32 0, i32* %start.ptr
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_same_object_maybe_clobbered_in_exit_2(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_same_object_maybe_clobbered_in_exit_2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: [[L_2_PRE:%.*]] = load i32, i32* [[PTR]], align 4
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT_1:%.*]], label [[LOOP]]
|
|
; CHECK: exit.1:
|
|
; CHECK-NEXT: store i32 0, i32* [[START_PTR]], align 4
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit.1, label %loop
|
|
|
|
exit.1:
|
|
%lcssa.min = phi i32* [ %min.select, %loop ]
|
|
store i32 0, i32* %start.ptr
|
|
br label %exit.2
|
|
|
|
exit.2:
|
|
%res = load i32, i32* %lcssa.min, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
declare i32 @__CxxFrameHandler3(...)
|
|
|
|
define i32 @test_pointer_phi_select_same_object_invoke_in_chain(i32* %ptr, i32* %end) personality i32 (...)* @__CxxFrameHandler3 {
|
|
; CHECK-LABEL: @test_pointer_phi_select_same_object_invoke_in_chain(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: [[L_2_PRE:%.*]] = load i32, i32* [[PTR]], align 4
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT_1:%.*]], label [[LOOP]]
|
|
; CHECK: exit.1:
|
|
; CHECK-NEXT: store i32 0, i32* [[START_PTR]], align 4
|
|
; CHECK-NEXT: invoke void @may_throw()
|
|
; CHECK-NEXT: to label [[EXIT_2:%.*]] unwind label [[CATCH_OBJECT:%.*]]
|
|
; CHECK: exit.2:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
; CHECK: catch.object:
|
|
; CHECK-NEXT: [[LP:%.*]] = landingpad { i8*, i32 }
|
|
; CHECK-NEXT: catch i8* null
|
|
; CHECK-NEXT: unreachable
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit.1, label %loop
|
|
|
|
exit.1:
|
|
%lcssa.min = phi i32* [ %min.select, %loop ]
|
|
store i32 0, i32* %start.ptr
|
|
invoke void @may_throw()
|
|
to label %exit.2 unwind label %catch.object
|
|
|
|
exit.2:
|
|
%res = load i32, i32* %lcssa.min, align 4
|
|
ret i32 %res
|
|
|
|
catch.object:
|
|
%lp = landingpad { i8*, i32 }
|
|
catch i8* null
|
|
unreachable
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_used_by_others_in_loop(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_used_by_others_in_loop(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: [[L_2_PRE:%.*]] = load i32, i32* [[PTR]], align 4
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[L_3:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[L_3]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i32 [[L_3]]
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret i32 [[L_3]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%l.3 = load i32, i32* %min.select, align 4
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i32 %l.3
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_used_by_others_in_loop_1(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_used_by_others_in_loop_1(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: [[L_2_PRE:%.*]] = load i32, i32* [[PTR]], align 4
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[L_3:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[L_3_PRE:%.*]], [[LOOP_LOOP_CRIT_EDGE:%.*]] ]
|
|
; CHECK-NEXT: [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY]] ], [ [[TMP0:%.*]], [[LOOP_LOOP_CRIT_EDGE]] ]
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LOOP_CRIT_EDGE]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP_LOOP_CRIT_EDGE]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i32 [[L_3]]
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP_LOOP_CRIT_EDGE]]
|
|
; CHECK: loop.loop_crit_edge:
|
|
; CHECK-NEXT: [[L_3_PRE]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: br label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%l.3 = load i32, i32* %min.ptr, align 4
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i32 %l.3
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_used_by_others_in_loop_2(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_used_by_others_in_loop_2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: [[L_2_PRE:%.*]] = load i32, i32* [[PTR]], align 4
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[L_2:%.*]] = phi i32 [ [[L_2_PRE]], [[ENTRY:%.*]] ], [ [[TMP0:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_1:%.*]] = load i32, i32* [[PTR_IV]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 [[L_1]], [[L_2]]
|
|
; CHECK-NEXT: [[TMP0]] = select i1 [[CMP_I_I_I]], i32 [[L_1]], i32 [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[GEP_MIN_PTR:%.*]] = getelementptr inbounds i32, i32* [[MIN_PTR]], i32 1
|
|
; CHECK-NEXT: [[L_3:%.*]] = load i32, i32* [[GEP_MIN_PTR]], align 4
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i32 [[L_3]]
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
%l.1 = load i32, i32* %ptr.iv, align 4
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 %l.1, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%gep.min.ptr = getelementptr inbounds i32, i32* %min.ptr, i32 1
|
|
%l.3 = load i32, i32* %gep.min.ptr, align 4
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i32 %l.3
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|
|
|
|
define i32 @test_pointer_phi_select_no_iter_load(i32* %ptr, i32* %end) {
|
|
; CHECK-LABEL: @test_pointer_phi_select_no_iter_load(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[START_PTR:%.*]] = getelementptr inbounds i32, i32* [[PTR:%.*]], i64 1
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[PTR_IV:%.*]] = phi i32* [ [[START_PTR]], [[ENTRY:%.*]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[MIN_PTR:%.*]] = phi i32* [ [[PTR]], [[ENTRY]] ], [ [[MIN_SELECT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: [[L_2:%.*]] = load i32, i32* [[MIN_PTR]], align 4
|
|
; CHECK-NEXT: [[CMP_I_I_I:%.*]] = icmp ult i32 10, [[L_2]]
|
|
; CHECK-NEXT: [[MIN_SELECT]] = select i1 [[CMP_I_I_I]], i32* [[PTR_IV]], i32* [[MIN_PTR]]
|
|
; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, i32* [[PTR_IV]], i64 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp eq i32* [[PTR_IV_NEXT]], [[END:%.*]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[RES:%.*]] = load i32, i32* [[MIN_SELECT]], align 4
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
%start.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%ptr.iv = phi i32* [ %start.ptr, %entry ], [ %ptr.iv.next, %loop ]
|
|
%min.ptr = phi i32* [ %ptr, %entry ], [ %min.select, %loop ]
|
|
%l.2 = load i32, i32* %min.ptr, align 4
|
|
%cmp.i.i.i = icmp ult i32 10, %l.2
|
|
%min.select = select i1 %cmp.i.i.i, i32* %ptr.iv, i32* %min.ptr
|
|
%ptr.iv.next = getelementptr inbounds i32, i32* %ptr.iv, i64 1
|
|
%ec = icmp eq i32* %ptr.iv.next, %end
|
|
br i1 %ec, label %exit, label %loop
|
|
|
|
exit:
|
|
%res = load i32, i32* %min.select, align 4
|
|
ret i32 %res
|
|
}
|