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 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
|
// REQUIRES: arm-registered-target
// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi %s | FileCheck %s
// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabihf %s | FileCheck %s
// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi -target-feature "+soft-float" -target-feature "+soft-float-abi" %s | FileCheck %s
// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi -target-feature "+soft-float" %s | FileCheck %s
// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi %s | FileCheck %s
// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi -meabi gnu %s | FileCheck %s
// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi %s | FileCheck %s
// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi -target-feature "+soft-float" -target-feature "+soft-float-abi" -meabi gnu %s | FileCheck %s
// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi -target-feature "+soft-float" -meabi gnu %s | FileCheck %s
// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabihf %s | FileCheck %s
// RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabihf -meabi gnu %s | FileCheck %s
// The Runtime ABI for the ARM Architecture IHI0043 section 4.1.2 The
// floating-point helper functions to always use the base AAPCS (soft-float)
// calling convention.
//
// These helper functions such as __aeabi_fadd are not explicitly called by
// clang, instead they are generated by the ARMISelLowering when they are
// needed; clang relies on llvm to use the base AAPCS.
//
// In this test we check that clang is not directly calling the __aeabi_
// functions. We rely on llvm to test that the base AAPCS is used for any
// __aeabi_ function from 4.1.2 that is used.
//
// When compiled to an object file with -mfloat-abi=soft each function F
// below should result in a call to __aeabi_F. If clang is changed to call any
// of these functions directly the test will need to be altered to check that
// arm_aapcscc is used.
//
// Note that it is only the functions in 4.1.2 that must use the base AAPCS,
// other runtime functions such as the _Complex helper routines are not covered.
float fadd(float a, float b) { return a + b; }
// CHECK-LABEL: define{{.*}} float @fadd(float %a, float %b)
// CHECK-NOT: __aeabi_fadd
// CHECK: %add = fadd float {{.*}}, {{.*}}
float fdiv(float a, float b) { return a / b; }
// CHECK-LABEL: define{{.*}} float @fdiv(float %a, float %b)
// CHECK-NOT: __aeabi_fdiv
// CHECK: %div = fdiv float {{.*}}, {{.*}}
float fmul(float a, float b) { return a * b; }
// CHECK-LABEL: define{{.*}} float @fmul(float %a, float %b)
// CHECK-NOT: __aeabi_fmul
// CHECK: %mul = fmul float {{.*}}, {{.*}}
float fsub(float a, float b) { return a - b; }
// CHECK-LABEL: define{{.*}} float @fsub(float %a, float %b)
// CHECK-NOT: __aeabi_fsub
// CHECK: %sub = fsub float {{.*}}, {{.*}}
int fcmpeq(float a, float b) { return a == b; }
// CHECK-LABEL: define{{.*}} i32 @fcmpeq(float %a, float %b)
// CHECK-NOT: __aeabi_fcmpeq
// CHECK: %cmp = fcmp oeq float {{.*}}, {{.*}}
int fcmplt(float a, float b) { return a < b; }
// CHECK-LABEL: define{{.*}} i32 @fcmplt(float %a, float %b)
// CHECK-NOT: __aeabi_fcmplt
// CHECK: %cmp = fcmp olt float {{.*}}, {{.*}}
int fcmple(float a, float b) { return a <= b; }
// CHECK-LABEL: define{{.*}} i32 @fcmple(float %a, float %b)
// CHECK-NOT: __aeabi_fcmple
// CHECK: %cmp = fcmp ole float {{.*}}, {{.*}}
int fcmpge(float a, float b) { return a >= b; }
// CHECK-LABEL: define{{.*}} i32 @fcmpge(float %a, float %b)
// CHECK-NOT: __aeabi_fcmpge
// CHECK: %cmp = fcmp oge float {{.*}}, {{.*}}
int fcmpgt(float a, float b) { return a > b; }
// CHECK-LABEL: define{{.*}} i32 @fcmpgt(float %a, float %b)
// CHECK-NOT: __aeabi_fcmpgt
// CHECK: %cmp = fcmp ogt float {{.*}}, {{.*}}
int fcmpun(float a, float b) { return __builtin_isunordered(a, b); }
// CHECK-LABEL: define{{.*}} i32 @fcmpun(float %a, float %b)
// CHECK-NOT: __aeabi_fcmpun
// CHECK: %cmp = fcmp uno float {{.*}}, {{.*}}
double dadd(double a, double b) { return a + b; }
// CHECK-LABEL: define{{.*}} double @dadd(double %a, double %b)
// CHECK-NOT: __aeabi_dadd
// CHECK: %add = fadd double {{.*}}, {{.*}}
double ddiv(double a, double b) { return a / b; }
// CHECK-LABEL: define{{.*}} double @ddiv(double %a, double %b)
// CHECK-NOT: __aeabi_ddiv
// CHECK: %div = fdiv double {{.*}}, {{.*}}
double dmul(double a, double b) { return a * b; }
// CHECK-LABEL: define{{.*}} double @dmul(double %a, double %b)
// CHECK-NOT: __aeabi_dmul
// CHECK: %mul = fmul double {{.*}}, {{.*}}
double dsub(double a, double b) { return a - b; }
// CHECK-LABEL: define{{.*}} double @dsub(double %a, double %b)
// CHECK-NOT: __aeabi_dsub
// CHECK: %sub = fsub double {{.*}}, {{.*}}
int dcmpeq(double a, double b) { return a == b; }
// CHECK-LABEL: define{{.*}} i32 @dcmpeq(double %a, double %b)
// CHECK-NOT: __aeabi_dcmpeq
// CHECK: %cmp = fcmp oeq double {{.*}}, {{.*}}
int dcmplt(double a, double b) { return a < b; }
// CHECK-LABEL: define{{.*}} i32 @dcmplt(double %a, double %b)
// CHECK-NOT: __aeabi_dcmplt
// CHECK: %cmp = fcmp olt double {{.*}}, {{.*}}
int dcmple(double a, double b) { return a <= b; }
// CHECK-LABEL: define{{.*}} i32 @dcmple(double %a, double %b)
// CHECK-NOT: __aeabi_dcmple
// CHECK: %cmp = fcmp ole double {{.*}}, {{.*}}
int dcmpge(double a, double b) { return a >= b; }
// CHECK-LABEL: define{{.*}} i32 @dcmpge(double %a, double %b)
// CHECK-NOT: __aeabi_dcmpge
// CHECK: %cmp = fcmp oge double {{.*}}, {{.*}}
int dcmpgt(double a, double b) { return a > b; }
// CHECK-LABEL: define{{.*}} i32 @dcmpgt(double %a, double %b)
// CHECK-NOT: __aeabi_dcmpgt
// CHECK: %cmp = fcmp ogt double {{.*}}, {{.*}}
int dcmpun(double a, double b) { return __builtin_isunordered(a, b); }
// CHECK-LABEL: define{{.*}} i32 @dcmpun(double %a, double %b)
// CHECK-NOT: __aeabi_dcmpun
// CHECK: %cmp = fcmp uno double {{.*}}, {{.*}}
int d2iz(double a) { return (int)a; }
// CHECK-LABEL: define{{.*}} i32 @d2iz(double %a)
// CHECK-NOT: __aeabi_d2iz
// CHECK: %conv = fptosi double {{.*}} to i32
unsigned int d2uiz(double a) { return (unsigned int)a; }
// CHECK-LABEL: define{{.*}} i32 @d2uiz(double %a)
// CHECK-NOT: __aeabi_d2uiz
// CHECK: %conv = fptoui double {{.*}} to i32
long long d2lz(double a) { return (long long)a; }
// CHECK-LABEL: define{{.*}} i64 @d2lz(double %a)
// CHECK-NOT: __aeabi_d2lz
// CHECK: %conv = fptosi double {{.*}} to i64
unsigned long long d2ulz(double a) { return (unsigned long long)a; }
// CHECK-LABEL: define{{.*}} i64 @d2ulz(double %a)
// CHECK-NOT: __aeabi_d2ulz
// CHECK: %conv = fptoui double {{.*}} to i64
int f2iz(float a) { return (int)a; }
// CHECK-LABEL: define{{.*}} i32 @f2iz(float %a)
// CHECK-NOT: __aeabi_f2iz
// CHECK: %conv = fptosi float {{.*}} to i32
unsigned int f2uiz(float a) { return (unsigned int)a; }
// CHECK-LABEL: define{{.*}} i32 @f2uiz(float %a)
// CHECK-NOT: __aeabi_f2uiz
// CHECK: %conv = fptoui float {{.*}} to i32
long long f2lz(float a) { return (long long)a; }
// CHECK-LABEL: define{{.*}} i64 @f2lz(float %a)
// CHECK-NOT: __aeabi_f2lz
// CHECK: %conv = fptosi float {{.*}} to i64
unsigned long long f2ulz(float a) { return (unsigned long long)a; }
// CHECK-LABEL: define{{.*}} i64 @f2ulz(float %a)
// CHECK-NOT: __aeabi_f2ulz
// CHECK: %conv = fptoui float {{.*}} to i64
float d2f(double a) { return (float)a; }
// CHECK-LABEL: define{{.*}} float @d2f(double %a)
// CHECK-NOT: __aeabi_d2f
// CHECK: %conv = fptrunc double {{.*}} to float
double f2d(float a) { return (double)a; }
// CHECK-LABEL: define{{.*}} double @f2d(float %a)
// CHECK-NOT: __aeabi_f2d
// CHECK: %conv = fpext float {{.*}} to double
double i2d(int a) { return (double)a; }
// CHECK-LABEL: define{{.*}} double @i2d(i32 %a)
// CHECK-NOT: __aeabi_i2d
// CHECK: %conv = sitofp i32 {{.*}} to double
double ui2d(unsigned int a) { return (double)a; }
// CHECK-LABEL: define{{.*}} double @ui2d(i32 %a)
// CHECK-NOT: __aeabi_ui2d
// CHECK: %conv = uitofp i32 {{.*}} to double
double l2d(long long a) { return (double)a; }
// CHECK-LABEL: define{{.*}} double @l2d(i64 %a)
// CHECK-NOT: __aeabi_l2d
// CHECK: %conv = sitofp i64 {{.*}} to double
double ul2d(unsigned long long a) { return (unsigned long long)a; }
// CHECK-LABEL: define{{.*}} double @ul2d(i64 %a)
// CHECK-NOT: __aeabi_ul2d
// CHECK: %conv = uitofp i64 {{.*}} to double
float i2f(int a) { return (int)a; }
// CHECK-LABEL: define{{.*}} float @i2f(i32 %a)
// CHECK-NOT: __aeabi_i2f
// CHECK: %conv = sitofp i32 {{.*}} to float
float ui2f(unsigned int a) { return (unsigned int)a; }
// CHECK-LABEL: define{{.*}} float @ui2f(i32 %a)
// CHECK-NOT: __aeabi_ui2f
// CHECK: %conv = uitofp i32 {{.*}} to float
float l2f(long long a) { return (long long)a; }
// CHECK-LABEL: define{{.*}} float @l2f(i64 %a)
// CHECK-NOT: __aeabi_l2f
// CHECK: %conv = sitofp i64 {{.*}} to float
float ul2f(unsigned long long a) { return (unsigned long long)a; }
// CHECK-LABEL: define{{.*}} float @ul2f(i64 %a)
// CHECK-NOT: __aeabi_ul2f
// CHECK: %conv = uitofp i64 {{.*}} to float
// Functions in section 4.1.2 not used by llvm and don't easily map directly to
// C source code.
// cfcmpeq
// cfcmple
// cfrcmple
// cdcmpeq
// cdcmple
// cdrcmple
// frsub
// drsub
|