1; RUN: opt < %s -indvars -S | FileCheck %s 2 3target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" 4 5; IV with constant start, preinc and postinc sign extends, with and without NSW. 6; IV rewrite only removes one sext. WidenIVs removes all three. 7define void @postincConstIV(i8* %base, i32 %limit) nounwind { 8entry: 9 br label %loop 10; CHECK: loop: 11; CHECK-NOT: sext 12; CHECK: exit: 13loop: 14 %iv = phi i32 [ %postiv, %loop ], [ 0, %entry ] 15 %ivnsw = phi i32 [ %postivnsw, %loop ], [ 0, %entry ] 16 %preofs = sext i32 %iv to i64 17 %preadr = getelementptr i8, i8* %base, i64 %preofs 18 store i8 0, i8* %preadr 19 %postiv = add i32 %iv, 1 20 %postofs = sext i32 %postiv to i64 21 %postadr = getelementptr i8, i8* %base, i64 %postofs 22 store i8 0, i8* %postadr 23 %postivnsw = add nsw i32 %ivnsw, 1 24 %postofsnsw = sext i32 %postivnsw to i64 25 %postadrnsw = getelementptr inbounds i8, i8* %base, i64 %postofsnsw 26 store i8 0, i8* %postadrnsw 27 %cond = icmp sgt i32 %limit, %iv 28 br i1 %cond, label %loop, label %exit 29exit: 30 br label %return 31return: 32 ret void 33} 34 35; IV with nonconstant start, preinc and postinc sign extends, 36; with and without NSW. 37; As with postincConstIV, WidenIVs removes all three sexts. 38define void @postincVarIV(i8* %base, i32 %init, i32 %limit) nounwind { 39entry: 40 %precond = icmp sgt i32 %limit, %init 41 br i1 %precond, label %loop, label %return 42; CHECK: loop: 43; CHECK-NOT: sext 44; CHECK: wide.trip.count = sext 45; CHECK-NOT: sext 46; CHECK: exit: 47loop: 48 %iv = phi i32 [ %postiv, %loop ], [ %init, %entry ] 49 %ivnsw = phi i32 [ %postivnsw, %loop ], [ %init, %entry ] 50 %preofs = sext i32 %iv to i64 51 %preadr = getelementptr i8, i8* %base, i64 %preofs 52 store i8 0, i8* %preadr 53 %postiv = add i32 %iv, 1 54 %postofs = sext i32 %postiv to i64 55 %postadr = getelementptr i8, i8* %base, i64 %postofs 56 store i8 0, i8* %postadr 57 %postivnsw = add nsw i32 %ivnsw, 1 58 %postofsnsw = sext i32 %postivnsw to i64 59 %postadrnsw = getelementptr i8, i8* %base, i64 %postofsnsw 60 store i8 0, i8* %postadrnsw 61 %cond = icmp sgt i32 %limit, %postiv 62 br i1 %cond, label %loop, label %exit 63exit: 64 br label %return 65return: 66 ret void 67} 68 69; Test sign extend elimination in the inner and outer loop. 70; %outercount is straightforward to widen, besides being in an outer loop. 71; %innercount is currently blocked by lcssa, so is not widened. 72; %inneriv can be widened only after proving it has no signed-overflow 73; based on the loop test. 74define void @nestedIV(i8* %address, i32 %limit) nounwind { 75entry: 76 %limitdec = add i32 %limit, -1 77 br label %outerloop 78 79; CHECK: outerloop: 80; 81; Eliminate %ofs1 after widening outercount. 82; CHECK-NOT: sext 83; CHECK: getelementptr 84; 85; IV rewriting hoists a gep into this block. We don't like that. 86; CHECK-NOT: getelementptr 87outerloop: 88 %outercount = phi i32 [ %outerpostcount, %outermerge ], [ 0, %entry ] 89 %innercount = phi i32 [ %innercount.merge, %outermerge ], [ 0, %entry ] 90 91 %outercountdec = add i32 %outercount, -1 92 %ofs1 = sext i32 %outercountdec to i64 93 %adr1 = getelementptr i8, i8* %address, i64 %ofs1 94 store i8 0, i8* %adr1 95 96 br label %innerpreheader 97 98innerpreheader: 99 %innerprecmp = icmp sgt i32 %limitdec, %innercount 100 br i1 %innerprecmp, label %innerloop, label %outermerge 101 102; CHECK: innerloop: 103; 104; Eliminate %ofs2 after widening inneriv. 105; Eliminate %ofs3 after normalizing sext(innerpostiv) 106; CHECK-NOT: sext 107; CHECK: getelementptr 108; 109; FIXME: We should check that indvars does not increase the number of 110; IVs in this loop. sext elimination plus LFTR currently results in 2 final 111; IVs. Waiting to remove LFTR. 112innerloop: 113 %inneriv = phi i32 [ %innerpostiv, %innerloop ], [ %innercount, %innerpreheader ] 114 %innerpostiv = add i32 %inneriv, 1 115 116 %ofs2 = sext i32 %inneriv to i64 117 %adr2 = getelementptr i8, i8* %address, i64 %ofs2 118 store i8 0, i8* %adr2 119 120 %ofs3 = sext i32 %innerpostiv to i64 121 %adr3 = getelementptr i8, i8* %address, i64 %ofs3 122 store i8 0, i8* %adr3 123 124 %innercmp = icmp sgt i32 %limitdec, %innerpostiv 125 br i1 %innercmp, label %innerloop, label %innerexit 126 127innerexit: 128 %innercount.lcssa = phi i32 [ %innerpostiv, %innerloop ] 129 br label %outermerge 130 131; CHECK: outermerge: 132; 133; Eliminate %ofs4 after widening outercount 134; CHECK-NOT: sext 135; CHECK: getelementptr 136; 137; TODO: Eliminate %ofs5 after removing lcssa 138outermerge: 139 %innercount.merge = phi i32 [ %innercount.lcssa, %innerexit ], [ %innercount, %innerpreheader ] 140 141 %ofs4 = sext i32 %outercount to i64 142 %adr4 = getelementptr i8, i8* %address, i64 %ofs4 143 store i8 0, i8* %adr4 144 145 %ofs5 = sext i32 %innercount.merge to i64 146 %adr5 = getelementptr i8, i8* %address, i64 %ofs5 147 store i8 0, i8* %adr5 148 149 %outerpostcount = add i32 %outercount, 1 150 %tmp47 = icmp slt i32 %outerpostcount, %limit 151 br i1 %tmp47, label %outerloop, label %return 152 153return: 154 ret void 155} 156