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