mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
1f7f3a6e63
This version contains 2 fixes for reported issues: 1. Make sure we do not try to sink terminator instructions. 2. Make sure we bail out, if we try to sink an instruction that needs to stay in place for another recurrence. Original message: If the recurrence PHI node has a single user, we can sink any instruction without side effects, given that all users are dominated by the instruction computing the incoming value of the next iteration ('Previous'). We can sink instructions that may cause traps, because that only causes the trap to occur later, but not on any new paths. With the relaxed check, we also have to make sure that we do not have a direct cycle (meaning PHI user == 'Previous), which indicates a reduction relation, which potentially gets missed by ReductionDescriptor. As follow-ups, we can also sink stores, iff they do not alias with other instructions we move them across and we could also support sinking chains of instructions and multiple users of the PHI. Fixes PR43398. Reviewers: hsaito, dcaballe, Ayal, rengolin Reviewed By: Ayal Differential Revision: https://reviews.llvm.org/D69228
46 lines
2.2 KiB
LLVM
46 lines
2.2 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN:opt -loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -S %s | FileCheck %s
|
|
|
|
; For %for.1, we are fine initially, because the previous value %for.1.next dominates the
|
|
; user of %for.1. But for %for.2, we have to sink the user (%for.1.next) past the previous
|
|
; value %for.2.next. This however breaks the condition we have for %for.1. We cannot fix
|
|
; both first order recurrences and cannot vectorize the loop.
|
|
define i32 @c(i32 %N) {
|
|
; CHECK-LABEL: @c(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
|
; CHECK: for.body:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 10, [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[FOR_1:%.*]] = phi i32 [ [[FOR_1_NEXT:%.*]], [[FOR_BODY]] ], [ 20, [[ENTRY]] ]
|
|
; CHECK-NEXT: [[FOR_2:%.*]] = phi i32 [ [[FOR_2_NEXT:%.*]], [[FOR_BODY]] ], [ 11, [[ENTRY]] ]
|
|
; CHECK-NEXT: [[FOR_1_NEXT]] = add nsw i32 [[FOR_2]], 1
|
|
; CHECK-NEXT: [[FOR_2_NEXT]] = shl i32 [[FOR_1]], 24
|
|
; CHECK-NEXT: [[INC]] = add nsw i32 [[IV]], 1
|
|
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N:%.*]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND1_FOR_END_CRIT_EDGE:%.*]], label [[FOR_BODY]]
|
|
; CHECK: for.cond1.for.end_crit_edge:
|
|
; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[FOR_1_NEXT]], [[FOR_BODY]] ]
|
|
; CHECK-NEXT: [[SEXT_LCSSA:%.*]] = phi i32 [ [[FOR_2_NEXT]], [[FOR_BODY]] ]
|
|
; CHECK-NEXT: [[RES:%.*]] = add i32 [[ADD_LCSSA]], [[SEXT_LCSSA]]
|
|
; CHECK-NEXT: ret i32 [[RES]]
|
|
;
|
|
entry:
|
|
br label %for.body
|
|
|
|
for.body: ; preds = %for.body.preheader, %for.body
|
|
%iv = phi i32 [ %inc, %for.body ], [ 10, %entry ]
|
|
%for.1 = phi i32 [ %for.1.next, %for.body ], [ 20, %entry ]
|
|
%for.2 = phi i32 [ %for.2.next, %for.body ], [ 11, %entry ]
|
|
%for.1.next = add nsw i32 %for.2, 1
|
|
%for.2.next = shl i32 %for.1, 24
|
|
%inc = add nsw i32 %iv, 1
|
|
%exitcond = icmp eq i32 %inc, %N
|
|
br i1 %exitcond, label %for.cond1.for.end_crit_edge, label %for.body
|
|
|
|
for.cond1.for.end_crit_edge: ; preds = %for.body
|
|
%add.lcssa = phi i32 [ %for.1.next, %for.body ]
|
|
%sext.lcssa = phi i32 [ %for.2.next, %for.body ]
|
|
%res = add i32 %add.lcssa, %sext.lcssa
|
|
ret i32 %res
|
|
}
|