Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 -Wno-unused-value -emit-llvm %s -o - | FileCheck %s
      2 
      3 // CHECK: @i = global [[INT:i[0-9]+]] 0
      4 volatile int i, j, k;
      5 volatile int ar[5];
      6 volatile char c;
      7 // CHECK: @ci = global [[CINT:.*]] zeroinitializer
      8 volatile _Complex int ci;
      9 volatile struct S {
     10 #ifdef __cplusplus
     11   void operator =(volatile struct S&o) volatile;
     12 #endif
     13   int i;
     14 } a, b;
     15 
     16 //void operator =(volatile struct S&o1, volatile struct S&o2) volatile;
     17 int printf(const char *, ...);
     18 
     19 
     20 // CHECK: define void @{{.*}}test
     21 void test() {
     22 
     23   asm("nop"); // CHECK: call void asm
     24 
     25   // should not load
     26   i;
     27 
     28   (float)(ci);
     29   // CHECK-NEXT: load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
     30   // CHECK-NEXT: load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
     31   // CHECK-NEXT: sitofp [[INT]]
     32 
     33   // These are not uses in C++:
     34   //   [expr.static.cast]p6:
     35   //     The lvalue-to-rvalue . . . conversions are not applied to the expression.
     36   (void)ci;
     37   (void)a;
     38 
     39   (void)(ci=ci);
     40   // CHECK-NEXT: [[R:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
     41   // CHECK-NEXT: [[I:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
     42   // CHECK-NEXT: store volatile [[INT]] [[R]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
     43   // CHECK-NEXT: store volatile [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
     44 
     45   (void)(i=j);
     46   // CHECK-NEXT: [[T:%.*]] = load volatile [[INT]]* @j
     47   // CHECK-NEXT: store volatile [[INT]] [[T]], [[INT]]* @i
     48 
     49   ci+=ci;
     50   // CHECK-NEXT: [[R1:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
     51   // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
     52   // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
     53   // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
     54   // Not sure why they're ordered this way.
     55   // CHECK-NEXT: [[R:%.*]] = add [[INT]] [[R2]], [[R1]]
     56   // CHECK-NEXT: [[I:%.*]] = add [[INT]] [[I2]], [[I1]]
     57   // CHECK-NEXT: store volatile [[INT]] [[R]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
     58   // CHECK-NEXT: store volatile [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
     59 
     60   // Note that C++ requires an extra load volatile over C from the LHS of the '+'.
     61   (ci += ci) + ci;
     62   // CHECK-NEXT: [[R1:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
     63   // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
     64   // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
     65   // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
     66   // CHECK-NEXT: [[R:%.*]] = add [[INT]] [[R2]], [[R1]]
     67   // CHECK-NEXT: [[I:%.*]] = add [[INT]] [[I2]], [[I1]]
     68   // CHECK-NEXT: store volatile [[INT]] [[R]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
     69   // CHECK-NEXT: store volatile [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
     70   // CHECK-NEXT: [[R1:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
     71   // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
     72   // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
     73   // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
     74   // These additions can be elided.
     75   // CHECK-NEXT: add [[INT]] [[R1]], [[R2]]
     76   // CHECK-NEXT: add [[INT]] [[I1]], [[I2]]
     77 
     78   asm("nop"); // CHECK-NEXT: call void asm
     79 
     80   // Extra load volatile in C++.
     81   (i += j) + k;
     82   // CHECK-NEXT: load volatile
     83   // CHECK-NEXT: load volatile
     84   // CHECK-NEXT: add nsw [[INT]]
     85   // CHECK-NEXT: store volatile
     86   // CHECK-NEXT: load volatile
     87   // CHECK-NEXT: load volatile
     88   // CHECK-NEXT: add nsw [[INT]]
     89 
     90   asm("nop"); // CHECK-NEXT: call void asm
     91 
     92   // Extra load volatile in C++.
     93   (i += j) + 1;
     94   // CHECK-NEXT: load volatile
     95   // CHECK-NEXT: load volatile
     96   // CHECK-NEXT: add nsw [[INT]]
     97   // CHECK-NEXT: store volatile
     98   // CHECK-NEXT: load volatile
     99   // CHECK-NEXT: add nsw [[INT]]
    100 
    101   asm("nop"); // CHECK-NEXT: call void asm
    102 
    103   ci+ci;
    104   // CHECK-NEXT: load volatile
    105   // CHECK-NEXT: load volatile
    106   // CHECK-NEXT: load volatile
    107   // CHECK-NEXT: load volatile
    108   // CHECK-NEXT: add [[INT]]
    109   // CHECK-NEXT: add [[INT]]
    110 
    111   __real i;
    112 
    113   +ci;
    114   // CHECK-NEXT: load volatile
    115   // CHECK-NEXT: load volatile
    116 
    117   asm("nop"); // CHECK-NEXT: call void asm
    118 
    119   (void)(i=i);
    120   // CHECK-NEXT: load volatile
    121   // CHECK-NEXT: store volatile
    122 
    123   (float)(i=i);
    124   // CHECK-NEXT: load volatile
    125   // CHECK-NEXT: store volatile
    126   // CHECK-NEXT: load volatile
    127   // CHECK-NEXT: sitofp
    128 
    129   (void)i;
    130 
    131   i=i;
    132   // CHECK-NEXT: load volatile
    133   // CHECK-NEXT: store volatile
    134 
    135   // Extra load volatile in C++.
    136   i=i=i;
    137   // CHECK-NEXT: load volatile
    138   // CHECK-NEXT: store volatile
    139   // CHECK-NEXT: load volatile
    140   // CHECK-NEXT: store volatile
    141 
    142   (void)__builtin_choose_expr(0, i=i, j=j);
    143   // CHECK-NEXT: load volatile
    144   // CHECK-NEXT: store volatile
    145 
    146   k ? (i=i) : (j=j);
    147   // CHECK-NEXT: load volatile
    148   // CHECK-NEXT: icmp
    149   // CHECK-NEXT: br i1
    150   // CHECK: load volatile
    151   // CHECK-NEXT: store volatile
    152   // CHECK-NEXT: br label
    153   // CHECK: load volatile
    154   // CHECK-NEXT: store volatile
    155   // CHECK-NEXT: br label
    156   // CHECK:      phi
    157 
    158   (void)(i,(i=i));
    159   // CHECK-NEXT: load volatile
    160   // CHECK-NEXT: store volatile
    161 
    162   i=i,k;
    163   // CHECK-NEXT: load volatile [[INT]]* @i
    164   // CHECK-NEXT: store volatile {{.*}}, [[INT]]* @i
    165 
    166   (i=j,k=j);
    167   // CHECK-NEXT: load volatile [[INT]]* @j
    168   // CHECK-NEXT: store volatile {{.*}}, [[INT]]* @i
    169   // CHECK-NEXT: load volatile [[INT]]* @j
    170   // CHECK-NEXT: store volatile {{.*}}, [[INT]]* @k
    171 
    172   (i=j,k);
    173   // CHECK-NEXT: load volatile [[INT]]* @j
    174   // CHECK-NEXT: store volatile {{.*}}, [[INT]]* @i
    175 
    176   (i,j);
    177 
    178   // Extra load in C++.
    179   i=c=k;
    180   // CHECK-NEXT: load volatile
    181   // CHECK-NEXT: trunc
    182   // CHECK-NEXT: store volatile
    183   // CHECK-NEXT: load volatile
    184   // CHECK-NEXT: sext
    185   // CHECK-NEXT: store volatile
    186 
    187   i+=k;
    188   // CHECK-NEXT: load volatile
    189   // CHECK-NEXT: load volatile
    190   // CHECK-NEXT: add nsw [[INT]]
    191   // CHECK-NEXT: store volatile
    192 
    193   ci;
    194 
    195   asm("nop"); // CHECK-NEXT: call void asm
    196 
    197   (int)ci;
    198   // CHECK-NEXT: load volatile {{.*}} @ci, i32 0, i32 0
    199   // CHECK-NEXT: load volatile {{.*}} @ci, i32 0, i32 1
    200 
    201   (bool)ci;
    202   // CHECK-NEXT: load volatile {{.*}} @ci, i32 0, i32 0
    203   // CHECK-NEXT: load volatile {{.*}} @ci, i32 0, i32 1
    204   // CHECK-NEXT: icmp ne
    205   // CHECK-NEXT: icmp ne
    206   // CHECK-NEXT: or i1
    207 
    208   ci=ci;
    209   // CHECK-NEXT: load volatile
    210   // CHECK-NEXT: load volatile
    211   // CHECK-NEXT: store volatile
    212   // CHECK-NEXT: store volatile
    213 
    214   asm("nop"); // CHECK-NEXT: call void asm
    215 
    216   // Extra load in C++.
    217   ci=ci=ci;
    218   // CHECK-NEXT: load volatile
    219   // CHECK-NEXT: load volatile
    220   // CHECK-NEXT: store volatile
    221   // CHECK-NEXT: store volatile
    222   // CHECK-NEXT: load volatile
    223   // CHECK-NEXT: load volatile
    224   // CHECK-NEXT: store volatile
    225   // CHECK-NEXT: store volatile
    226 
    227   __imag ci = __imag ci = __imag ci;
    228   // CHECK-NEXT: [[T:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
    229   // CHECK-NEXT: store volatile [[INT]] [[T]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
    230   // CHECK-NEXT: [[T:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
    231   // CHECK-NEXT: store volatile [[INT]] [[T]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
    232 
    233   __real (i = j);
    234   // CHECK-NEXT: load volatile
    235   // CHECK-NEXT: store volatile
    236 
    237   __imag i;
    238 
    239   // ============================================================
    240   // FIXME: Test cases we get wrong.
    241 
    242   // A use.  We load all of a into a copy of a, then load i.  gcc forgets to do
    243   // the assignment.
    244   // (a = a).i;
    245 
    246   // ============================================================
    247   // Test cases where we intentionally differ from gcc, due to suspected bugs in
    248   // gcc.
    249 
    250   // Not a use.  gcc forgets to do the assignment.
    251   // CHECK-NEXT: call
    252   ((a=a),a);
    253 
    254   // Not a use.  gcc gets this wrong, it doesn't emit the copy!
    255   // CHECK-NEXT: call
    256   (void)(a=a);
    257 
    258   // Not a use.  gcc got this wrong in 4.2 and omitted the side effects
    259   // entirely, but it is fixed in 4.4.0.
    260   __imag (i = j);
    261   // CHECK-NEXT: load volatile
    262   // CHECK-NEXT: store volatile
    263 
    264   // C++ does an extra load here.  Note that we have to do full loads.
    265   (float)(ci=ci);
    266   // CHECK-NEXT: load volatile
    267   // CHECK-NEXT: load volatile
    268   // CHECK-NEXT: store volatile
    269   // CHECK-NEXT: store volatile
    270   // CHECK-NEXT: load volatile
    271   // CHECK-NEXT: load volatile
    272   // CHECK-NEXT: sitofp
    273 
    274   // Not a use, bug?  gcc treats this as not a use, that's probably a
    275   // bug due to tree folding ignoring volatile.
    276   (int)(ci=ci);
    277   // CHECK-NEXT: load volatile
    278   // CHECK-NEXT: load volatile
    279   // CHECK-NEXT: store volatile
    280   // CHECK-NEXT: store volatile
    281   // CHECK-NEXT: load volatile
    282   // CHECK-NEXT: load volatile
    283 
    284   // A use.
    285   (float)(i=i);
    286   // CHECK-NEXT: load volatile
    287   // CHECK-NEXT: store volatile
    288   // CHECK-NEXT: load volatile
    289   // CHECK-NEXT: sitofp
    290 
    291   // A use.  gcc treats this as not a use, that's probably a bug due to tree
    292   // folding ignoring volatile.
    293   (int)(i=i);
    294   // CHECK-NEXT: load volatile
    295   // CHECK-NEXT: store volatile
    296   // CHECK-NEXT: load volatile
    297 
    298   // A use.
    299   -(i=j);
    300   // CHECK-NEXT: load volatile
    301   // CHECK-NEXT: store volatile
    302   // CHECK-NEXT: load volatile
    303   // CHECK-NEXT: sub
    304 
    305   // A use.  gcc treats this a not a use, that's probably a bug due to tree
    306   // folding ignoring volatile.
    307   +(i=k);
    308   // CHECK-NEXT: load volatile
    309   // CHECK-NEXT: store volatile
    310   // CHECK-NEXT: load volatile
    311 
    312   // A use. gcc treats this a not a use, that's probably a bug due to tree
    313   // folding ignoring volatile.
    314   __real (ci=ci);
    315   // CHECK-NEXT: load volatile
    316   // CHECK-NEXT: load volatile
    317   // CHECK-NEXT: store volatile
    318   // CHECK-NEXT: store volatile
    319 
    320   // A use.
    321   i + 0;
    322   // CHECK-NEXT: load volatile
    323   // CHECK-NEXT: add
    324 
    325   // A use.
    326   (i=j) + i;
    327   // CHECK-NEXT: load volatile
    328   // CHECK-NEXT: store volatile
    329   // CHECK-NEXT: load volatile
    330   // CHECK-NEXT: load volatile
    331   // CHECK-NEXT: add
    332 
    333   // A use.  gcc treats this as not a use, that's probably a bug due to tree
    334   // folding ignoring volatile.
    335   (i=j) + 0;
    336   // CHECK-NEXT: load volatile
    337   // CHECK-NEXT: store volatile
    338   // CHECK-NEXT: load volatile
    339   // CHECK-NEXT: add
    340 
    341   (i,j)=k;
    342   // CHECK-NEXT: load volatile [[INT]]* @k
    343   // CHECK-NEXT: store volatile {{.*}}, [[INT]]* @j
    344 
    345   (j=k,i)=i;
    346   // CHECK-NEXT: load volatile [[INT]]* @i
    347   // CHECK-NEXT: load volatile [[INT]]* @k
    348   // CHECK-NEXT: store volatile {{.*}}, [[INT]]* @j
    349   // CHECK-NEXT: store volatile {{.*}}, [[INT]]* @i
    350 
    351   // CHECK-NEXT: ret void
    352 }
    353