Home | History | Annotate | Download | only in IndVarSimplify
      1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
      2 ; RUN: opt < %s -indvars -S | FileCheck %s
      3 
      4 target datalayout = "e-m:e-i64:64-p:64:64:64-n8:16:32:64-S128"
      5 
      6 ; When widening IV and its users, trunc and zext/sext are not needed
      7 ; if the original 32-bit user is known to be non-negative, whether
      8 ; the IV is considered signed or unsigned.
      9 define void @foo(i32* %A, i32* %B, i32* %C, i32 %N) {
     10 ; CHECK-LABEL: @foo(
     11 ; CHECK-NEXT:  entry:
     12 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, %N
     13 ; CHECK-NEXT:    br i1 [[CMP1]], label %for.body.lr.ph, label %for.end
     14 ; CHECK:       for.body.lr.ph:
     15 ; CHECK-NEXT:    br label %for.body
     16 ; CHECK:       for.body:
     17 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV:%.*]].next, %for.inc ], [ 0, %for.body.lr.ph ]
     18 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* %B, i64 [[INDVARS_IV]]
     19 ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
     20 ; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 2
     21 ; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, i32* %C, i64 [[TMP1]]
     22 ; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[ARRAYIDX2]], align 4
     23 ; CHECK-NEXT:    [[ADD3:%.*]] = add nsw i32 [[TMP0]], [[TMP2]]
     24 ; CHECK-NEXT:    [[TRUNC0:%.*]] = trunc i64 [[TMP1]] to i32
     25 ; CHECK-NEXT:    [[DIV0:%.*]] = udiv i32 5, [[TRUNC0]]
     26 ; CHECK-NEXT:    [[ADD4:%.*]] = add nsw i32 [[ADD3]], [[DIV0]]
     27 ; CHECK-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds i32, i32* %A, i64 [[INDVARS_IV]]
     28 ; CHECK-NEXT:    store i32 [[ADD4]], i32* [[ARRAYIDX5]], align 4
     29 ; CHECK-NEXT:    br label %for.inc
     30 ; CHECK:       for.inc:
     31 ; CHECK-NEXT:    [[INDVARS_IV_NEXT:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 1
     32 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 %N to i64
     33 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
     34 ; CHECK-NEXT:    br i1 [[EXITCOND]], label %for.body, label %for.cond.for.end_crit_edge
     35 ; CHECK:       for.cond.for.end_crit_edge:
     36 ; CHECK-NEXT:    br label %for.end
     37 ; CHECK:       for.end:
     38 ; CHECK-NEXT:    ret void
     39 ;
     40 entry:
     41   %cmp1 = icmp slt i32 0, %N
     42   br i1 %cmp1, label %for.body.lr.ph, label %for.end
     43 
     44 for.body.lr.ph:                                   ; preds = %entry
     45   br label %for.body
     46 
     47 for.body:                                         ; preds = %for.body.lr.ph, %for.inc
     48   %i.02 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
     49   %idxprom = sext i32 %i.02 to i64
     50   %arrayidx = getelementptr inbounds i32, i32* %B, i64 %idxprom
     51   %0 = load i32, i32* %arrayidx, align 4
     52   %add = add nsw i32 %i.02, 2
     53   %idxprom1 = zext i32 %add to i64
     54   %arrayidx2 = getelementptr inbounds i32, i32* %C, i64 %idxprom1
     55   %1 = load i32, i32* %arrayidx2, align 4
     56   %add3 = add nsw i32 %0, %1
     57   %div0 = udiv i32 5, %add
     58   %add4 = add nsw i32 %add3, %div0
     59   %idxprom4 = zext i32 %i.02 to i64
     60   %arrayidx5 = getelementptr inbounds i32, i32* %A, i64 %idxprom4
     61   store i32 %add4, i32* %arrayidx5, align 4
     62   br label %for.inc
     63 
     64 for.inc:                                          ; preds = %for.body
     65   %inc = add nsw i32 %i.02, 1
     66   %cmp = icmp slt i32 %inc, %N
     67   br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge
     68 
     69 for.cond.for.end_crit_edge:                       ; preds = %for.inc
     70   br label %for.end
     71 
     72 for.end:                                          ; preds = %for.cond.for.end_crit_edge, %entry
     73   ret void
     74 }
     75 
     76 define void @foo1(i32* %A, i32* %B, i32* %C, i32 %N) {
     77 ; CHECK-LABEL: @foo1(
     78 ; CHECK-NEXT:  entry:
     79 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, %N
     80 ; CHECK-NEXT:    br i1 [[CMP1]], label %for.body.lr.ph, label %for.end
     81 ; CHECK:       for.body.lr.ph:
     82 ; CHECK-NEXT:    br label %for.body
     83 ; CHECK:       for.body:
     84 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV:%.*]].next, %for.inc ], [ 0, %for.body.lr.ph ]
     85 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* %B, i64 [[INDVARS_IV]]
     86 ; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
     87 ; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 2
     88 ; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, i32* %C, i64 [[TMP1]]
     89 ; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[ARRAYIDX2]], align 4
     90 ; CHECK-NEXT:    [[ADD3:%.*]] = add nsw i32 [[TMP0]], [[TMP2]]
     91 ; CHECK-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds i32, i32* %A, i64 [[INDVARS_IV]]
     92 ; CHECK-NEXT:    store i32 [[ADD3]], i32* [[ARRAYIDX5]], align 4
     93 ; CHECK-NEXT:    br label %for.inc
     94 ; CHECK:       for.inc:
     95 ; CHECK-NEXT:    [[INDVARS_IV_NEXT:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 1
     96 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 %N to i64
     97 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
     98 ; CHECK-NEXT:    br i1 [[EXITCOND]], label %for.body, label %for.cond.for.end_crit_edge
     99 ; CHECK:       for.cond.for.end_crit_edge:
    100 ; CHECK-NEXT:    br label %for.end
    101 ; CHECK:       for.end:
    102 ; CHECK-NEXT:    ret void
    103 ;
    104 entry:
    105   %cmp1 = icmp slt i32 0, %N
    106   br i1 %cmp1, label %for.body.lr.ph, label %for.end
    107 
    108 for.body.lr.ph:                                   ; preds = %entry
    109   br label %for.body
    110 
    111 for.body:                                         ; preds = %for.body.lr.ph, %for.inc
    112   %i.02 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
    113   %idxprom = zext i32 %i.02 to i64
    114   %arrayidx = getelementptr inbounds i32, i32* %B, i64 %idxprom
    115   %0 = load i32, i32* %arrayidx, align 4
    116   %add = add nsw i32 %i.02, 2
    117   %idxprom1 = sext i32 %add to i64
    118   %arrayidx2 = getelementptr inbounds i32, i32* %C, i64 %idxprom1
    119   %1 = load i32, i32* %arrayidx2, align 4
    120   %add3 = add nsw i32 %0, %1
    121   %idxprom4 = sext i32 %i.02 to i64
    122   %arrayidx5 = getelementptr inbounds i32, i32* %A, i64 %idxprom4
    123   store i32 %add3, i32* %arrayidx5, align 4
    124   br label %for.inc
    125 
    126 for.inc:                                          ; preds = %for.body
    127   %inc = add nsw i32 %i.02, 1
    128   %cmp = icmp slt i32 %inc, %N
    129   br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge
    130 
    131 for.cond.for.end_crit_edge:                       ; preds = %for.inc
    132   br label %for.end
    133 
    134 for.end:                                          ; preds = %for.cond.for.end_crit_edge, %entry
    135   ret void
    136 }
    137 
    138 
    139 @a = common global [100 x i32] zeroinitializer, align 16
    140 @b = common global [100 x i32] zeroinitializer, align 16
    141 
    142 define i32 @foo2(i32 %M) {
    143 ; CHECK-LABEL: @foo2(
    144 ; CHECK-NEXT:  entry:
    145 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, %M
    146 ; CHECK-NEXT:    br i1 [[CMP1]], label %for.body.lr.ph, label %for.end
    147 ; CHECK:       for.body.lr.ph:
    148 ; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 %M to i64
    149 ; CHECK-NEXT:    br label %for.body
    150 ; CHECK:       for.body:
    151 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV:%.*]].next, %for.inc ], [ 0, %for.body.lr.ph ]
    152 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* @a, i64 0, i64 [[INDVARS_IV]]
    153 ; CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
    154 ; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* @b, i64 0, i64 [[INDVARS_IV]]
    155 ; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[ARRAYIDX2]], align 4
    156 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP1]], [[TMP2]]
    157 ; CHECK-NEXT:    [[TMP3:%.*]] = add nsw i64 [[INDVARS_IV]], [[TMP0]]
    158 ; CHECK-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* @a, i64 0, i64 [[TMP3]]
    159 ; CHECK-NEXT:    store i32 [[ADD]], i32* [[ARRAYIDX5]], align 4
    160 ; CHECK-NEXT:    br label %for.inc
    161 ; CHECK:       for.inc:
    162 ; CHECK-NEXT:    [[INDVARS_IV_NEXT:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 1
    163 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 %M to i64
    164 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
    165 ; CHECK-NEXT:    br i1 [[EXITCOND]], label %for.body, label %for.cond.for.end_crit_edge
    166 ; CHECK:       for.cond.for.end_crit_edge:
    167 ; CHECK-NEXT:    br label %for.end
    168 ; CHECK:       for.end:
    169 ; CHECK-NEXT:    [[CALL:%.*]] = call i32 @dummy(i32* getelementptr inbounds ([100 x i32], [100 x i32]* @a, i32 0, i32 0), i32* getelementptr inbounds ([100 x i32], [100 x i32]* @b, i32 0, i32 0))
    170 ; CHECK-NEXT:    ret i32 0
    171 ;
    172 entry:
    173   %cmp1 = icmp slt i32 0, %M
    174   br i1 %cmp1, label %for.body.lr.ph, label %for.end
    175 
    176 for.body.lr.ph:                                   ; preds = %entry
    177   br label %for.body
    178 
    179 for.body:                                         ; preds = %for.body.lr.ph, %for.inc
    180   %i.02 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
    181   %idxprom = zext i32 %i.02 to i64
    182   %arrayidx = getelementptr inbounds [100 x i32], [100 x i32]* @a, i64 0, i64 %idxprom
    183   %0 = load i32, i32* %arrayidx, align 4
    184   %idxprom1 = sext i32 %i.02 to i64
    185   %arrayidx2 = getelementptr inbounds [100 x i32], [100 x i32]* @b, i64 0, i64 %idxprom1
    186   %1 = load i32, i32* %arrayidx2, align 4
    187   %add = add nsw i32 %0, %1
    188   %add3 = add nsw i32 %i.02, %M
    189   %idxprom4 = sext i32 %add3 to i64
    190   %arrayidx5 = getelementptr inbounds [100 x i32], [100 x i32]* @a, i64 0, i64 %idxprom4
    191   store i32 %add, i32* %arrayidx5, align 4
    192   br label %for.inc
    193 
    194 for.inc:                                          ; preds = %for.body
    195   %inc = add nsw i32 %i.02, 1
    196   %cmp = icmp slt i32 %inc, %M
    197   br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge
    198 
    199 for.cond.for.end_crit_edge:                       ; preds = %for.inc
    200   br label %for.end
    201 
    202 for.end:                                          ; preds = %for.cond.for.end_crit_edge, %entry
    203   %call = call i32 @dummy(i32* getelementptr inbounds ([100 x i32], [100 x i32]* @a, i32 0, i32 0), i32* getelementptr inbounds ([100 x i32], [100 x i32]* @b, i32 0, i32 0))
    204   ret i32 0
    205 }
    206 
    207 declare i32 @dummy(i32*, i32*)
    208 
    209 ; A case where zext should not be eliminated when its operands could only be extended by sext.
    210 define i32 @foo3(i32 %M) {
    211 ; CHECK-LABEL: @foo3(
    212 ; CHECK-NEXT:  entry:
    213 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 0, %M
    214 ; CHECK-NEXT:    br i1 [[CMP1]], label %for.body.lr.ph, label %for.end
    215 ; CHECK:       for.body.lr.ph:
    216 ; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 %M to i64
    217 ; CHECK-NEXT:    br label %for.body
    218 ; CHECK:       for.body:
    219 ; CHECK-NEXT:    [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV:%.*]].next, %for.inc ], [ 0, %for.body.lr.ph ]
    220 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* @a, i64 0, i64 [[INDVARS_IV]]
    221 ; CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* [[ARRAYIDX]], align 4
    222 ; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* @b, i64 0, i64 [[INDVARS_IV]]
    223 ; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[ARRAYIDX2]], align 4
    224 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP1]], [[TMP2]]
    225 ; CHECK-NEXT:    [[TMP3:%.*]] = add nsw i64 [[INDVARS_IV]], [[TMP0]]
    226 ; CHECK-NEXT:    [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32
    227 ; CHECK-NEXT:    [[IDXPROM4:%.*]] = zext i32 [[TMP4]] to i64
    228 ; CHECK-NEXT:    [[ARRAYIDX5:%.*]] = getelementptr inbounds [100 x i32], [100 x i32]* @a, i64 0, i64 [[IDXPROM4]]
    229 ; CHECK-NEXT:    store i32 [[ADD]], i32* [[ARRAYIDX5]], align 4
    230 ; CHECK-NEXT:    br label %for.inc
    231 ; CHECK:       for.inc:
    232 ; CHECK-NEXT:    [[INDVARS_IV_NEXT:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 1
    233 ; CHECK-NEXT:    [[WIDE_TRIP_COUNT:%.*]] = zext i32 %M to i64
    234 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]]
    235 ; CHECK-NEXT:    br i1 [[EXITCOND]], label %for.body, label %for.cond.for.end_crit_edge
    236 ; CHECK:       for.cond.for.end_crit_edge:
    237 ; CHECK-NEXT:    br label %for.end
    238 ; CHECK:       for.end:
    239 ; CHECK-NEXT:    [[CALL:%.*]] = call i32 @dummy(i32* getelementptr inbounds ([100 x i32], [100 x i32]* @a, i32 0, i32 0), i32* getelementptr inbounds ([100 x i32], [100 x i32]* @b, i32 0, i32 0))
    240 ; CHECK-NEXT:    ret i32 0
    241 ;
    242 entry:
    243   %cmp1 = icmp slt i32 0, %M
    244   br i1 %cmp1, label %for.body.lr.ph, label %for.end
    245 
    246 for.body.lr.ph:                                   ; preds = %entry
    247   br label %for.body
    248 
    249 for.body:                                         ; preds = %for.body.lr.ph, %for.inc
    250   %i.02 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ]
    251   %idxprom = sext i32 %i.02 to i64
    252   %arrayidx = getelementptr inbounds [100 x i32], [100 x i32]* @a, i64 0, i64 %idxprom
    253   %0 = load i32, i32* %arrayidx, align 4
    254   %idxprom1 = sext i32 %i.02 to i64
    255   %arrayidx2 = getelementptr inbounds [100 x i32], [100 x i32]* @b, i64 0, i64 %idxprom1
    256   %1 = load i32, i32* %arrayidx2, align 4
    257   %add = add nsw i32 %0, %1
    258   %add3 = add nsw i32 %i.02, %M
    259   %idxprom4 = zext i32 %add3 to i64
    260   %arrayidx5 = getelementptr inbounds [100 x i32], [100 x i32]* @a, i64 0, i64 %idxprom4
    261   store i32 %add, i32* %arrayidx5, align 4
    262   br label %for.inc
    263 
    264 for.inc:                                          ; preds = %for.body
    265   %inc = add nsw i32 %i.02, 1
    266   %cmp = icmp slt i32 %inc, %M
    267   br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge
    268 
    269 for.cond.for.end_crit_edge:                       ; preds = %for.inc
    270   br label %for.end
    271 
    272 for.end:                                          ; preds = %for.cond.for.end_crit_edge, %entry
    273   %call = call i32 @dummy(i32* getelementptr inbounds ([100 x i32], [100 x i32]* @a, i32 0, i32 0), i32* getelementptr inbounds ([100 x i32], [100 x i32]* @b, i32 0, i32 0))
    274   ret i32 0
    275 }
    276