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