brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.1 KiB · d3f79fd Raw
277 lines · c
1// RUN: %clang_cc1 -triple sparcv9-unknown-unknown -emit-llvm %s -o - | FileCheck %s2#include <stdarg.h>3 4// CHECK-LABEL: define{{.*}} void @f_void()5void f_void(void) {}6 7// Arguments and return values smaller than the word size are extended.8 9// CHECK-LABEL: define{{.*}} signext i32 @f_int_1(i32 noundef signext %x)10int f_int_1(int x) { return x; }11 12// CHECK-LABEL: define{{.*}} zeroext i32 @f_int_2(i32 noundef zeroext %x)13unsigned f_int_2(unsigned x) { return x; }14 15// CHECK-LABEL: define{{.*}} i64 @f_int_3(i64 noundef %x)16long long f_int_3(long long x) { return x; }17 18// CHECK-LABEL: define{{.*}} signext i8 @f_int_4(i8 noundef signext %x)19char f_int_4(char x) { return x; }20 21// CHECK-LABEL: define{{.*}} fp128 @f_ld(fp128 noundef %x)22long double f_ld(long double x) { return x; }23 24// Zero-sized structs reserves an argument register slot if passed directly.25struct empty {};26struct emptyarr { struct empty a[10]; };27 28// In 16-byte structs, 16-byte aligned members are expanded29// to their corresponding i128/f128 types.30struct align16_int { _Alignas(16) int x; };31struct align16_mixed { _Alignas(16) int x; double y; };32struct align16_longdouble { long double x; };33 34// CHECK-LABEL: define{{.*}} i64 @f_empty(i64 %x.coerce)35struct empty f_empty(struct empty x) { return x; }36 37// CHECK-LABEL: define{{.*}} i64 @f_emptyarr(i64 %x.coerce)38struct empty f_emptyarr(struct emptyarr x) { return x.a[0]; }39 40// CHECK-LABEL: define{{.*}} void @f_aligncaller(i64 %a.coerce0, i64 %a.coerce1)41// CHECK-LABEL: declare{{.*}} void @f_aligncallee(i32 noundef signext, i64, i64, i64)42void f_aligncallee(int pad, struct align16_int a);43void f_aligncaller(struct align16_int a) {44    f_aligncallee(0, a);45}46 47// CHECK-LABEL: define{{.*}} double @f_mixed_aligned(i64 noundef %a, i64 %0, i64 %b.coerce0, double %b.coerce1)48double f_mixed_aligned(long a, struct align16_mixed b) {49	return b.y;50}51 52// CHECK-LABEL: define{{.*}} fp128 @f_longdouble(i64 noundef %a, i64 %0, fp128 %b.coerce)53long double f_longdouble(long a, struct align16_longdouble b) {54	return b.x;55}56 57// CHECK-LABEL: define{{.*}} i64 @f_emptyvar(i32 noundef zeroext %count, ...)58long f_emptyvar(unsigned count, ...) {59    long ret;60    va_list args;61    va_start(args, count);62 63// CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %args64// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 865// CHECK-DAG: store ptr %[[NXT]], ptr %args66    va_arg(args, struct empty);67 68// CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %args69// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 870// CHECK-DAG: store ptr %[[NXT]], ptr %args71// CHECK-DAG: load i64, ptr %[[CUR]]72    ret = va_arg(args, long);73    va_end(args);74    return ret;75}76 77// If the zero-sized struct is contained in a non-zero-sized struct,78// though, it doesn't reserve any registers.79struct emptymixed { struct empty a; long b; };80struct emptyflex { unsigned count; struct empty data[10]; };81 82// CHECK-LABEL: define{{.*}} i64 @f_emptymixed(i64 %x.coerce)83long f_emptymixed(struct emptymixed x) { return x.b; }84 85// CHECK-LABEL: define{{.*}} i64 @f_emptyflex(i64 %x.coerce, i64 noundef %y)86long f_emptyflex(struct emptyflex x, long y) { return y; }87 88// Small structs are passed in registers.89struct small {90  int *a, *b;91};92 93// CHECK-LABEL: define{{.*}} %struct.small @f_small(ptr %x.coerce0, ptr %x.coerce1)94struct small f_small(struct small x) {95  x.a += *x.b;96  x.b = 0;97  return x;98}99 100// Medium-sized structs are passed indirectly, but can be returned in registers.101struct medium {102  int *a, *b;103  int *c, *d;104};105 106struct medium_aligned {107  _Alignas(16) int *a;108  int *b, *c, *d;109};110 111// CHECK-LABEL: define{{.*}} %struct.medium @f_medium(ptr dead_on_return noundef %x)112struct medium f_medium(struct medium x) {113  x.a += *x.b;114  x.b = 0;115  return x;116}117 118// CHECK-LABEL: define{{.*}} %struct.medium_aligned @f_medium_aligned(ptr dead_on_return noundef %x)119struct medium_aligned f_medium_aligned(struct medium_aligned x) {120  x.a += *x.b;121  x.b = 0;122  return x;123}124 125// Large structs are also returned indirectly.126struct large {127  int *a, *b;128  int *c, *d;129  int x;130};131 132// CHECK-LABEL: define{{.*}} void @f_large(ptr dead_on_unwind noalias writable sret(%struct.large) align 8 %agg.result, ptr dead_on_return noundef %x)133struct large f_large(struct large x) {134  x.a += *x.b;135  x.b = 0;136  return x;137}138 139// Large returns are converted into a pointer argument.140// Such conversion should preserve the alignment of overaligned arguments.141// define{{.*}} void @f_largereturn_aligned(ptr dead_on_unwind noalias writable sret(%struct.large) align 8 %agg.result, i64 %0, i64 %x.coerce0, i64 %x.coerce1)142struct large f_largereturn_aligned(struct align16_int x) {143  struct large ret;144  ret.x = x.x;145  return ret;146}147 148// A 64-bit struct fits in a register.149struct reg {150  int a, b;151};152 153// CHECK-LABEL: define{{.*}} i64 @f_reg(i64 %x.coerce)154struct reg f_reg(struct reg x) {155  x.a += x.b;156  return x;157}158 159// Structs with mixed int and float parts require the inreg attribute.160struct mixed {161  int a;162  float b;163};164 165// CHECK-LABEL: define{{.*}} inreg %struct.mixed @f_mixed(i32 inreg %x.coerce0, float inreg %x.coerce1)166struct mixed f_mixed(struct mixed x) {167  x.a += 1;168  return x;169}170 171// Struct with padding.172struct mixed2 {173  int a;174  double b;175};176 177// CHECK: define{{.*}} { i64, double } @f_mixed2(i64 %x.coerce0, double %x.coerce1)178// CHECK: store i64 %x.coerce0179// CHECK: store double %x.coerce1180struct mixed2 f_mixed2(struct mixed2 x) {181  x.a += 1;182  return x;183}184 185// Struct with single element and padding in passed in the high bits of a186// register.187struct tiny {188  char a;189};190 191// CHECK-LABEL: define{{.*}} i64 @f_tiny(i64 %x.coerce)192// CHECK: %[[HB:[^ ]+]] = lshr i64 %x.coerce, 56193// CHECK: = trunc i64 %[[HB]] to i8194struct tiny f_tiny(struct tiny x) {195  x.a += 1;196  return x;197}198 199// CHECK-LABEL: define{{.*}} void @call_tiny()200// CHECK: %[[XV:[^ ]+]] = zext i8 %{{[^ ]+}} to i64201// CHECK: %[[HB:[^ ]+]] = shl i64 %[[XV]], 56202// CHECK: = call i64 @f_tiny(i64 %[[HB]])203void call_tiny(void) {204  struct tiny x = { 1 };205  f_tiny(x);206}207 208// CHECK-LABEL: define{{.*}} signext i32 @f_variable(ptr noundef %f, ...)209// CHECK: %ap = alloca ptr210// CHECK: call void @llvm.va_start211//212int f_variable(char *f, ...) {213  int s = 0;214  char c;215  va_list ap;216  va_start(ap, f);217  while ((c = *f++)) switch (c) {218 219// CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap220// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8221// CHECK-DAG: store ptr %[[NXT]], ptr %ap222// CHECK-DAG: %[[EXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 4223// CHECK-DAG: load i32, ptr %[[EXT]]224// CHECK: br225  case 'i':226    s += va_arg(ap, int);227    break;228 229// CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap230// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8231// CHECK-DAG: store ptr %[[NXT]], ptr %ap232// CHECK-DAG: load i64, ptr %[[CUR]]233// CHECK: br234  case 'l':235    s += va_arg(ap, long);236    break;237 238// CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap239// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8240// CHECK-DAG: store ptr %[[NXT]], ptr %ap241// CHECK: br242  case 't':243    s += va_arg(ap, struct tiny).a;244    break;245 246// CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap247// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 16248// CHECK-DAG: store ptr %[[NXT]], ptr %ap249// CHECK: br250  case 's':251    s += *va_arg(ap, struct small).a;252    break;253 254// CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap255// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i64 8256// CHECK-DAG: store ptr %[[NXT]], ptr %ap257// CHECK-DAG: %[[ADR:[^ ]+]] = load ptr, ptr %[[CUR]]258// CHECK: br259  case 'm':260    s += *va_arg(ap, struct medium).a;261    break;262 263// CHECK: %[[CUR:[^ ]+]] = load ptr, ptr %ap264// CHECK-DAG: %[[TMP:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15265// CHECK-DAG: %[[ALIGNED:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP]], i64 -16)266// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, ptr %[[ALIGNED]], i64 16267// CHECK-DAG: store ptr %[[NXT]], ptr %ap268// CHECK-DAG: call void @llvm.memcpy.p0.p0.i64(ptr align 16 {{.*}}, ptr align 16 %[[ALIGNED]], i64 16, i1 false)269// CHECK: br270  case 'a':271    s += va_arg(ap, struct align16_int).x;272    break;273  }274  va_end(ap);275  return s;276}277