128 lines
6.1 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -S -passes=loop-fusion -loop-fusion-peel-max-count=3 < %s | FileCheck %s
; Tests if we are able to fuse two guarded loops which have constant but
; different trip counts. The first two iterations of the first loop should be
; peeled off, and then the loops should be fused together.
@B = common global [1024 x i32] zeroinitializer, align 16
define void @main(ptr noalias %A) {
; CHECK-LABEL: define void @main(
; CHECK-SAME: ptr noalias [[A:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CMP4:%.*]] = icmp slt i64 0, 45
; CHECK-NEXT: [[CMP31:%.*]] = icmp slt i64 2, 45
; CHECK-NEXT: br i1 [[CMP4]], label %[[FOR_FIRST_ENTRY:.*]], label %[[FOR_END:.*]]
; CHECK: [[FOR_FIRST_ENTRY]]:
; CHECK-NEXT: br label %[[FOR_FIRST_PEEL_BEGIN:.*]]
; CHECK: [[FOR_FIRST_PEEL_BEGIN]]:
; CHECK-NEXT: br label %[[FOR_FIRST_PEEL:.*]]
; CHECK: [[FOR_FIRST_PEEL]]:
; CHECK-NEXT: [[SUB_PEEL:%.*]] = sub nsw i64 0, 3
; CHECK-NEXT: [[ADD_PEEL:%.*]] = add nsw i64 0, 3
; CHECK-NEXT: [[MUL_PEEL:%.*]] = mul nsw i64 [[SUB_PEEL]], [[ADD_PEEL]]
; CHECK-NEXT: [[REM_PEEL:%.*]] = srem i64 [[MUL_PEEL]], 0
; CHECK-NEXT: [[CONV_PEEL:%.*]] = trunc i64 [[REM_PEEL]] to i32
; CHECK-NEXT: [[ARRAYIDX_PEEL:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 0
; CHECK-NEXT: store i32 [[CONV_PEEL]], ptr [[ARRAYIDX_PEEL]], align 4
; CHECK-NEXT: [[INC_PEEL:%.*]] = add nsw i64 0, 1
; CHECK-NEXT: [[CMP_PEEL:%.*]] = icmp slt i64 [[INC_PEEL]], 45
; CHECK-NEXT: br label %[[FOR_FIRST_PEEL_NEXT:.*]]
; CHECK: [[FOR_FIRST_PEEL_NEXT]]:
; CHECK-NEXT: br label %[[FOR_FIRST_PEEL2:.*]]
; CHECK: [[FOR_FIRST_PEEL2]]:
; CHECK-NEXT: [[SUB_PEEL3:%.*]] = sub nsw i64 [[INC_PEEL]], 3
; CHECK-NEXT: [[ADD_PEEL4:%.*]] = add nsw i64 [[INC_PEEL]], 3
; CHECK-NEXT: [[MUL_PEEL5:%.*]] = mul nsw i64 [[SUB_PEEL3]], [[ADD_PEEL4]]
; CHECK-NEXT: [[REM_PEEL6:%.*]] = srem i64 [[MUL_PEEL5]], [[INC_PEEL]]
; CHECK-NEXT: [[CONV_PEEL7:%.*]] = trunc i64 [[REM_PEEL6]] to i32
; CHECK-NEXT: [[ARRAYIDX_PEEL8:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[INC_PEEL]]
; CHECK-NEXT: store i32 [[CONV_PEEL7]], ptr [[ARRAYIDX_PEEL8]], align 4
; CHECK-NEXT: [[INC_PEEL9:%.*]] = add nsw i64 [[INC_PEEL]], 1
; CHECK-NEXT: [[CMP_PEEL10:%.*]] = icmp slt i64 [[INC_PEEL9]], 45
; CHECK-NEXT: br label %[[FOR_FIRST_PEEL_NEXT1:.*]]
; CHECK: [[FOR_FIRST_PEEL_NEXT1]]:
; CHECK-NEXT: br label %[[FOR_FIRST_PEEL_NEXT11:.*]]
; CHECK: [[FOR_FIRST_PEEL_NEXT11]]:
; CHECK-NEXT: br label %[[FOR_FIRST_ENTRY_PEEL_NEWPH:.*]]
; CHECK: [[FOR_FIRST_ENTRY_PEEL_NEWPH]]:
; CHECK-NEXT: br label %[[FOR_FIRST:.*]]
; CHECK: [[FOR_FIRST]]:
; CHECK-NEXT: [[I_05:%.*]] = phi i64 [ [[INC:%.*]], %[[FOR_FIRST]] ], [ [[INC_PEEL9]], %[[FOR_FIRST_ENTRY_PEEL_NEWPH]] ]
; CHECK-NEXT: [[I1_02:%.*]] = phi i64 [ [[INC14:%.*]], %[[FOR_FIRST]] ], [ 2, %[[FOR_FIRST_ENTRY_PEEL_NEWPH]] ]
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[I_05]], 3
; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[I_05]], 3
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i64 [[SUB]], [[ADD]]
; CHECK-NEXT: [[REM:%.*]] = srem i64 [[MUL]], [[I_05]]
; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[REM]] to i32
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[I_05]]
; CHECK-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4
; CHECK-NEXT: [[INC]] = add nsw i64 [[I_05]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INC]], 45
; CHECK-NEXT: [[SUB7:%.*]] = sub nsw i64 [[I1_02]], 3
; CHECK-NEXT: [[ADD8:%.*]] = add nsw i64 [[I1_02]], 3
; CHECK-NEXT: [[MUL9:%.*]] = mul nsw i64 [[SUB7]], [[ADD8]]
; CHECK-NEXT: [[REM10:%.*]] = srem i64 [[MUL9]], [[I1_02]]
; CHECK-NEXT: [[CONV11:%.*]] = trunc i64 [[REM10]] to i32
; CHECK-NEXT: [[ARRAYIDX12:%.*]] = getelementptr inbounds [1024 x i32], ptr @B, i64 0, i64 [[I1_02]]
; CHECK-NEXT: store i32 [[CONV11]], ptr [[ARRAYIDX12]], align 4
; CHECK-NEXT: [[INC14]] = add nsw i64 [[I1_02]], 1
; CHECK-NEXT: [[CMP3:%.*]] = icmp slt i64 [[INC14]], 45
; CHECK-NEXT: br i1 [[CMP3]], label %[[FOR_FIRST]], label %[[FOR_SECOND_EXIT:.*]]
; CHECK: [[FOR_SECOND_EXIT]]:
; CHECK-NEXT: br label %[[FOR_END]]
; CHECK: [[FOR_END]]:
; CHECK-NEXT: ret void
;
entry:
%cmp4 = icmp slt i64 0, 45
br i1 %cmp4, label %for.first.entry, label %for.second.guard
for.first.entry: ; preds = %entry
br label %for.first
for.first: ; preds = %for.first.entry, %for.first
%i.05 = phi i64 [ %inc, %for.first ], [ 0, %for.first.entry ]
%sub = sub nsw i64 %i.05, 3
%add = add nsw i64 %i.05, 3
%mul = mul nsw i64 %sub, %add
%rem = srem i64 %mul, %i.05
%conv = trunc i64 %rem to i32
%arrayidx = getelementptr inbounds i32, ptr %A, i64 %i.05
store i32 %conv, ptr %arrayidx, align 4
%inc = add nsw i64 %i.05, 1
%cmp = icmp slt i64 %inc, 45
br i1 %cmp, label %for.first, label %for.first.exit
for.first.exit: ; preds = %for.first
br label %for.second.guard
for.second.guard: ; preds = %for.first.exit, %entry
%cmp31 = icmp slt i64 2, 45
br i1 %cmp31, label %for.second.entry, label %for.end
for.second.entry: ; preds = %for.second.guard
br label %for.second
for.second: ; preds = %for.second.entry, %for.second
%i1.02 = phi i64 [ %inc14, %for.second ], [ 2, %for.second.entry ]
%sub7 = sub nsw i64 %i1.02, 3
%add8 = add nsw i64 %i1.02, 3
%mul9 = mul nsw i64 %sub7, %add8
%rem10 = srem i64 %mul9, %i1.02
%conv11 = trunc i64 %rem10 to i32
%arrayidx12 = getelementptr inbounds [1024 x i32], ptr @B, i64 0, i64 %i1.02
store i32 %conv11, ptr %arrayidx12, align 4
%inc14 = add nsw i64 %i1.02, 1
%cmp3 = icmp slt i64 %inc14, 45
br i1 %cmp3, label %for.second, label %for.second.exit
for.second.exit: ; preds = %for.second
br label %for.end
for.end: ; preds = %for.second.exit, %for.second.guard
ret void
}