Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / CodeGen / sparcv9-abi.c
blob2d39c64c1c2ce6c76a974907349a59c02fbafd0e
1 // RUN: %clang_cc1 -triple sparcv9-unknown-unknown -emit-llvm %s -o - | FileCheck %s
2 #include <stdarg.h>
4 // CHECK-LABEL: define{{.*}} void @f_void()
5 void f_void(void) {}
7 // Arguments and return values smaller than the word size are extended.
9 // CHECK-LABEL: define{{.*}} signext i32 @f_int_1(i32 noundef signext %x)
10 int f_int_1(int x) { return x; }
12 // CHECK-LABEL: define{{.*}} zeroext i32 @f_int_2(i32 noundef zeroext %x)
13 unsigned f_int_2(unsigned x) { return x; }
15 // CHECK-LABEL: define{{.*}} i64 @f_int_3(i64 noundef %x)
16 long long f_int_3(long long x) { return x; }
18 // CHECK-LABEL: define{{.*}} signext i8 @f_int_4(i8 noundef signext %x)
19 char f_int_4(char x) { return x; }
21 // CHECK-LABEL: define{{.*}} fp128 @f_ld(fp128 noundef %x)
22 long double f_ld(long double x) { return x; }
24 // Small structs are passed in registers.
25 struct small {
26 int *a, *b;
29 // CHECK-LABEL: define{{.*}} %struct.small @f_small(ptr %x.coerce0, ptr %x.coerce1)
30 struct small f_small(struct small x) {
31 x.a += *x.b;
32 x.b = 0;
33 return x;
36 // Medium-sized structs are passed indirectly, but can be returned in registers.
37 struct medium {
38 int *a, *b;
39 int *c, *d;
42 // CHECK-LABEL: define{{.*}} %struct.medium @f_medium(ptr noundef %x)
43 struct medium f_medium(struct medium x) {
44 x.a += *x.b;
45 x.b = 0;
46 return x;
49 // Large structs are also returned indirectly.
50 struct large {
51 int *a, *b;
52 int *c, *d;
53 int x;
56 // CHECK-LABEL: define{{.*}} void @f_large(ptr noalias sret(%struct.large) align 8 %agg.result, ptr noundef %x)
57 struct large f_large(struct large x) {
58 x.a += *x.b;
59 x.b = 0;
60 return x;
63 // A 64-bit struct fits in a register.
64 struct reg {
65 int a, b;
68 // CHECK-LABEL: define{{.*}} i64 @f_reg(i64 %x.coerce)
69 struct reg f_reg(struct reg x) {
70 x.a += x.b;
71 return x;
74 // Structs with mixed int and float parts require the inreg attribute.
75 struct mixed {
76 int a;
77 float b;
80 // CHECK-LABEL: define{{.*}} inreg %struct.mixed @f_mixed(i32 inreg %x.coerce0, float inreg %x.coerce1)
81 struct mixed f_mixed(struct mixed x) {
82 x.a += 1;
83 return x;
86 // Struct with padding.
87 struct mixed2 {
88 int a;
89 double b;
92 // CHECK: define{{.*}} { i64, double } @f_mixed2(i64 %x.coerce0, double %x.coerce1)
93 // CHECK: store i64 %x.coerce0
94 // CHECK: store double %x.coerce1
95 struct mixed2 f_mixed2(struct mixed2 x) {
96 x.a += 1;
97 return x;
100 // Struct with single element and padding in passed in the high bits of a
101 // register.
102 struct tiny {
103 char a;
106 // CHECK-LABEL: define{{.*}} i64 @f_tiny(i64 %x.coerce)
107 // CHECK: %[[HB:[^ ]+]] = lshr i64 %x.coerce, 56
108 // CHECK: = trunc i64 %[[HB]] to i8
109 struct tiny f_tiny(struct tiny x) {
110 x.a += 1;
111 return x;
114 // CHECK-LABEL: define{{.*}} void @call_tiny()
115 // CHECK: %[[XV:[^ ]+]] = zext i8 %{{[^ ]+}} to i64
116 // CHECK: %[[HB:[^ ]+]] = shl i64 %[[XV]], 56
117 // CHECK: = call i64 @f_tiny(i64 %[[HB]])
118 void call_tiny(void) {
119 struct tiny x = { 1 };
120 f_tiny(x);
123 // CHECK-LABEL: define{{.*}} signext i32 @f_variable(ptr noundef %f, ...)
124 // CHECK: %ap = alloca ptr
125 // CHECK: call void @llvm.va_start
127 int f_variable(char *f, ...) {
128 int s = 0;
129 char c;
130 va_list ap;
131 va_start(ap, f);
132 while ((c = *f++)) switch (c) {
134 // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
135 // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8
136 // CHECK-DAG: store ptr %[[NXT]], ptr %ap
137 // CHECK-DAG: %[[EXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 4
138 // CHECK-DAG: load i32, ptr %[[EXT]]
139 // CHECK: br
140 case 'i':
141 s += va_arg(ap, int);
142 break;
144 // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
145 // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8
146 // CHECK-DAG: store ptr %[[NXT]], ptr %ap
147 // CHECK-DAG: load i64, ptr %[[CUR]]
148 // CHECK: br
149 case 'l':
150 s += va_arg(ap, long);
151 break;
153 // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
154 // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8
155 // CHECK-DAG: store ptr %[[NXT]], ptr %ap
156 // CHECK: br
157 case 't':
158 s += va_arg(ap, struct tiny).a;
159 break;
161 // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
162 // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 16
163 // CHECK-DAG: store ptr %[[NXT]], ptr %ap
164 // CHECK: br
165 case 's':
166 s += *va_arg(ap, struct small).a;
167 break;
169 // CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap
170 // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8
171 // CHECK-DAG: store ptr %[[NXT]], ptr %ap
172 // CHECK-DAG: %[[ADR:[^ ]+]] = load ptr, ptr %[[CUR]]
173 // CHECK: br
174 case 'm':
175 s += *va_arg(ap, struct medium).a;
176 break;
178 return s;