Home | History | Annotate | Download | only in IndVarSimplify
      1 ; RUN: opt < %s -indvars -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