blob: edb84039085375c3ab80f0d5c6120b8d5df68176 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -passes=loop-interchange -loop-interchange-profitabilities=ignore -S | FileCheck %s
; red = 0;
; for (i = 0; i < 2; i++)
; for (j = 0; j < 2; j++)
; red = A[j][i] == 0 ? i + 1 : red;
;
; These loops must not be interchanged, because the reduction operation is not
; associative. For example, consider `A` is as follows:
;
; A = {{1, 0}, {0, 1}};
;
; In the original code, the final value of `red` is 2, but if the loops are
; interchanged, the final value of `red` becomes 1.
;
define i8 @reduce_anyof(ptr %A) {
; CHECK-LABEL: define i8 @reduce_anyof(
; CHECK-SAME: ptr [[A:%.*]]) {
; CHECK-NEXT: [[FOR_I_HEADER_PREHEADER1:.*]]:
; CHECK-NEXT: br label %[[FOR_I_HEADER1:.*]]
; CHECK: [[FOR_I_HEADER1]]:
; CHECK-NEXT: [[I:%.*]] = phi i64 [ 0, %[[FOR_I_HEADER_PREHEADER1]] ], [ [[I_INC:%.*]], %[[FOR_I_LATCH:.*]] ]
; CHECK-NEXT: [[RED_OUTER:%.*]] = phi i8 [ 0, %[[FOR_I_HEADER_PREHEADER1]] ], [ [[RED_LCSSA:%.*]], %[[FOR_I_LATCH]] ]
; CHECK-NEXT: [[ADD:%.*]] = add i64 [[I]], 1
; CHECK-NEXT: [[ADD8:%.*]] = trunc i64 [[ADD]] to i8
; CHECK-NEXT: br label %[[FOR_J_SPLIT1:.*]]
; CHECK: [[FOR_J_SPLIT1]]:
; CHECK-NEXT: [[J:%.*]] = phi i64 [ 0, %[[FOR_I_HEADER1]] ], [ [[TMP2:%.*]], %[[FOR_J_SPLIT1]] ]
; CHECK-NEXT: [[RED:%.*]] = phi i8 [ [[RED_OUTER]], %[[FOR_I_HEADER1]] ], [ [[SEL:%.*]], %[[FOR_J_SPLIT1]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i8], ptr [[A]], i64 [[J]], i64 [[I]]
; CHECK-NEXT: [[LV:%.*]] = load i8, ptr [[ARRAYIDX]], align 4
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[LV]], 0
; CHECK-NEXT: [[SEL]] = select i1 [[CMP]], i8 [[ADD8]], i8 [[RED]]
; CHECK-NEXT: [[TMP2]] = add i64 [[J]], 1
; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[TMP2]], 2
; CHECK-NEXT: br i1 [[TMP3]], label %[[FOR_I_LATCH]], label %[[FOR_J_SPLIT1]]
; CHECK: [[FOR_I_LATCH]]:
; CHECK-NEXT: [[RED_LCSSA]] = phi i8 [ [[SEL]], %[[FOR_J_SPLIT1]] ]
; CHECK-NEXT: [[I_INC]] = add i64 [[I]], 1
; CHECK-NEXT: [[EC_I:%.*]] = icmp eq i64 [[I_INC]], 2
; CHECK-NEXT: br i1 [[EC_I]], label %[[FOR_J_SPLIT2:.*]], label %[[FOR_I_HEADER1]]
; CHECK: [[FOR_J_SPLIT2]]:
; CHECK-NEXT: [[RES:%.*]] = phi i8 [ [[RED_LCSSA]], %[[FOR_I_LATCH]] ]
; CHECK-NEXT: ret i8 [[RES]]
;
entry:
br label %for.i.header
for.i.header:
%i = phi i64 [ 0, %entry ], [ %i.inc, %for.i.latch ]
%red.outer = phi i8 [ 0, %entry ], [ %red.lcssa, %for.i.latch ]
%add = add i64 %i, 1
%add8 = trunc i64 %add to i8
br label %for.j
for.j:
%j = phi i64 [ 0, %for.i.header ], [ %j.inc, %for.j ]
%red = phi i8 [ %red.outer, %for.i.header ], [ %sel, %for.j ]
%arrayidx = getelementptr inbounds [2 x i8], ptr %A, i64 %j, i64 %i
%lv = load i8, ptr %arrayidx, align 4
%cmp = icmp eq i8 %lv, 0
%sel = select i1 %cmp, i8 %add8, i8 %red
%j.inc = add i64 %j, 1
%ec.j = icmp eq i64 %j.inc, 2
br i1 %ec.j, label %for.i.latch, label %for.j
for.i.latch:
%red.lcssa = phi i8 [ %sel, %for.j ]
%i.inc = add i64 %i, 1
%ec.i = icmp eq i64 %i.inc, 2
br i1 %ec.i, label %exit, label %for.i.header
exit:
%res = phi i8 [ %red.lcssa, %for.i.latch ]
ret i8 %res
}