1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; Check that phi analysis can determine the number of iterations of the 3; loop to peel such that the phi nodes (other than the iteration variable) 4; have their resulting values known and are thus removed by peeling the loop 5; at least that many times. 6 7; RUN: opt < %s -S -passes=loop-unroll | FileCheck %s 8; RUN: opt < %s -S -passes=loop-unroll-full | FileCheck %s 9 10; void f(float); 11; void g(int); 12declare void @_Z1ff(float) 13declare void @_Z1gi(i32 signext) 14 15; Check that phi analysis can handle a cast. 16define void @_Z8castTestv() { 17; The phis become invariant through the chain of phis, with a unary 18; instruction on a loop invariant. Check that the phis for x, a, and y 19; are removed since x is based on a cast of y, which is based on a, which is 20; set on the backedge. 21; Consider the calls to g and f. 22; First iteration: g(0), x=0, f(0.0), y=0.0, a=5.0 23; Second iteration: g(0), x=0, f(0.0), y=5.0, a=5.0 24; Third iteration: g(0), x=5 (requires cast), f(5.0), a=5.0 25; Fourth iteration (and subsequent): g(5), x=5, f(5.0), a=5.0 26; Therefore, peeling 3 times removes the phi nodes, so check for 3 peels. 27; 28; void castTest() { 29; int x = 0; 30; float y = 0.0; 31; float a = 0.0; 32; for(int i = 0; i <100000; ++i) { 33; g(x); 34; x = y; 35; f(y); 36; y = a; 37; a = 5.0; 38; } 39; } 40; 41; CHECK-LABEL: @_Z8castTestv( 42; CHECK-NEXT: entry: 43; CHECK-NEXT: br label [[FOR_BODY_PEEL_BEGIN:%.*]] 44; CHECK: for.body.peel.begin: 45; CHECK-NEXT: br label [[FOR_BODY_PEEL:%.*]] 46; CHECK: for.body.peel: 47; CHECK-NEXT: tail call void @_Z1gi(i32 noundef signext 0) 48; CHECK-NEXT: [[CONV_PEEL:%.*]] = fptosi float 0.000000e+00 to i32 49; CHECK-NEXT: tail call void @_Z1ff(float noundef 0.000000e+00) 50; CHECK-NEXT: [[INC_PEEL:%.*]] = add nuw nsw i32 0, 1 51; CHECK-NEXT: [[EXITCOND_PEEL:%.*]] = icmp ne i32 [[INC_PEEL]], 100000 52; CHECK-NEXT: br i1 [[EXITCOND_PEEL]], label [[FOR_BODY_PEEL_NEXT:%.*]], label [[FOR_COND_CLEANUP:%.*]] 53; CHECK: for.body.peel.next: 54; CHECK-NEXT: br label [[FOR_BODY_PEEL2:%.*]] 55; CHECK: for.body.peel2: 56; CHECK-NEXT: tail call void @_Z1gi(i32 noundef signext [[CONV_PEEL]]) 57; CHECK-NEXT: [[CONV_PEEL3:%.*]] = fptosi float 0.000000e+00 to i32 58; CHECK-NEXT: tail call void @_Z1ff(float noundef 0.000000e+00) 59; CHECK-NEXT: [[INC_PEEL4:%.*]] = add nuw nsw i32 [[INC_PEEL]], 1 60; CHECK-NEXT: [[EXITCOND_PEEL5:%.*]] = icmp ne i32 [[INC_PEEL4]], 100000 61; CHECK-NEXT: br i1 [[EXITCOND_PEEL5]], label [[FOR_BODY_PEEL_NEXT1:%.*]], label [[FOR_COND_CLEANUP]] 62; CHECK: for.body.peel.next1: 63; CHECK-NEXT: br label [[FOR_BODY_PEEL7:%.*]] 64; CHECK: for.body.peel7: 65; CHECK-NEXT: tail call void @_Z1gi(i32 noundef signext [[CONV_PEEL3]]) 66; CHECK-NEXT: [[CONV_PEEL8:%.*]] = fptosi float 5.000000e+00 to i32 67; CHECK-NEXT: tail call void @_Z1ff(float noundef 5.000000e+00) 68; CHECK-NEXT: [[INC_PEEL9:%.*]] = add nuw nsw i32 [[INC_PEEL4]], 1 69; CHECK-NEXT: [[EXITCOND_PEEL10:%.*]] = icmp ne i32 [[INC_PEEL9]], 100000 70; CHECK-NEXT: br i1 [[EXITCOND_PEEL10]], label [[FOR_BODY_PEEL_NEXT6:%.*]], label [[FOR_COND_CLEANUP]] 71; CHECK: for.body.peel.next6: 72; CHECK-NEXT: br label [[FOR_BODY_PEEL_NEXT11:%.*]] 73; CHECK: for.body.peel.next11: 74; CHECK-NEXT: br label [[ENTRY_PEEL_NEWPH:%.*]] 75; CHECK: entry.peel.newph: 76; CHECK-NEXT: br label [[FOR_BODY:%.*]] 77; CHECK: for.cond.cleanup.loopexit: 78; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] 79; CHECK: for.cond.cleanup: 80; CHECK-NEXT: ret void 81; CHECK: for.body: 82; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[INC_PEEL9]], [[ENTRY_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_BODY]] ] 83; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[CONV_PEEL8]], [[ENTRY_PEEL_NEWPH]] ], [ 5, [[FOR_BODY]] ] 84; CHECK-NEXT: tail call void @_Z1gi(i32 noundef signext [[X]]) 85; CHECK-NEXT: tail call void @_Z1ff(float noundef 5.000000e+00) 86; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1 87; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[INC]], 100000 88; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], !llvm.loop [[LOOP0:![0-9]+]] 89; 90entry: 91 br label %for.body 92 93for.cond.cleanup: 94 ret void 95 96for.body: 97 %i = phi i32 [ 0, %entry ], [ %inc, %for.body ] 98 %a = phi float [ 0.000000e+00, %entry ], [ 5.000000e+00, %for.body ] 99 %y = phi float [ 0.000000e+00, %entry ], [ %a, %for.body ] 100 %x = phi i32 [ 0, %entry ], [ %conv, %for.body ] 101 tail call void @_Z1gi(i32 noundef signext %x) 102 %conv = fptosi float %y to i32 103 tail call void @_Z1ff(float noundef %y) 104 %inc = add nuw nsw i32 %i, 1 105 %exitcond = icmp ne i32 %inc, 100000 106 br i1 %exitcond, label %for.body, label %for.cond.cleanup 107} 108 109; Check that phi analysis can handle a binary operator. 110define void @_Z6binaryv() { 111; The phis become invariant through the chain of phis, with a unary 112; instruction on a loop invariant. Check that the phis for x, a, and y 113; are removed since x is based on y, which is based on a, which is based 114; on a binary add of a phi and a constant. 115; Consider the calls to g: 116; First iteration: g(0), x=0, g(0), y=1, a=5 117; Second iteration: g(0), x=1, g(5), y=6(binary operator), a=5 118; Third iteration: g(1), x=6, g(5), y=6, a=5 119; Fourth iteration (and subsequent): g(6), x=6, g(5), y=6, a=5 120; Therefore, peeling 3 times removes the phi nodes. 121; 122; void g(int); 123; void binary() { 124; int x = 0; 125; int y = 0; 126; int a = 0; 127; for(int i = 0; i <100000; ++i) { 128; g(x); 129; x = y; 130; g(a); 131; y = a + 1; 132; a = 5; 133; } 134; } 135; 136; CHECK-LABEL: @_Z6binaryv( 137; CHECK-NEXT: entry: 138; CHECK-NEXT: br label [[FOR_BODY_PEEL_BEGIN:%.*]] 139; CHECK: for.body.peel.begin: 140; CHECK-NEXT: br label [[FOR_BODY_PEEL:%.*]] 141; CHECK: for.body.peel: 142; CHECK-NEXT: tail call void @_Z1gi(i32 signext 0) 143; CHECK-NEXT: tail call void @_Z1gi(i32 signext 0) 144; CHECK-NEXT: [[ADD_PEEL:%.*]] = add nuw nsw i32 0, 1 145; CHECK-NEXT: [[INC_PEEL:%.*]] = add nuw nsw i32 0, 1 146; CHECK-NEXT: [[EXITCOND_PEEL:%.*]] = icmp eq i32 [[INC_PEEL]], 100000 147; CHECK-NEXT: br i1 [[EXITCOND_PEEL]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY_PEEL_NEXT:%.*]] 148; CHECK: for.body.peel.next: 149; CHECK-NEXT: br label [[FOR_BODY_PEEL2:%.*]] 150; CHECK: for.body.peel2: 151; CHECK-NEXT: tail call void @_Z1gi(i32 signext 0) 152; CHECK-NEXT: tail call void @_Z1gi(i32 signext 5) 153; CHECK-NEXT: [[INC_PEEL4:%.*]] = add nuw nsw i32 [[INC_PEEL]], 1 154; CHECK-NEXT: [[EXITCOND_PEEL5:%.*]] = icmp eq i32 [[INC_PEEL4]], 100000 155; CHECK-NEXT: br i1 [[EXITCOND_PEEL5]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY_PEEL_NEXT1:%.*]] 156; CHECK: for.body.peel.next1: 157; CHECK-NEXT: br label [[FOR_BODY_PEEL7:%.*]] 158; CHECK: for.body.peel7: 159; CHECK-NEXT: tail call void @_Z1gi(i32 signext [[ADD_PEEL]]) 160; CHECK-NEXT: tail call void @_Z1gi(i32 signext 5) 161; CHECK-NEXT: [[INC_PEEL9:%.*]] = add nuw nsw i32 [[INC_PEEL4]], 1 162; CHECK-NEXT: [[EXITCOND_PEEL10:%.*]] = icmp eq i32 [[INC_PEEL9]], 100000 163; CHECK-NEXT: br i1 [[EXITCOND_PEEL10]], label [[FOR_COND_CLEANUP]], label [[FOR_BODY_PEEL_NEXT6:%.*]] 164; CHECK: for.body.peel.next6: 165; CHECK-NEXT: br label [[FOR_BODY_PEEL_NEXT11:%.*]] 166; CHECK: for.body.peel.next11: 167; CHECK-NEXT: br label [[ENTRY_PEEL_NEWPH:%.*]] 168; CHECK: entry.peel.newph: 169; CHECK-NEXT: br label [[FOR_BODY:%.*]] 170; CHECK: for.cond.cleanup.loopexit: 171; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] 172; CHECK: for.cond.cleanup: 173; CHECK-NEXT: ret void 174; CHECK: for.body: 175; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[INC_PEEL9]], [[ENTRY_PEEL_NEWPH]] ], [ [[INC:%.*]], [[FOR_BODY]] ] 176; CHECK-NEXT: tail call void @_Z1gi(i32 signext 6) 177; CHECK-NEXT: tail call void @_Z1gi(i32 signext 5) 178; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1 179; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 100000 180; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]], !llvm.loop [[LOOP2:![0-9]+]] 181; 182entry: 183 br label %for.body 184 185for.cond.cleanup: 186 ret void 187 188for.body: 189 %i = phi i32 [ 0, %entry ], [ %inc, %for.body ] 190 %a = phi i32 [ 0, %entry ], [ 5, %for.body ] 191 %y = phi i32 [ 0, %entry ], [ %add, %for.body ] 192 %x = phi i32 [ 0, %entry ], [ %y, %for.body ] 193 tail call void @_Z1gi(i32 signext %x) 194 tail call void @_Z1gi(i32 signext %a) 195 %add = add nuw nsw i32 %a, 1 196 %inc = add nuw nsw i32 %i, 1 197 %exitcond = icmp eq i32 %inc, 100000 198 br i1 %exitcond, label %for.cond.cleanup, label %for.body 199} 200