summaryrefslogtreecommitdiffstats
path: root/test/CodeGen/x86_64-floatvectors.c
blob: 389a06a6d6e43981fc3147307d71a36b8f5974d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | \
// RUN:   FileCheck %s

// This test validates that the inreg branch generation for __builtin_va_arg 
// does not exceed the alloca size of the type, which can cause the SROA pass to
// eliminate the assignment.

typedef struct { float x, y, z; } vec3f;

double Vec3FTest(__builtin_va_list ap) {
  vec3f vec = __builtin_va_arg(ap, vec3f);
  return vec.x + vec.y + vec.z;
}
// CHECK: define double @Vec3FTest
// CHECK: vaarg.in_reg:
// CHECK: [[Vec3FLoad1:%.*]] = load <2 x float>, <2 x float>*
// CHECK: [[Vec3FGEP1:%.*]] = getelementptr inbounds { <2 x float>, float }, { <2 x float>, float }* {{%.*}}, i32 0, i32 0
// CHECK: store <2 x float> [[Vec3FLoad1]], <2 x float>* [[Vec3FGEP1]]
// CHECK: [[Vec3FLoad2:%.*]] = load float, float*
// CHECK: [[Vec3FGEP2:%.*]] = getelementptr inbounds { <2 x float>, float }, { <2 x float>, float }* {{%.*}}, i32 0, i32 1
// CHECK: store float [[Vec3FLoad2]], float* [[Vec3FGEP2]]
// CHECK: vaarg.in_mem:


typedef struct { float x, y, z, q; } vec4f;

double Vec4FTest(__builtin_va_list ap) {
  vec4f vec = __builtin_va_arg(ap, vec4f);
  return vec.x + vec.y + vec.z + vec.q;
}
// CHECK: define double @Vec4FTest
// CHECK: vaarg.in_reg:
// CHECK: [[Vec4FLoad1:%.*]] = load <2 x float>, <2 x float>*
// CHECK: [[Vec4FGEP1:%.*]] = getelementptr inbounds { <2 x float>, <2 x float> }, { <2 x float>, <2 x float> }* {{%.*}}, i32 0, i32 0
// CHECK: store <2 x float> [[Vec4FLoad1]], <2 x float>* [[Vec4FGEP1]]
// CHECK: [[Vec4FLoad2:%.*]] = load <2 x float>, <2 x float>*
// CHECK: [[Vec4FGEP2:%.*]] = getelementptr inbounds { <2 x float>, <2 x float> }, { <2 x float>, <2 x float> }* {{%.*}}, i32 0, i32 1
// CHECK: store <2 x float> [[Vec4FLoad2]], <2 x float>* [[Vec4FGEP2]]
// CHECK: vaarg.in_mem:

typedef struct { double x, y; } vec2d;

double Vec2DTest(__builtin_va_list ap) {
  vec2d vec = __builtin_va_arg(ap, vec2d);
  return vec.x + vec.y;
}
// CHECK: define double @Vec2DTest
// CHECK: vaarg.in_reg:
// CHECK: [[Vec2DLoad1:%.*]] = load double, double*
// CHECK: [[Vec2DGEP1:%.*]] = getelementptr inbounds { double, double }, { double, double }* {{%.*}}, i32 0, i32 0
// CHECK: store double [[Vec2DLoad1]], double* [[Vec2DGEP1]]
// CHECK: [[Vec2DLoad2:%.*]] = load double, double*
// CHECK: [[Vec2DGEP2:%.*]] = getelementptr inbounds { double, double }, { double, double }* {{%.*}}, i32 0, i32 1
// CHECK: store double [[Vec2DLoad2]], double* [[Vec2DGEP2]]
// CHECK: vaarg.in_mem:

typedef struct {
  float x, y;
  double z;
} vec2f1d;

double Vec2F1DTest(__builtin_va_list ap) {
  vec2f1d vec = __builtin_va_arg(ap, vec2f1d);
  return vec.x + vec.y + vec.z;
}
// CHECK: define double @Vec2F1DTest
// CHECK: vaarg.in_reg:
// CHECK: [[Vec2F1DLoad1:%.*]] = load <2 x float>, <2 x float>*
// CHECK: [[Vec2F1DGEP1:%.*]] = getelementptr inbounds { <2 x float>, double }, { <2 x float>, double }* {{%.*}}, i32 0, i32 0
// CHECK: store <2 x float> [[Vec2F1DLoad1]], <2 x float>* [[Vec2F1DGEP1]]
// CHECK: [[Vec2F1DLoad2:%.*]] = load double, double*
// CHECK: [[Vec2F1DGEP2:%.*]] = getelementptr inbounds { <2 x float>, double }, { <2 x float>, double }* {{%.*}}, i32 0, i32 1
// CHECK: store double [[Vec2F1DLoad2]], double* [[Vec2F1DGEP2]]
// CHECK: vaarg.in_mem:

typedef struct {
  double x;
  float y, z;
} vec1d2f;

double Vec1D2FTest(__builtin_va_list ap) {
  vec1d2f vec = __builtin_va_arg(ap, vec1d2f);
  return vec.x + vec.y + vec.z;
}
// CHECK: define double @Vec1D2FTest
// CHECK: vaarg.in_reg:
// CHECK: [[Vec1D2FLoad1:%.*]] = load double, double*
// CHECK: [[Vec1D2FGEP1:%.*]] = getelementptr inbounds { double, <2 x float> }, { double, <2 x float> }* {{%.*}}, i32 0, i32 0
// CHECK: store double [[Vec1D2FLoad1]], double* [[Vec1D2FGEP1]]
// CHECK: [[Vec1D2FLoad2:%.*]] = load <2 x float>, <2 x float>*
// CHECK: [[Vec1D2FGEP2:%.*]] = getelementptr inbounds { double, <2 x float> }, { double, <2 x float> }* {{%.*}}, i32 0, i32 1
// CHECK: store <2 x float> [[Vec1D2FLoad2]], <2 x float>* [[Vec1D2FGEP2]]
// CHECK: vaarg.in_mem:

typedef struct {
  float x;
  double z;
} vec1f1d;

double Vec1F1DTest(__builtin_va_list ap) {
  vec1f1d vec = __builtin_va_arg(ap, vec1f1d);
  return vec.x  + vec.z;
}
// CHECK: define double @Vec1F1DTest
// CHECK: vaarg.in_reg:
// CHECK: [[Vec1F1DLoad1:%.*]] = load float, float*
// CHECK: [[Vec1F1DGEP1:%.*]] = getelementptr inbounds { float, double }, { float, double }* {{%.*}}, i32 0, i32 0
// CHECK: store float [[Vec1F1DLoad1]], float* [[Vec1F1DGEP1]]
// CHECK: [[Vec1F1DLoad2:%.*]] = load double, double*
// CHECK: [[Vec1F1DGEP2:%.*]] = getelementptr inbounds { float, double }, { float, double }* {{%.*}}, i32 0, i32 1
// CHECK: store double [[Vec1F1DLoad2]], double* [[Vec1F1DGEP2]]
// CHECK: vaarg.in_mem:

typedef struct {
  double x;
  float z;
} vec1d1f;

double Vec1D1FTest(__builtin_va_list ap) {
  vec1d1f vec = __builtin_va_arg(ap, vec1d1f);
  return vec.x  + vec.z;
}
// CHECK: define double @Vec1D1FTest
// CHECK: vaarg.in_reg:
// CHECK: [[Vec1D1FLoad1:%.*]] = load double, double*
// CHECK: [[Vec1D1FGEP1:%.*]] = getelementptr inbounds { double, float }, { double, float }* {{%.*}}, i32 0, i32 0
// CHECK: store double [[Vec1D1FLoad1]], double* [[Vec1D1FGEP1]]
// CHECK: [[Vec1D1FLoad2:%.*]] = load float, float*
// CHECK: [[Vec1D1FGEP2:%.*]] = getelementptr inbounds { double, float }, { double, float }* {{%.*}}, i32 0, i32 1
// CHECK: store float [[Vec1D1FLoad2]], float* [[Vec1D1FGEP2]]
// CHECK: vaarg.in_mem: