234 lines · c
1// REQUIRES: arm-registered-target2// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi %s | FileCheck %s3// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabihf %s | FileCheck %s4// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi -target-feature "+soft-float" -target-feature "+soft-float-abi" %s | FileCheck %s5// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi -target-feature "+soft-float" %s | FileCheck %s6// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi %s | FileCheck %s7// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi -meabi gnu %s | FileCheck %s8// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi %s | FileCheck %s9// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi -target-feature "+soft-float" -target-feature "+soft-float-abi" -meabi gnu %s | FileCheck %s10// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi -target-feature "+soft-float" -meabi gnu %s | FileCheck %s11// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabihf %s | FileCheck %s12// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabihf -meabi gnu %s | FileCheck %s13 14// The Runtime ABI for the ARM Architecture IHI0043 section 4.1.2 The15// floating-point helper functions to always use the base AAPCS (soft-float)16// calling convention.17//18// These helper functions such as __aeabi_fadd are not explicitly called by19// clang, instead they are generated by the ARMISelLowering when they are20// needed; clang relies on llvm to use the base AAPCS.21//22// In this test we check that clang is not directly calling the __aeabi_23// functions. We rely on llvm to test that the base AAPCS is used for any24// __aeabi_ function from 4.1.2 that is used.25//26// When compiled to an object file with -mfloat-abi=soft each function F27// below should result in a call to __aeabi_F. If clang is changed to call any28// of these functions directly the test will need to be altered to check that29// arm_aapcscc is used.30//31// Note that it is only the functions in 4.1.2 that must use the base AAPCS,32// other runtime functions such as the _Complex helper routines are not covered.33 34float fadd(float a, float b) { return a + b; }35// CHECK-LABEL: define{{.*}} float @fadd(float noundef %a, float noundef %b)36// CHECK-NOT: __aeabi_fadd37// CHECK: %add = fadd float {{.*}}, {{.*}}38 39float fdiv(float a, float b) { return a / b; }40// CHECK-LABEL: define{{.*}} float @fdiv(float noundef %a, float noundef %b)41// CHECK-NOT: __aeabi_fdiv42// CHECK: %div = fdiv float {{.*}}, {{.*}}43 44float fmul(float a, float b) { return a * b; }45// CHECK-LABEL: define{{.*}} float @fmul(float noundef %a, float noundef %b)46// CHECK-NOT: __aeabi_fmul47// CHECK: %mul = fmul float {{.*}}, {{.*}}48 49float fsub(float a, float b) { return a - b; }50// CHECK-LABEL: define{{.*}} float @fsub(float noundef %a, float noundef %b)51// CHECK-NOT: __aeabi_fsub52// CHECK: %sub = fsub float {{.*}}, {{.*}}53 54int fcmpeq(float a, float b) { return a == b; }55// CHECK-LABEL: define{{.*}} i32 @fcmpeq(float noundef %a, float noundef %b)56// CHECK-NOT: __aeabi_fcmpeq57// CHECK: %cmp = fcmp oeq float {{.*}}, {{.*}}58 59int fcmplt(float a, float b) { return a < b; }60// CHECK-LABEL: define{{.*}} i32 @fcmplt(float noundef %a, float noundef %b)61// CHECK-NOT: __aeabi_fcmplt62// CHECK: %cmp = fcmp olt float {{.*}}, {{.*}}63 64int fcmple(float a, float b) { return a <= b; }65// CHECK-LABEL: define{{.*}} i32 @fcmple(float noundef %a, float noundef %b)66// CHECK-NOT: __aeabi_fcmple67// CHECK: %cmp = fcmp ole float {{.*}}, {{.*}}68 69int fcmpge(float a, float b) { return a >= b; }70// CHECK-LABEL: define{{.*}} i32 @fcmpge(float noundef %a, float noundef %b)71// CHECK-NOT: __aeabi_fcmpge72// CHECK: %cmp = fcmp oge float {{.*}}, {{.*}}73 74int fcmpgt(float a, float b) { return a > b; }75// CHECK-LABEL: define{{.*}} i32 @fcmpgt(float noundef %a, float noundef %b)76// CHECK-NOT: __aeabi_fcmpgt77// CHECK: %cmp = fcmp ogt float {{.*}}, {{.*}}78 79int fcmpun(float a, float b) { return __builtin_isunordered(a, b); }80// CHECK-LABEL: define{{.*}} i32 @fcmpun(float noundef %a, float noundef %b)81// CHECK-NOT: __aeabi_fcmpun82// CHECK: %cmp = fcmp uno float {{.*}}, {{.*}}83 84double dadd(double a, double b) { return a + b; }85// CHECK-LABEL: define{{.*}} double @dadd(double noundef %a, double noundef %b)86// CHECK-NOT: __aeabi_dadd87// CHECK: %add = fadd double {{.*}}, {{.*}}88 89double ddiv(double a, double b) { return a / b; }90// CHECK-LABEL: define{{.*}} double @ddiv(double noundef %a, double noundef %b)91// CHECK-NOT: __aeabi_ddiv92// CHECK: %div = fdiv double {{.*}}, {{.*}}93 94double dmul(double a, double b) { return a * b; }95// CHECK-LABEL: define{{.*}} double @dmul(double noundef %a, double noundef %b)96// CHECK-NOT: __aeabi_dmul97// CHECK: %mul = fmul double {{.*}}, {{.*}}98 99double dsub(double a, double b) { return a - b; }100// CHECK-LABEL: define{{.*}} double @dsub(double noundef %a, double noundef %b)101// CHECK-NOT: __aeabi_dsub102// CHECK: %sub = fsub double {{.*}}, {{.*}}103 104int dcmpeq(double a, double b) { return a == b; }105// CHECK-LABEL: define{{.*}} i32 @dcmpeq(double noundef %a, double noundef %b)106// CHECK-NOT: __aeabi_dcmpeq107// CHECK: %cmp = fcmp oeq double {{.*}}, {{.*}}108 109int dcmplt(double a, double b) { return a < b; }110// CHECK-LABEL: define{{.*}} i32 @dcmplt(double noundef %a, double noundef %b)111// CHECK-NOT: __aeabi_dcmplt112// CHECK: %cmp = fcmp olt double {{.*}}, {{.*}}113 114int dcmple(double a, double b) { return a <= b; }115// CHECK-LABEL: define{{.*}} i32 @dcmple(double noundef %a, double noundef %b)116// CHECK-NOT: __aeabi_dcmple117// CHECK: %cmp = fcmp ole double {{.*}}, {{.*}}118 119int dcmpge(double a, double b) { return a >= b; }120// CHECK-LABEL: define{{.*}} i32 @dcmpge(double noundef %a, double noundef %b)121// CHECK-NOT: __aeabi_dcmpge122// CHECK: %cmp = fcmp oge double {{.*}}, {{.*}}123 124int dcmpgt(double a, double b) { return a > b; }125// CHECK-LABEL: define{{.*}} i32 @dcmpgt(double noundef %a, double noundef %b)126// CHECK-NOT: __aeabi_dcmpgt127// CHECK: %cmp = fcmp ogt double {{.*}}, {{.*}}128 129int dcmpun(double a, double b) { return __builtin_isunordered(a, b); }130// CHECK-LABEL: define{{.*}} i32 @dcmpun(double noundef %a, double noundef %b)131// CHECK-NOT: __aeabi_dcmpun132// CHECK: %cmp = fcmp uno double {{.*}}, {{.*}}133 134int d2iz(double a) { return (int)a; }135// CHECK-LABEL: define{{.*}} i32 @d2iz(double noundef %a)136// CHECK-NOT: __aeabi_d2iz137// CHECK: %conv = fptosi double {{.*}} to i32138 139unsigned int d2uiz(double a) { return (unsigned int)a; }140// CHECK-LABEL: define{{.*}} i32 @d2uiz(double noundef %a)141// CHECK-NOT: __aeabi_d2uiz142// CHECK: %conv = fptoui double {{.*}} to i32143 144long long d2lz(double a) { return (long long)a; }145// CHECK-LABEL: define{{.*}} i64 @d2lz(double noundef %a)146// CHECK-NOT: __aeabi_d2lz147// CHECK: %conv = fptosi double {{.*}} to i64148 149unsigned long long d2ulz(double a) { return (unsigned long long)a; }150// CHECK-LABEL: define{{.*}} i64 @d2ulz(double noundef %a)151// CHECK-NOT: __aeabi_d2ulz152// CHECK: %conv = fptoui double {{.*}} to i64153 154int f2iz(float a) { return (int)a; }155// CHECK-LABEL: define{{.*}} i32 @f2iz(float noundef %a)156// CHECK-NOT: __aeabi_f2iz157// CHECK: %conv = fptosi float {{.*}} to i32158 159unsigned int f2uiz(float a) { return (unsigned int)a; }160// CHECK-LABEL: define{{.*}} i32 @f2uiz(float noundef %a)161// CHECK-NOT: __aeabi_f2uiz162// CHECK: %conv = fptoui float {{.*}} to i32163 164long long f2lz(float a) { return (long long)a; }165// CHECK-LABEL: define{{.*}} i64 @f2lz(float noundef %a)166// CHECK-NOT: __aeabi_f2lz167// CHECK: %conv = fptosi float {{.*}} to i64168 169unsigned long long f2ulz(float a) { return (unsigned long long)a; }170// CHECK-LABEL: define{{.*}} i64 @f2ulz(float noundef %a)171// CHECK-NOT: __aeabi_f2ulz172// CHECK: %conv = fptoui float {{.*}} to i64173 174float d2f(double a) { return (float)a; }175// CHECK-LABEL: define{{.*}} float @d2f(double noundef %a)176// CHECK-NOT: __aeabi_d2f177// CHECK: %conv = fptrunc double {{.*}} to float178 179double f2d(float a) { return (double)a; }180// CHECK-LABEL: define{{.*}} double @f2d(float noundef %a)181// CHECK-NOT: __aeabi_f2d182// CHECK: %conv = fpext float {{.*}} to double183 184double i2d(int a) { return (double)a; }185// CHECK-LABEL: define{{.*}} double @i2d(i32 noundef %a)186// CHECK-NOT: __aeabi_i2d187// CHECK: %conv = sitofp i32 {{.*}} to double188 189double ui2d(unsigned int a) { return (double)a; }190// CHECK-LABEL: define{{.*}} double @ui2d(i32 noundef %a)191// CHECK-NOT: __aeabi_ui2d192// CHECK: %conv = uitofp i32 {{.*}} to double193 194double l2d(long long a) { return (double)a; }195// CHECK-LABEL: define{{.*}} double @l2d(i64 noundef %a)196// CHECK-NOT: __aeabi_l2d197// CHECK: %conv = sitofp i64 {{.*}} to double198 199double ul2d(unsigned long long a) { return (unsigned long long)a; }200// CHECK-LABEL: define{{.*}} double @ul2d(i64 noundef %a)201// CHECK-NOT: __aeabi_ul2d202// CHECK: %conv = uitofp i64 {{.*}} to double203 204float i2f(int a) { return (int)a; }205// CHECK-LABEL: define{{.*}} float @i2f(i32 noundef %a)206// CHECK-NOT: __aeabi_i2f207// CHECK: %conv = sitofp i32 {{.*}} to float208 209float ui2f(unsigned int a) { return (unsigned int)a; }210// CHECK-LABEL: define{{.*}} float @ui2f(i32 noundef %a)211// CHECK-NOT: __aeabi_ui2f212// CHECK: %conv = uitofp i32 {{.*}} to float213 214float l2f(long long a) { return (long long)a; }215// CHECK-LABEL: define{{.*}} float @l2f(i64 noundef %a)216// CHECK-NOT: __aeabi_l2f217// CHECK: %conv = sitofp i64 {{.*}} to float218 219float ul2f(unsigned long long a) { return (unsigned long long)a; }220// CHECK-LABEL: define{{.*}} float @ul2f(i64 noundef %a)221// CHECK-NOT: __aeabi_ul2f222// CHECK: %conv = uitofp i64 {{.*}} to float223 224// Functions in section 4.1.2 not used by llvm and don't easily map directly to225// C source code.226// cfcmpeq227// cfcmple228// cfrcmple229// cdcmpeq230// cdcmple231// cdrcmple232// frsub233// drsub234