Home | History | Annotate | Download | only in LoopVectorize
      1 ; RUN: opt < %s -O3 -loop-vectorize -force-vector-unroll=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s
      2 
      3 target datalayout = "e-p:32:32:32-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:64:128-a0:0:64-n32-S64"
      4 
      5 %struct.anon = type { [100 x i32], i32, [100 x i32] }
      6 %struct.anon.0 = type { [100 x [100 x i32]], i32, [100 x [100 x i32]] }
      7 
      8 @Foo = common global %struct.anon zeroinitializer, align 4
      9 @Bar = common global %struct.anon.0 zeroinitializer, align 4
     10 
     11 @PB = external global i32*
     12 @PA = external global i32*
     13 
     14 
     15 ;; === First, the tests that should always vectorize, wither statically or by adding run-time checks ===
     16 
     17 
     18 ; /// Different objects, positive induction, constant distance
     19 ; int noAlias01 (int a) {
     20 ;   int i;
     21 ;   for (i=0; i<SIZE; i++)
     22 ;     Foo.A[i] = Foo.B[i] + a;
     23 ;   return Foo.A[a];
     24 ; }
     25 ; CHECK-LABEL: define i32 @noAlias01(
     26 ; CHECK: add nsw <4 x i32>
     27 ; CHECK: ret
     28 
     29 define i32 @noAlias01(i32 %a) nounwind {
     30 entry:
     31   %a.addr = alloca i32, align 4
     32   %i = alloca i32, align 4
     33   store i32 %a, i32* %a.addr, align 4
     34   store i32 0, i32* %i, align 4
     35   br label %for.cond
     36 
     37 for.cond:                                         ; preds = %for.inc, %entry
     38   %0 = load i32* %i, align 4
     39   %cmp = icmp slt i32 %0, 100
     40   br i1 %cmp, label %for.body, label %for.end
     41 
     42 for.body:                                         ; preds = %for.cond
     43   %1 = load i32* %i, align 4
     44   %arrayidx = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %1
     45   %2 = load i32* %arrayidx, align 4
     46   %3 = load i32* %a.addr, align 4
     47   %add = add nsw i32 %2, %3
     48   %4 = load i32* %i, align 4
     49   %arrayidx1 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %4
     50   store i32 %add, i32* %arrayidx1, align 4
     51   br label %for.inc
     52 
     53 for.inc:                                          ; preds = %for.body
     54   %5 = load i32* %i, align 4
     55   %inc = add nsw i32 %5, 1
     56   store i32 %inc, i32* %i, align 4
     57   br label %for.cond
     58 
     59 for.end:                                          ; preds = %for.cond
     60   %6 = load i32* %a.addr, align 4
     61   %arrayidx2 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
     62   %7 = load i32* %arrayidx2, align 4
     63   ret i32 %7
     64 }
     65 
     66 ; /// Different objects, positive induction with widening slide
     67 ; int noAlias02 (int a) {
     68 ;   int i;
     69 ;   for (i=0; i<SIZE-10; i++)
     70 ;     Foo.A[i] = Foo.B[i+10] + a;
     71 ;   return Foo.A[a];
     72 ; }
     73 ; CHECK-LABEL: define i32 @noAlias02(
     74 ; CHECK: add nsw <4 x i32>
     75 ; CHECK: ret
     76 
     77 define i32 @noAlias02(i32 %a) {
     78 entry:
     79   %a.addr = alloca i32, align 4
     80   %i = alloca i32, align 4
     81   store i32 %a, i32* %a.addr, align 4
     82   store i32 0, i32* %i, align 4
     83   br label %for.cond
     84 
     85 for.cond:                                         ; preds = %for.inc, %entry
     86   %0 = load i32* %i, align 4
     87   %cmp = icmp slt i32 %0, 90
     88   br i1 %cmp, label %for.body, label %for.end
     89 
     90 for.body:                                         ; preds = %for.cond
     91   %1 = load i32* %i, align 4
     92   %add = add nsw i32 %1, 10
     93   %arrayidx = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %add
     94   %2 = load i32* %arrayidx, align 4
     95   %3 = load i32* %a.addr, align 4
     96   %add1 = add nsw i32 %2, %3
     97   %4 = load i32* %i, align 4
     98   %arrayidx2 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %4
     99   store i32 %add1, i32* %arrayidx2, align 4
    100   br label %for.inc
    101 
    102 for.inc:                                          ; preds = %for.body
    103   %5 = load i32* %i, align 4
    104   %inc = add nsw i32 %5, 1
    105   store i32 %inc, i32* %i, align 4
    106   br label %for.cond
    107 
    108 for.end:                                          ; preds = %for.cond
    109   %6 = load i32* %a.addr, align 4
    110   %arrayidx3 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
    111   %7 = load i32* %arrayidx3, align 4
    112   ret i32 %7
    113 }
    114 
    115 ; /// Different objects, positive induction with shortening slide
    116 ; int noAlias03 (int a) {
    117 ;   int i;
    118 ;   for (i=0; i<SIZE; i++)
    119 ;     Foo.A[i+10] = Foo.B[i] + a;
    120 ;   return Foo.A[a];
    121 ; }
    122 ; CHECK-LABEL: define i32 @noAlias03(
    123 ; CHECK: add nsw <4 x i32>
    124 ; CHECK: ret
    125 
    126 define i32 @noAlias03(i32 %a) {
    127 entry:
    128   %a.addr = alloca i32, align 4
    129   %i = alloca i32, align 4
    130   store i32 %a, i32* %a.addr, align 4
    131   store i32 0, i32* %i, align 4
    132   br label %for.cond
    133 
    134 for.cond:                                         ; preds = %for.inc, %entry
    135   %0 = load i32* %i, align 4
    136   %cmp = icmp slt i32 %0, 100
    137   br i1 %cmp, label %for.body, label %for.end
    138 
    139 for.body:                                         ; preds = %for.cond
    140   %1 = load i32* %i, align 4
    141   %arrayidx = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %1
    142   %2 = load i32* %arrayidx, align 4
    143   %3 = load i32* %a.addr, align 4
    144   %add = add nsw i32 %2, %3
    145   %4 = load i32* %i, align 4
    146   %add1 = add nsw i32 %4, 10
    147   %arrayidx2 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %add1
    148   store i32 %add, i32* %arrayidx2, align 4
    149   br label %for.inc
    150 
    151 for.inc:                                          ; preds = %for.body
    152   %5 = load i32* %i, align 4
    153   %inc = add nsw i32 %5, 1
    154   store i32 %inc, i32* %i, align 4
    155   br label %for.cond
    156 
    157 for.end:                                          ; preds = %for.cond
    158   %6 = load i32* %a.addr, align 4
    159   %arrayidx3 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
    160   %7 = load i32* %arrayidx3, align 4
    161   ret i32 %7
    162 }
    163 
    164 ; /// Pointer access, positive stride, run-time check added
    165 ; int noAlias04 (int a) {
    166 ;   int i;
    167 ;   for (i=0; i<SIZE; i++)
    168 ;     *(PA+i) = *(PB+i) + a;
    169 ;   return *(PA+a);
    170 ; }
    171 ; CHECK-LABEL: define i32 @noAlias04(
    172 ; CHECK-NOT: add nsw <4 x i32>
    173 ; CHECK: ret
    174 ;
    175 ; TODO: This test vectorizes (with run-time check) on real targets with -O3)
    176 ; Check why it's not being vectorized even when forcing vectorization
    177 
    178 define i32 @noAlias04(i32 %a) #0 {
    179 entry:
    180   %a.addr = alloca i32, align 4
    181   %i = alloca i32, align 4
    182   store i32 %a, i32* %a.addr, align 4
    183   store i32 0, i32* %i, align 4
    184   br label %for.cond
    185 
    186 for.cond:                                         ; preds = %for.inc, %entry
    187   %0 = load i32* %i, align 4
    188   %cmp = icmp slt i32 %0, 100
    189   br i1 %cmp, label %for.body, label %for.end
    190 
    191 for.body:                                         ; preds = %for.cond
    192   %1 = load i32** @PB, align 4
    193   %2 = load i32* %i, align 4
    194   %add.ptr = getelementptr inbounds i32* %1, i32 %2
    195   %3 = load i32* %add.ptr, align 4
    196   %4 = load i32* %a.addr, align 4
    197   %add = add nsw i32 %3, %4
    198   %5 = load i32** @PA, align 4
    199   %6 = load i32* %i, align 4
    200   %add.ptr1 = getelementptr inbounds i32* %5, i32 %6
    201   store i32 %add, i32* %add.ptr1, align 4
    202   br label %for.inc
    203 
    204 for.inc:                                          ; preds = %for.body
    205   %7 = load i32* %i, align 4
    206   %inc = add nsw i32 %7, 1
    207   store i32 %inc, i32* %i, align 4
    208   br label %for.cond
    209 
    210 for.end:                                          ; preds = %for.cond
    211   %8 = load i32** @PA, align 4
    212   %9 = load i32* %a.addr, align 4
    213   %add.ptr2 = getelementptr inbounds i32* %8, i32 %9
    214   %10 = load i32* %add.ptr2, align 4
    215   ret i32 %10
    216 }
    217 
    218 ; /// Different objects, positive induction, multi-array
    219 ; int noAlias05 (int a) {
    220 ;   int i, N=10;
    221 ;   for (i=0; i<SIZE; i++)
    222 ;     Bar.A[N][i] = Bar.B[N][i] + a;
    223 ;   return Bar.A[N][a];
    224 ; }
    225 ; CHECK-LABEL: define i32 @noAlias05(
    226 ; CHECK: add nsw <4 x i32>
    227 ; CHECK: ret
    228 
    229 define i32 @noAlias05(i32 %a) #0 {
    230 entry:
    231   %a.addr = alloca i32, align 4
    232   %i = alloca i32, align 4
    233   %N = alloca i32, align 4
    234   store i32 %a, i32* %a.addr, align 4
    235   store i32 10, i32* %N, align 4
    236   store i32 0, i32* %i, align 4
    237   br label %for.cond
    238 
    239 for.cond:                                         ; preds = %for.inc, %entry
    240   %0 = load i32* %i, align 4
    241   %cmp = icmp slt i32 %0, 100
    242   br i1 %cmp, label %for.body, label %for.end
    243 
    244 for.body:                                         ; preds = %for.cond
    245   %1 = load i32* %i, align 4
    246   %2 = load i32* %N, align 4
    247   %arrayidx = getelementptr inbounds [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0* @Bar, i32 0, i32 2), i32 0, i32 %2
    248   %arrayidx1 = getelementptr inbounds [100 x i32]* %arrayidx, i32 0, i32 %1
    249   %3 = load i32* %arrayidx1, align 4
    250   %4 = load i32* %a.addr, align 4
    251   %add = add nsw i32 %3, %4
    252   %5 = load i32* %i, align 4
    253   %6 = load i32* %N, align 4
    254   %arrayidx2 = getelementptr inbounds [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %6
    255   %arrayidx3 = getelementptr inbounds [100 x i32]* %arrayidx2, i32 0, i32 %5
    256   store i32 %add, i32* %arrayidx3, align 4
    257   br label %for.inc
    258 
    259 for.inc:                                          ; preds = %for.body
    260   %7 = load i32* %i, align 4
    261   %inc = add nsw i32 %7, 1
    262   store i32 %inc, i32* %i, align 4
    263   br label %for.cond
    264 
    265 for.end:                                          ; preds = %for.cond
    266   %8 = load i32* %a.addr, align 4
    267   %9 = load i32* %N, align 4
    268   %arrayidx4 = getelementptr inbounds [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %9
    269   %arrayidx5 = getelementptr inbounds [100 x i32]* %arrayidx4, i32 0, i32 %8
    270   %10 = load i32* %arrayidx5, align 4
    271   ret i32 %10
    272 }
    273 
    274 ; /// Same objects, positive induction, multi-array, different sub-elements
    275 ; int noAlias06 (int a) {
    276 ;   int i, N=10;
    277 ;   for (i=0; i<SIZE; i++)
    278 ;     Bar.A[N][i] = Bar.A[N+1][i] + a;
    279 ;   return Bar.A[N][a];
    280 ; }
    281 ; CHECK-LABEL: define i32 @noAlias06(
    282 ; CHECK: add nsw <4 x i32>
    283 ; CHECK: ret
    284 
    285 define i32 @noAlias06(i32 %a) #0 {
    286 entry:
    287   %a.addr = alloca i32, align 4
    288   %i = alloca i32, align 4
    289   %N = alloca i32, align 4
    290   store i32 %a, i32* %a.addr, align 4
    291   store i32 10, i32* %N, align 4
    292   store i32 0, i32* %i, align 4
    293   br label %for.cond
    294 
    295 for.cond:                                         ; preds = %for.inc, %entry
    296   %0 = load i32* %i, align 4
    297   %cmp = icmp slt i32 %0, 100
    298   br i1 %cmp, label %for.body, label %for.end
    299 
    300 for.body:                                         ; preds = %for.cond
    301   %1 = load i32* %i, align 4
    302   %2 = load i32* %N, align 4
    303   %add = add nsw i32 %2, 1
    304   %arrayidx = getelementptr inbounds [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %add
    305   %arrayidx1 = getelementptr inbounds [100 x i32]* %arrayidx, i32 0, i32 %1
    306   %3 = load i32* %arrayidx1, align 4
    307   %4 = load i32* %a.addr, align 4
    308   %add2 = add nsw i32 %3, %4
    309   %5 = load i32* %i, align 4
    310   %6 = load i32* %N, align 4
    311   %arrayidx3 = getelementptr inbounds [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %6
    312   %arrayidx4 = getelementptr inbounds [100 x i32]* %arrayidx3, i32 0, i32 %5
    313   store i32 %add2, i32* %arrayidx4, align 4
    314   br label %for.inc
    315 
    316 for.inc:                                          ; preds = %for.body
    317   %7 = load i32* %i, align 4
    318   %inc = add nsw i32 %7, 1
    319   store i32 %inc, i32* %i, align 4
    320   br label %for.cond
    321 
    322 for.end:                                          ; preds = %for.cond
    323   %8 = load i32* %a.addr, align 4
    324   %9 = load i32* %N, align 4
    325   %arrayidx5 = getelementptr inbounds [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %9
    326   %arrayidx6 = getelementptr inbounds [100 x i32]* %arrayidx5, i32 0, i32 %8
    327   %10 = load i32* %arrayidx6, align 4
    328   ret i32 %10
    329 }
    330 
    331 ; /// Different objects, negative induction, constant distance
    332 ; int noAlias07 (int a) {
    333 ;   int i;
    334 ;   for (i=0; i<SIZE; i++)
    335 ;     Foo.A[SIZE-i-1] = Foo.B[SIZE-i-1] + a;
    336 ;   return Foo.A[a];
    337 ; }
    338 ; CHECK-LABEL: define i32 @noAlias07(
    339 ; CHECK: sub nsw <4 x i32>
    340 ; CHECK: ret
    341 
    342 define i32 @noAlias07(i32 %a) #0 {
    343 entry:
    344   %a.addr = alloca i32, align 4
    345   %i = alloca i32, align 4
    346   store i32 %a, i32* %a.addr, align 4
    347   store i32 0, i32* %i, align 4
    348   br label %for.cond
    349 
    350 for.cond:                                         ; preds = %for.inc, %entry
    351   %0 = load i32* %i, align 4
    352   %cmp = icmp slt i32 %0, 100
    353   br i1 %cmp, label %for.body, label %for.end
    354 
    355 for.body:                                         ; preds = %for.cond
    356   %1 = load i32* %i, align 4
    357   %sub = sub nsw i32 100, %1
    358   %sub1 = sub nsw i32 %sub, 1
    359   %arrayidx = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %sub1
    360   %2 = load i32* %arrayidx, align 4
    361   %3 = load i32* %a.addr, align 4
    362   %add = add nsw i32 %2, %3
    363   %4 = load i32* %i, align 4
    364   %sub2 = sub nsw i32 100, %4
    365   %sub3 = sub nsw i32 %sub2, 1
    366   %arrayidx4 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %sub3
    367   store i32 %add, i32* %arrayidx4, align 4
    368   br label %for.inc
    369 
    370 for.inc:                                          ; preds = %for.body
    371   %5 = load i32* %i, align 4
    372   %inc = add nsw i32 %5, 1
    373   store i32 %inc, i32* %i, align 4
    374   br label %for.cond
    375 
    376 for.end:                                          ; preds = %for.cond
    377   %6 = load i32* %a.addr, align 4
    378   %arrayidx5 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
    379   %7 = load i32* %arrayidx5, align 4
    380   ret i32 %7
    381 }
    382 
    383 ; /// Different objects, negative induction, shortening slide
    384 ; int noAlias08 (int a) {
    385 ;   int i;
    386 ;   for (i=0; i<SIZE-10; i++)
    387 ;     Foo.A[SIZE-i-1] = Foo.B[SIZE-i-10] + a;
    388 ;   return Foo.A[a];
    389 ; }
    390 ; CHECK-LABEL: define i32 @noAlias08(
    391 ; CHECK: sub nsw <4 x i32>
    392 ; CHECK: ret
    393 
    394 define i32 @noAlias08(i32 %a) #0 {
    395 entry:
    396   %a.addr = alloca i32, align 4
    397   %i = alloca i32, align 4
    398   store i32 %a, i32* %a.addr, align 4
    399   store i32 0, i32* %i, align 4
    400   br label %for.cond
    401 
    402 for.cond:                                         ; preds = %for.inc, %entry
    403   %0 = load i32* %i, align 4
    404   %cmp = icmp slt i32 %0, 90
    405   br i1 %cmp, label %for.body, label %for.end
    406 
    407 for.body:                                         ; preds = %for.cond
    408   %1 = load i32* %i, align 4
    409   %sub = sub nsw i32 100, %1
    410   %sub1 = sub nsw i32 %sub, 10
    411   %arrayidx = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %sub1
    412   %2 = load i32* %arrayidx, align 4
    413   %3 = load i32* %a.addr, align 4
    414   %add = add nsw i32 %2, %3
    415   %4 = load i32* %i, align 4
    416   %sub2 = sub nsw i32 100, %4
    417   %sub3 = sub nsw i32 %sub2, 1
    418   %arrayidx4 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %sub3
    419   store i32 %add, i32* %arrayidx4, align 4
    420   br label %for.inc
    421 
    422 for.inc:                                          ; preds = %for.body
    423   %5 = load i32* %i, align 4
    424   %inc = add nsw i32 %5, 1
    425   store i32 %inc, i32* %i, align 4
    426   br label %for.cond
    427 
    428 for.end:                                          ; preds = %for.cond
    429   %6 = load i32* %a.addr, align 4
    430   %arrayidx5 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
    431   %7 = load i32* %arrayidx5, align 4
    432   ret i32 %7
    433 }
    434 
    435 ; /// Different objects, negative induction, widening slide
    436 ; int noAlias09 (int a) {
    437 ;   int i;
    438 ;   for (i=0; i<SIZE; i++)
    439 ;     Foo.A[SIZE-i-10] = Foo.B[SIZE-i-1] + a;
    440 ;   return Foo.A[a];
    441 ; }
    442 ; CHECK-LABEL: define i32 @noAlias09(
    443 ; CHECK: sub nsw <4 x i32>
    444 ; CHECK: ret
    445 
    446 define i32 @noAlias09(i32 %a) #0 {
    447 entry:
    448   %a.addr = alloca i32, align 4
    449   %i = alloca i32, align 4
    450   store i32 %a, i32* %a.addr, align 4
    451   store i32 0, i32* %i, align 4
    452   br label %for.cond
    453 
    454 for.cond:                                         ; preds = %for.inc, %entry
    455   %0 = load i32* %i, align 4
    456   %cmp = icmp slt i32 %0, 100
    457   br i1 %cmp, label %for.body, label %for.end
    458 
    459 for.body:                                         ; preds = %for.cond
    460   %1 = load i32* %i, align 4
    461   %sub = sub nsw i32 100, %1
    462   %sub1 = sub nsw i32 %sub, 1
    463   %arrayidx = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %sub1
    464   %2 = load i32* %arrayidx, align 4
    465   %3 = load i32* %a.addr, align 4
    466   %add = add nsw i32 %2, %3
    467   %4 = load i32* %i, align 4
    468   %sub2 = sub nsw i32 100, %4
    469   %sub3 = sub nsw i32 %sub2, 10
    470   %arrayidx4 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %sub3
    471   store i32 %add, i32* %arrayidx4, align 4
    472   br label %for.inc
    473 
    474 for.inc:                                          ; preds = %for.body
    475   %5 = load i32* %i, align 4
    476   %inc = add nsw i32 %5, 1
    477   store i32 %inc, i32* %i, align 4
    478   br label %for.cond
    479 
    480 for.end:                                          ; preds = %for.cond
    481   %6 = load i32* %a.addr, align 4
    482   %arrayidx5 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
    483   %7 = load i32* %arrayidx5, align 4
    484   ret i32 %7
    485 }
    486 
    487 ; /// Pointer access, negative stride, run-time check added
    488 ; int noAlias10 (int a) {
    489 ;   int i;
    490 ;   for (i=0; i<SIZE; i++)
    491 ;     *(PA+SIZE-i-1) = *(PB+SIZE-i-1) + a;
    492 ;   return *(PA+a);
    493 ; }
    494 ; CHECK-LABEL: define i32 @noAlias10(
    495 ; CHECK-NOT: sub nsw <4 x i32>
    496 ; CHECK: ret
    497 ;
    498 ; TODO: This test vectorizes (with run-time check) on real targets with -O3)
    499 ; Check why it's not being vectorized even when forcing vectorization
    500 
    501 define i32 @noAlias10(i32 %a) #0 {
    502 entry:
    503   %a.addr = alloca i32, align 4
    504   %i = alloca i32, align 4
    505   store i32 %a, i32* %a.addr, align 4
    506   store i32 0, i32* %i, align 4
    507   br label %for.cond
    508 
    509 for.cond:                                         ; preds = %for.inc, %entry
    510   %0 = load i32* %i, align 4
    511   %cmp = icmp slt i32 %0, 100
    512   br i1 %cmp, label %for.body, label %for.end
    513 
    514 for.body:                                         ; preds = %for.cond
    515   %1 = load i32** @PB, align 4
    516   %add.ptr = getelementptr inbounds i32* %1, i32 100
    517   %2 = load i32* %i, align 4
    518   %idx.neg = sub i32 0, %2
    519   %add.ptr1 = getelementptr inbounds i32* %add.ptr, i32 %idx.neg
    520   %add.ptr2 = getelementptr inbounds i32* %add.ptr1, i32 -1
    521   %3 = load i32* %add.ptr2, align 4
    522   %4 = load i32* %a.addr, align 4
    523   %add = add nsw i32 %3, %4
    524   %5 = load i32** @PA, align 4
    525   %add.ptr3 = getelementptr inbounds i32* %5, i32 100
    526   %6 = load i32* %i, align 4
    527   %idx.neg4 = sub i32 0, %6
    528   %add.ptr5 = getelementptr inbounds i32* %add.ptr3, i32 %idx.neg4
    529   %add.ptr6 = getelementptr inbounds i32* %add.ptr5, i32 -1
    530   store i32 %add, i32* %add.ptr6, align 4
    531   br label %for.inc
    532 
    533 for.inc:                                          ; preds = %for.body
    534   %7 = load i32* %i, align 4
    535   %inc = add nsw i32 %7, 1
    536   store i32 %inc, i32* %i, align 4
    537   br label %for.cond
    538 
    539 for.end:                                          ; preds = %for.cond
    540   %8 = load i32** @PA, align 4
    541   %9 = load i32* %a.addr, align 4
    542   %add.ptr7 = getelementptr inbounds i32* %8, i32 %9
    543   %10 = load i32* %add.ptr7, align 4
    544   ret i32 %10
    545 }
    546 
    547 ; /// Different objects, negative induction, multi-array
    548 ; int noAlias11 (int a) {
    549 ;   int i, N=10;
    550 ;   for (i=0; i<SIZE; i++)
    551 ;     Bar.A[N][SIZE-i-1] = Bar.B[N][SIZE-i-1] + a;
    552 ;   return Bar.A[N][a];
    553 ; }
    554 ; CHECK-LABEL: define i32 @noAlias11(
    555 ; CHECK: sub nsw <4 x i32>
    556 ; CHECK: ret
    557 
    558 define i32 @noAlias11(i32 %a) #0 {
    559 entry:
    560   %a.addr = alloca i32, align 4
    561   %i = alloca i32, align 4
    562   %N = alloca i32, align 4
    563   store i32 %a, i32* %a.addr, align 4
    564   store i32 10, i32* %N, align 4
    565   store i32 0, i32* %i, align 4
    566   br label %for.cond
    567 
    568 for.cond:                                         ; preds = %for.inc, %entry
    569   %0 = load i32* %i, align 4
    570   %cmp = icmp slt i32 %0, 100
    571   br i1 %cmp, label %for.body, label %for.end
    572 
    573 for.body:                                         ; preds = %for.cond
    574   %1 = load i32* %i, align 4
    575   %sub = sub nsw i32 100, %1
    576   %sub1 = sub nsw i32 %sub, 1
    577   %2 = load i32* %N, align 4
    578   %arrayidx = getelementptr inbounds [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0* @Bar, i32 0, i32 2), i32 0, i32 %2
    579   %arrayidx2 = getelementptr inbounds [100 x i32]* %arrayidx, i32 0, i32 %sub1
    580   %3 = load i32* %arrayidx2, align 4
    581   %4 = load i32* %a.addr, align 4
    582   %add = add nsw i32 %3, %4
    583   %5 = load i32* %i, align 4
    584   %sub3 = sub nsw i32 100, %5
    585   %sub4 = sub nsw i32 %sub3, 1
    586   %6 = load i32* %N, align 4
    587   %arrayidx5 = getelementptr inbounds [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %6
    588   %arrayidx6 = getelementptr inbounds [100 x i32]* %arrayidx5, i32 0, i32 %sub4
    589   store i32 %add, i32* %arrayidx6, align 4
    590   br label %for.inc
    591 
    592 for.inc:                                          ; preds = %for.body
    593   %7 = load i32* %i, align 4
    594   %inc = add nsw i32 %7, 1
    595   store i32 %inc, i32* %i, align 4
    596   br label %for.cond
    597 
    598 for.end:                                          ; preds = %for.cond
    599   %8 = load i32* %a.addr, align 4
    600   %9 = load i32* %N, align 4
    601   %arrayidx7 = getelementptr inbounds [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %9
    602   %arrayidx8 = getelementptr inbounds [100 x i32]* %arrayidx7, i32 0, i32 %8
    603   %10 = load i32* %arrayidx8, align 4
    604   ret i32 %10
    605 }
    606 
    607 ; /// Same objects, negative induction, multi-array, different sub-elements
    608 ; int noAlias12 (int a) {
    609 ;   int i, N=10;
    610 ;   for (i=0; i<SIZE; i++)
    611 ;     Bar.A[N][SIZE-i-1] = Bar.A[N+1][SIZE-i-1] + a;
    612 ;   return Bar.A[N][a];
    613 ; }
    614 ; CHECK-LABEL: define i32 @noAlias12(
    615 ; CHECK: sub nsw <4 x i32>
    616 ; CHECK: ret
    617 
    618 define i32 @noAlias12(i32 %a) #0 {
    619 entry:
    620   %a.addr = alloca i32, align 4
    621   %i = alloca i32, align 4
    622   %N = alloca i32, align 4
    623   store i32 %a, i32* %a.addr, align 4
    624   store i32 10, i32* %N, align 4
    625   store i32 0, i32* %i, align 4
    626   br label %for.cond
    627 
    628 for.cond:                                         ; preds = %for.inc, %entry
    629   %0 = load i32* %i, align 4
    630   %cmp = icmp slt i32 %0, 100
    631   br i1 %cmp, label %for.body, label %for.end
    632 
    633 for.body:                                         ; preds = %for.cond
    634   %1 = load i32* %i, align 4
    635   %sub = sub nsw i32 100, %1
    636   %sub1 = sub nsw i32 %sub, 1
    637   %2 = load i32* %N, align 4
    638   %add = add nsw i32 %2, 1
    639   %arrayidx = getelementptr inbounds [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %add
    640   %arrayidx2 = getelementptr inbounds [100 x i32]* %arrayidx, i32 0, i32 %sub1
    641   %3 = load i32* %arrayidx2, align 4
    642   %4 = load i32* %a.addr, align 4
    643   %add3 = add nsw i32 %3, %4
    644   %5 = load i32* %i, align 4
    645   %sub4 = sub nsw i32 100, %5
    646   %sub5 = sub nsw i32 %sub4, 1
    647   %6 = load i32* %N, align 4
    648   %arrayidx6 = getelementptr inbounds [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %6
    649   %arrayidx7 = getelementptr inbounds [100 x i32]* %arrayidx6, i32 0, i32 %sub5
    650   store i32 %add3, i32* %arrayidx7, align 4
    651   br label %for.inc
    652 
    653 for.inc:                                          ; preds = %for.body
    654   %7 = load i32* %i, align 4
    655   %inc = add nsw i32 %7, 1
    656   store i32 %inc, i32* %i, align 4
    657   br label %for.cond
    658 
    659 for.end:                                          ; preds = %for.cond
    660   %8 = load i32* %a.addr, align 4
    661   %9 = load i32* %N, align 4
    662   %arrayidx8 = getelementptr inbounds [100 x [100 x i32]]* getelementptr inbounds (%struct.anon.0* @Bar, i32 0, i32 0), i32 0, i32 %9
    663   %arrayidx9 = getelementptr inbounds [100 x i32]* %arrayidx8, i32 0, i32 %8
    664   %10 = load i32* %arrayidx9, align 4
    665   ret i32 %10
    666 }
    667 
    668 ; /// Same objects, positive induction, constant distance, just enough for vector size
    669 ; int noAlias13 (int a) {
    670 ;   int i;
    671 ;   for (i=0; i<SIZE; i++)
    672 ;     Foo.A[i] = Foo.A[i+4] + a;
    673 ;   return Foo.A[a];
    674 ; }
    675 ; CHECK-LABEL: define i32 @noAlias13(
    676 ; CHECK: add nsw <4 x i32>
    677 ; CHECK: ret
    678 
    679 define i32 @noAlias13(i32 %a) #0 {
    680 entry:
    681   %a.addr = alloca i32, align 4
    682   %i = alloca i32, align 4
    683   store i32 %a, i32* %a.addr, align 4
    684   store i32 0, i32* %i, align 4
    685   br label %for.cond
    686 
    687 for.cond:                                         ; preds = %for.inc, %entry
    688   %0 = load i32* %i, align 4
    689   %cmp = icmp slt i32 %0, 100
    690   br i1 %cmp, label %for.body, label %for.end
    691 
    692 for.body:                                         ; preds = %for.cond
    693   %1 = load i32* %i, align 4
    694   %add = add nsw i32 %1, 4
    695   %arrayidx = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %add
    696   %2 = load i32* %arrayidx, align 4
    697   %3 = load i32* %a.addr, align 4
    698   %add1 = add nsw i32 %2, %3
    699   %4 = load i32* %i, align 4
    700   %arrayidx2 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %4
    701   store i32 %add1, i32* %arrayidx2, align 4
    702   br label %for.inc
    703 
    704 for.inc:                                          ; preds = %for.body
    705   %5 = load i32* %i, align 4
    706   %inc = add nsw i32 %5, 1
    707   store i32 %inc, i32* %i, align 4
    708   br label %for.cond
    709 
    710 for.end:                                          ; preds = %for.cond
    711   %6 = load i32* %a.addr, align 4
    712   %arrayidx3 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
    713   %7 = load i32* %arrayidx3, align 4
    714   ret i32 %7
    715 }
    716 
    717 ; /// Same objects, negative induction, constant distance, just enough for vector size
    718 ; int noAlias14 (int a) {
    719 ;   int i;
    720 ;   for (i=0; i<SIZE; i++)
    721 ;     Foo.A[SIZE-i-1] = Foo.A[SIZE-i-5] + a;
    722 ;   return Foo.A[a];
    723 ; }
    724 ; CHECK-LABEL: define i32 @noAlias14(
    725 ; CHECK: sub nsw <4 x i32>
    726 ; CHECK: ret
    727 
    728 define i32 @noAlias14(i32 %a) #0 {
    729 entry:
    730   %a.addr = alloca i32, align 4
    731   %i = alloca i32, align 4
    732   store i32 %a, i32* %a.addr, align 4
    733   store i32 0, i32* %i, align 4
    734   br label %for.cond
    735 
    736 for.cond:                                         ; preds = %for.inc, %entry
    737   %0 = load i32* %i, align 4
    738   %cmp = icmp slt i32 %0, 100
    739   br i1 %cmp, label %for.body, label %for.end
    740 
    741 for.body:                                         ; preds = %for.cond
    742   %1 = load i32* %i, align 4
    743   %sub = sub nsw i32 100, %1
    744   %sub1 = sub nsw i32 %sub, 5
    745   %arrayidx = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %sub1
    746   %2 = load i32* %arrayidx, align 4
    747   %3 = load i32* %a.addr, align 4
    748   %add = add nsw i32 %2, %3
    749   %4 = load i32* %i, align 4
    750   %sub2 = sub nsw i32 100, %4
    751   %sub3 = sub nsw i32 %sub2, 1
    752   %arrayidx4 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %sub3
    753   store i32 %add, i32* %arrayidx4, align 4
    754   br label %for.inc
    755 
    756 for.inc:                                          ; preds = %for.body
    757   %5 = load i32* %i, align 4
    758   %inc = add nsw i32 %5, 1
    759   store i32 %inc, i32* %i, align 4
    760   br label %for.cond
    761 
    762 for.end:                                          ; preds = %for.cond
    763   %6 = load i32* %a.addr, align 4
    764   %arrayidx5 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
    765   %7 = load i32* %arrayidx5, align 4
    766   ret i32 %7
    767 }
    768 
    769 
    770 ;; === Now, the tests that we could vectorize with induction changes or run-time checks ===
    771 
    772 
    773 ; /// Different objects, swapped induction, alias at the end
    774 ; int mayAlias01 (int a) {
    775 ;   int i;
    776 ;   for (i=0; i<SIZE; i++)
    777 ;     Foo.A[i] = Foo.B[SIZE-i-1] + a;
    778 ;   return Foo.A[a];
    779 ; }
    780 ; CHECK-LABEL: define i32 @mayAlias01(
    781 ; CHECK-NOT: add nsw <4 x i32>
    782 ; CHECK: ret
    783 
    784 define i32 @mayAlias01(i32 %a) nounwind {
    785 entry:
    786   %a.addr = alloca i32, align 4
    787   %i = alloca i32, align 4
    788   store i32 %a, i32* %a.addr, align 4
    789   store i32 0, i32* %i, align 4
    790   br label %for.cond
    791 
    792 for.cond:                                         ; preds = %for.inc, %entry
    793   %0 = load i32* %i, align 4
    794   %cmp = icmp slt i32 %0, 100
    795   br i1 %cmp, label %for.body, label %for.end
    796 
    797 for.body:                                         ; preds = %for.cond
    798   %1 = load i32* %i, align 4
    799   %sub = sub nsw i32 100, %1
    800   %sub1 = sub nsw i32 %sub, 1
    801   %arrayidx = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %sub1
    802   %2 = load i32* %arrayidx, align 4
    803   %3 = load i32* %a.addr, align 4
    804   %add = add nsw i32 %2, %3
    805   %4 = load i32* %i, align 4
    806   %arrayidx2 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %4
    807   store i32 %add, i32* %arrayidx2, align 4
    808   br label %for.inc
    809 
    810 for.inc:                                          ; preds = %for.body
    811   %5 = load i32* %i, align 4
    812   %inc = add nsw i32 %5, 1
    813   store i32 %inc, i32* %i, align 4
    814   br label %for.cond
    815 
    816 for.end:                                          ; preds = %for.cond
    817   %6 = load i32* %a.addr, align 4
    818   %arrayidx3 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
    819   %7 = load i32* %arrayidx3, align 4
    820   ret i32 %7
    821 }
    822 
    823 ; /// Different objects, swapped induction, alias at the beginning
    824 ; int mayAlias02 (int a) {
    825 ;   int i;
    826 ;   for (i=0; i<SIZE; i++)
    827 ;     Foo.A[SIZE-i-1] = Foo.B[i] + a;
    828 ;   return Foo.A[a];
    829 ; }
    830 ; CHECK-LABEL: define i32 @mayAlias02(
    831 ; CHECK-NOT: add nsw <4 x i32>
    832 ; CHECK: ret
    833 
    834 define i32 @mayAlias02(i32 %a) nounwind {
    835 entry:
    836   %a.addr = alloca i32, align 4
    837   %i = alloca i32, align 4
    838   store i32 %a, i32* %a.addr, align 4
    839   store i32 0, i32* %i, align 4
    840   br label %for.cond
    841 
    842 for.cond:                                         ; preds = %for.inc, %entry
    843   %0 = load i32* %i, align 4
    844   %cmp = icmp slt i32 %0, 100
    845   br i1 %cmp, label %for.body, label %for.end
    846 
    847 for.body:                                         ; preds = %for.cond
    848   %1 = load i32* %i, align 4
    849   %arrayidx = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %1
    850   %2 = load i32* %arrayidx, align 4
    851   %3 = load i32* %a.addr, align 4
    852   %add = add nsw i32 %2, %3
    853   %4 = load i32* %i, align 4
    854   %sub = sub nsw i32 100, %4
    855   %sub1 = sub nsw i32 %sub, 1
    856   %arrayidx2 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %sub1
    857   store i32 %add, i32* %arrayidx2, align 4
    858   br label %for.inc
    859 
    860 for.inc:                                          ; preds = %for.body
    861   %5 = load i32* %i, align 4
    862   %inc = add nsw i32 %5, 1
    863   store i32 %inc, i32* %i, align 4
    864   br label %for.cond
    865 
    866 for.end:                                          ; preds = %for.cond
    867   %6 = load i32* %a.addr, align 4
    868   %arrayidx3 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
    869   %7 = load i32* %arrayidx3, align 4
    870   ret i32 %7
    871 }
    872 
    873 ; /// Pointer access, run-time check added
    874 ; int mayAlias03 (int a) {
    875 ;   int i;
    876 ;   for (i=0; i<SIZE; i++)
    877 ;     *(PA+i) = *(PB+SIZE-i-1) + a;
    878 ;   return *(PA+a);
    879 ; }
    880 ; CHECK-LABEL: define i32 @mayAlias03(
    881 ; CHECK-NOT: add nsw <4 x i32>
    882 ; CHECK: ret
    883 
    884 define i32 @mayAlias03(i32 %a) nounwind {
    885 entry:
    886   %a.addr = alloca i32, align 4
    887   %i = alloca i32, align 4
    888   store i32 %a, i32* %a.addr, align 4
    889   store i32 0, i32* %i, align 4
    890   br label %for.cond
    891 
    892 for.cond:                                         ; preds = %for.inc, %entry
    893   %0 = load i32* %i, align 4
    894   %cmp = icmp slt i32 %0, 100
    895   br i1 %cmp, label %for.body, label %for.end
    896 
    897 for.body:                                         ; preds = %for.cond
    898   %1 = load i32** @PB, align 4
    899   %add.ptr = getelementptr inbounds i32* %1, i32 100
    900   %2 = load i32* %i, align 4
    901   %idx.neg = sub i32 0, %2
    902   %add.ptr1 = getelementptr inbounds i32* %add.ptr, i32 %idx.neg
    903   %add.ptr2 = getelementptr inbounds i32* %add.ptr1, i32 -1
    904   %3 = load i32* %add.ptr2, align 4
    905   %4 = load i32* %a.addr, align 4
    906   %add = add nsw i32 %3, %4
    907   %5 = load i32** @PA, align 4
    908   %6 = load i32* %i, align 4
    909   %add.ptr3 = getelementptr inbounds i32* %5, i32 %6
    910   store i32 %add, i32* %add.ptr3, align 4
    911   br label %for.inc
    912 
    913 for.inc:                                          ; preds = %for.body
    914   %7 = load i32* %i, align 4
    915   %inc = add nsw i32 %7, 1
    916   store i32 %inc, i32* %i, align 4
    917   br label %for.cond
    918 
    919 for.end:                                          ; preds = %for.cond
    920   %8 = load i32** @PA, align 4
    921   %9 = load i32* %a.addr, align 4
    922   %add.ptr4 = getelementptr inbounds i32* %8, i32 %9
    923   %10 = load i32* %add.ptr4, align 4
    924   ret i32 %10
    925 }
    926 
    927 
    928 ;; === Finally, the tests that should only vectorize with care (or if we ignore undefined behaviour at all) ===
    929 
    930 
    931 ; int mustAlias01 (int a) {
    932 ;   int i;
    933 ;   for (i=0; i<SIZE; i++)
    934 ;     Foo.A[i+10] = Foo.B[SIZE-i-1] + a;
    935 ;   return Foo.A[a];
    936 ; }
    937 ; CHECK-LABEL: define i32 @mustAlias01(
    938 ; CHECK-NOT: add nsw <4 x i32>
    939 ; CHECK: ret
    940 
    941 define i32 @mustAlias01(i32 %a) nounwind {
    942 entry:
    943   %a.addr = alloca i32, align 4
    944   %i = alloca i32, align 4
    945   store i32 %a, i32* %a.addr, align 4
    946   store i32 0, i32* %i, align 4
    947   br label %for.cond
    948 
    949 for.cond:                                         ; preds = %for.inc, %entry
    950   %0 = load i32* %i, align 4
    951   %cmp = icmp slt i32 %0, 100
    952   br i1 %cmp, label %for.body, label %for.end
    953 
    954 for.body:                                         ; preds = %for.cond
    955   %1 = load i32* %i, align 4
    956   %sub = sub nsw i32 100, %1
    957   %sub1 = sub nsw i32 %sub, 1
    958   %arrayidx = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %sub1
    959   %2 = load i32* %arrayidx, align 4
    960   %3 = load i32* %a.addr, align 4
    961   %add = add nsw i32 %2, %3
    962   %4 = load i32* %i, align 4
    963   %add2 = add nsw i32 %4, 10
    964   %arrayidx3 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %add2
    965   store i32 %add, i32* %arrayidx3, align 4
    966   br label %for.inc
    967 
    968 for.inc:                                          ; preds = %for.body
    969   %5 = load i32* %i, align 4
    970   %inc = add nsw i32 %5, 1
    971   store i32 %inc, i32* %i, align 4
    972   br label %for.cond
    973 
    974 for.end:                                          ; preds = %for.cond
    975   %6 = load i32* %a.addr, align 4
    976   %arrayidx4 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
    977   %7 = load i32* %arrayidx4, align 4
    978   ret i32 %7
    979 }
    980 
    981 ; int mustAlias02 (int a) {
    982 ;   int i;
    983 ;   for (i=0; i<SIZE; i++)
    984 ;     Foo.A[i] = Foo.B[SIZE-i-10] + a;
    985 ;   return Foo.A[a];
    986 ; }
    987 ; CHECK-LABEL: define i32 @mustAlias02(
    988 ; CHECK-NOT: add nsw <4 x i32>
    989 ; CHECK: ret
    990 
    991 define i32 @mustAlias02(i32 %a) nounwind {
    992 entry:
    993   %a.addr = alloca i32, align 4
    994   %i = alloca i32, align 4
    995   store i32 %a, i32* %a.addr, align 4
    996   store i32 0, i32* %i, align 4
    997   br label %for.cond
    998 
    999 for.cond:                                         ; preds = %for.inc, %entry
   1000   %0 = load i32* %i, align 4
   1001   %cmp = icmp slt i32 %0, 100
   1002   br i1 %cmp, label %for.body, label %for.end
   1003 
   1004 for.body:                                         ; preds = %for.cond
   1005   %1 = load i32* %i, align 4
   1006   %sub = sub nsw i32 100, %1
   1007   %sub1 = sub nsw i32 %sub, 10
   1008   %arrayidx = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %sub1
   1009   %2 = load i32* %arrayidx, align 4
   1010   %3 = load i32* %a.addr, align 4
   1011   %add = add nsw i32 %2, %3
   1012   %4 = load i32* %i, align 4
   1013   %arrayidx2 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %4
   1014   store i32 %add, i32* %arrayidx2, align 4
   1015   br label %for.inc
   1016 
   1017 for.inc:                                          ; preds = %for.body
   1018   %5 = load i32* %i, align 4
   1019   %inc = add nsw i32 %5, 1
   1020   store i32 %inc, i32* %i, align 4
   1021   br label %for.cond
   1022 
   1023 for.end:                                          ; preds = %for.cond
   1024   %6 = load i32* %a.addr, align 4
   1025   %arrayidx3 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
   1026   %7 = load i32* %arrayidx3, align 4
   1027   ret i32 %7
   1028 }
   1029 
   1030 ; int mustAlias03 (int a) {
   1031 ;   int i;
   1032 ;   for (i=0; i<SIZE; i++)
   1033 ;     Foo.A[i+10] = Foo.B[SIZE-i-10] + a;
   1034 ;   return Foo.A[a];
   1035 ; }
   1036 ; CHECK-LABEL: define i32 @mustAlias03(
   1037 ; CHECK-NOT: add nsw <4 x i32>
   1038 ; CHECK: ret
   1039 
   1040 define i32 @mustAlias03(i32 %a) nounwind {
   1041 entry:
   1042   %a.addr = alloca i32, align 4
   1043   %i = alloca i32, align 4
   1044   store i32 %a, i32* %a.addr, align 4
   1045   store i32 0, i32* %i, align 4
   1046   br label %for.cond
   1047 
   1048 for.cond:                                         ; preds = %for.inc, %entry
   1049   %0 = load i32* %i, align 4
   1050   %cmp = icmp slt i32 %0, 100
   1051   br i1 %cmp, label %for.body, label %for.end
   1052 
   1053 for.body:                                         ; preds = %for.cond
   1054   %1 = load i32* %i, align 4
   1055   %sub = sub nsw i32 100, %1
   1056   %sub1 = sub nsw i32 %sub, 10
   1057   %arrayidx = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 2), i32 0, i32 %sub1
   1058   %2 = load i32* %arrayidx, align 4
   1059   %3 = load i32* %a.addr, align 4
   1060   %add = add nsw i32 %2, %3
   1061   %4 = load i32* %i, align 4
   1062   %add2 = add nsw i32 %4, 10
   1063   %arrayidx3 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %add2
   1064   store i32 %add, i32* %arrayidx3, align 4
   1065   br label %for.inc
   1066 
   1067 for.inc:                                          ; preds = %for.body
   1068   %5 = load i32* %i, align 4
   1069   %inc = add nsw i32 %5, 1
   1070   store i32 %inc, i32* %i, align 4
   1071   br label %for.cond
   1072 
   1073 for.end:                                          ; preds = %for.cond
   1074   %6 = load i32* %a.addr, align 4
   1075   %arrayidx4 = getelementptr inbounds [100 x i32]* getelementptr inbounds (%struct.anon* @Foo, i32 0, i32 0), i32 0, i32 %6
   1076   %7 = load i32* %arrayidx4, align 4
   1077   ret i32 %7
   1078 }
   1079