// RUN: %clang_cc1 -emit-llvm < %s -o %t
// RUN: grep volatile %t | count 28
// RUN: grep memcpy %t | count 7
// The number 28 comes from the current codegen for volatile loads;
// if this number changes, it's not necessarily something wrong, but
// something has changed to affect volatile load/store codegen
int S;
volatile int vS;
int* pS;
volatile int* pvS;
int A[10];
volatile int vA[10];
struct { int x; } F;
struct { volatile int x; } vF;
struct { int x; } F2;
volatile struct { int x; } vF2;
volatile struct { int x; } *vpF2;
struct { struct { int y; } x; } F3;
volatile struct { struct { int y; } x; } vF3;
struct { int x:3; } BF;
struct { volatile int x:3; } vBF;
typedef int v4si __attribute__ ((vector_size (16)));
v4si V;
volatile v4si vV;
typedef __attribute__(( ext_vector_type(4) )) int extv4;
extv4 VE;
volatile extv4 vVE;
volatile struct {int x;} aggFct(void);
typedef volatile int volatile_int;
volatile_int vtS;
int main() {
int i;
// load
i=S;
i=vS;
i=*pS;
i=*pvS;
i=A[2];
i=vA[2];
i=F.x;
i=vF.x;
i=F2.x;
i=vF2.x;
i=vpF2->x;
i=F3.x.y;
i=vF3.x.y;
i=BF.x;
i=vBF.x;
i=V[3];
i=vV[3];
i=VE.yx[1];
i=vVE.zy[1];
i = aggFct().x; // Note: not volatile
i=vtS;
// store
S=i;
vS=i;
*pS=i;
*pvS=i;
A[2]=i;
vA[2]=i;
F.x=i;
vF.x=i;
F2.x=i;
vF2.x=i;
vpF2->x=i;
vF3.x.y=i;
BF.x=i;
vBF.x=i;
V[3]=i;
vV[3]=i;
vtS=i;
// other ops:
++S;
++vS;
i+=S;
i+=vS;
++vtS;
(void)vF2;
vF2 = vF2;
vF2 = vF2 = vF2;
vF2 = (vF2, vF2);
}