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