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 double %conv, %conv1
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
|