1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=loop-unroll %s | FileCheck %s 3 4; In both cases, we have one unpredictable exit and one IV-based exit with 5; known trip count. We can fully unroll against the latter. In one of the 6; examples the IV-based exit is the latch exit, in the other the non-latch 7; exit. After full unrolling, the functions fold to ret i1 true. 8 9define i1 @test_latch() { 10; CHECK-LABEL: @test_latch( 11; CHECK-NEXT: start: 12; CHECK-NEXT: [[A1:%.*]] = alloca [2 x i64], align 8 13; CHECK-NEXT: [[A2:%.*]] = alloca [2 x i64], align 8 14; CHECK-NEXT: store i64 -5015437470765251660, ptr [[A1]], align 8 15; CHECK-NEXT: [[A1_1:%.*]] = getelementptr inbounds [2 x i64], ptr [[A1]], i64 0, i64 1 16; CHECK-NEXT: store i64 -8661621401413125213, ptr [[A1_1]], align 8 17; CHECK-NEXT: store i64 -5015437470765251660, ptr [[A2]], align 8 18; CHECK-NEXT: [[A2_1:%.*]] = getelementptr inbounds [2 x i64], ptr [[A2]], i64 0, i64 1 19; CHECK-NEXT: store i64 -8661621401413125213, ptr [[A2_1]], align 8 20; CHECK-NEXT: br label [[LOOP:%.*]] 21; CHECK: loop: 22; CHECK-NEXT: [[LOAD1:%.*]] = load i64, ptr [[A1]], align 8 23; CHECK-NEXT: [[LOAD2:%.*]] = load i64, ptr [[A2]], align 8 24; CHECK-NEXT: [[EXITCOND2:%.*]] = icmp eq i64 [[LOAD1]], [[LOAD2]] 25; CHECK-NEXT: br i1 [[EXITCOND2]], label [[LATCH:%.*]], label [[EXIT:%.*]] 26; CHECK: latch: 27; CHECK-NEXT: [[GEP1_1:%.*]] = getelementptr inbounds [2 x i64], ptr [[A1]], i64 0, i64 1 28; CHECK-NEXT: [[GEP2_1:%.*]] = getelementptr inbounds [2 x i64], ptr [[A2]], i64 0, i64 1 29; CHECK-NEXT: [[LOAD1_1:%.*]] = load i64, ptr [[GEP1_1]], align 8 30; CHECK-NEXT: [[LOAD2_1:%.*]] = load i64, ptr [[GEP2_1]], align 8 31; CHECK-NEXT: [[EXITCOND2_1:%.*]] = icmp eq i64 [[LOAD1_1]], [[LOAD2_1]] 32; CHECK-NEXT: br i1 [[EXITCOND2_1]], label [[LATCH_1:%.*]], label [[EXIT]] 33; CHECK: latch.1: 34; CHECK-NEXT: br label [[EXIT]] 35; CHECK: exit: 36; CHECK-NEXT: [[EXIT_VAL:%.*]] = phi i1 [ false, [[LOOP]] ], [ false, [[LATCH]] ], [ true, [[LATCH_1]] ] 37; CHECK-NEXT: ret i1 [[EXIT_VAL]] 38; 39start: 40 %a1 = alloca [2 x i64], align 8 41 %a2 = alloca [2 x i64], align 8 42 store i64 -5015437470765251660, ptr %a1, align 8 43 %a1.1 = getelementptr inbounds [2 x i64], ptr %a1, i64 0, i64 1 44 store i64 -8661621401413125213, ptr %a1.1, align 8 45 store i64 -5015437470765251660, ptr %a2, align 8 46 %a2.1 = getelementptr inbounds [2 x i64], ptr %a2, i64 0, i64 1 47 store i64 -8661621401413125213, ptr %a2.1, align 8 48 br label %loop 49 50loop: 51 %iv = phi i64 [ 0, %start ], [ %iv.next, %latch ] 52 %gep1 = getelementptr inbounds [2 x i64], ptr %a1, i64 0, i64 %iv 53 %gep2 = getelementptr inbounds [2 x i64], ptr %a2, i64 0, i64 %iv 54 %load1 = load i64, ptr %gep1, align 8 55 %load2 = load i64, ptr %gep2, align 8 56 %exitcond2 = icmp eq i64 %load1, %load2 57 br i1 %exitcond2, label %latch, label %exit 58 59latch: 60 %iv.next = add nuw nsw i64 %iv, 1 61 %exitcond = icmp eq i64 %iv.next, 2 62 br i1 %exitcond, label %exit, label %loop 63 64exit: 65 %exit.val = phi i1 [ true, %latch ], [ false, %loop ] 66 ret i1 %exit.val 67} 68 69define i1 @test_non_latch() { 70; CHECK-LABEL: @test_non_latch( 71; CHECK-NEXT: start: 72; CHECK-NEXT: [[A1:%.*]] = alloca [2 x i64], align 8 73; CHECK-NEXT: [[A2:%.*]] = alloca [2 x i64], align 8 74; CHECK-NEXT: store i64 -5015437470765251660, ptr [[A1]], align 8 75; CHECK-NEXT: [[A1_1:%.*]] = getelementptr inbounds [2 x i64], ptr [[A1]], i64 0, i64 1 76; CHECK-NEXT: store i64 -8661621401413125213, ptr [[A1_1]], align 8 77; CHECK-NEXT: store i64 -5015437470765251660, ptr [[A2]], align 8 78; CHECK-NEXT: [[A2_1:%.*]] = getelementptr inbounds [2 x i64], ptr [[A2]], i64 0, i64 1 79; CHECK-NEXT: store i64 -8661621401413125213, ptr [[A2_1]], align 8 80; CHECK-NEXT: br label [[LOOP:%.*]] 81; CHECK: loop: 82; CHECK-NEXT: br label [[LATCH:%.*]] 83; CHECK: latch: 84; CHECK-NEXT: [[LOAD1:%.*]] = load i64, ptr [[A1]], align 8 85; CHECK-NEXT: [[LOAD2:%.*]] = load i64, ptr [[A2]], align 8 86; CHECK-NEXT: [[EXITCOND2:%.*]] = icmp eq i64 [[LOAD1]], [[LOAD2]] 87; CHECK-NEXT: br i1 [[EXITCOND2]], label [[LOOP_1:%.*]], label [[EXIT:%.*]] 88; CHECK: loop.1: 89; CHECK-NEXT: br label [[LATCH_1:%.*]] 90; CHECK: latch.1: 91; CHECK-NEXT: [[GEP1_1:%.*]] = getelementptr inbounds [2 x i64], ptr [[A1]], i64 0, i64 1 92; CHECK-NEXT: [[GEP2_1:%.*]] = getelementptr inbounds [2 x i64], ptr [[A2]], i64 0, i64 1 93; CHECK-NEXT: [[LOAD1_1:%.*]] = load i64, ptr [[GEP1_1]], align 8 94; CHECK-NEXT: [[LOAD2_1:%.*]] = load i64, ptr [[GEP2_1]], align 8 95; CHECK-NEXT: [[EXITCOND2_1:%.*]] = icmp eq i64 [[LOAD1_1]], [[LOAD2_1]] 96; CHECK-NEXT: br i1 [[EXITCOND2_1]], label [[LOOP_2:%.*]], label [[EXIT]] 97; CHECK: loop.2: 98; CHECK-NEXT: br i1 true, label [[EXIT]], label [[LATCH_2:%.*]] 99; CHECK: latch.2: 100; CHECK-NEXT: br label [[EXIT]] 101; CHECK: exit: 102; CHECK-NEXT: [[EXIT_VAL:%.*]] = phi i1 [ false, [[LATCH]] ], [ false, [[LATCH_1]] ], [ true, [[LOOP_2]] ], [ false, [[LATCH_2]] ] 103; CHECK-NEXT: ret i1 [[EXIT_VAL]] 104; 105start: 106 %a1 = alloca [2 x i64], align 8 107 %a2 = alloca [2 x i64], align 8 108 store i64 -5015437470765251660, ptr %a1, align 8 109 %a1.1 = getelementptr inbounds [2 x i64], ptr %a1, i64 0, i64 1 110 store i64 -8661621401413125213, ptr %a1.1, align 8 111 store i64 -5015437470765251660, ptr %a2, align 8 112 %a2.1 = getelementptr inbounds [2 x i64], ptr %a2, i64 0, i64 1 113 store i64 -8661621401413125213, ptr %a2.1, align 8 114 br label %loop 115 116loop: 117 %iv = phi i64 [ 0, %start ], [ %iv.next, %latch ] 118 %exitcond = icmp eq i64 %iv, 2 119 br i1 %exitcond, label %exit, label %latch 120 121latch: 122 %iv.next = add nuw nsw i64 %iv, 1 123 %gep1 = getelementptr inbounds [2 x i64], ptr %a1, i64 0, i64 %iv 124 %gep2 = getelementptr inbounds [2 x i64], ptr %a2, i64 0, i64 %iv 125 %load1 = load i64, ptr %gep1, align 8 126 %load2 = load i64, ptr %gep2, align 8 127 %exitcond2 = icmp eq i64 %load1, %load2 128 br i1 %exitcond2, label %loop, label %exit 129 130exit: 131 %exit.val = phi i1 [ false, %latch ], [ true, %loop ] 132 ret i1 %exit.val 133} 134