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