| ; 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 |
| } |
| |