1 // RUN: %clang -std=c++11 --target=aarch64-arm--eabi -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AARCH64 2 // RUN: %clang -std=c++11 --target=x86_64 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-X86 3 4 /* Various contexts where type _Float16 can appear. */ 5 6 7 /* Namespace */ 8 9 namespace { 10 _Float16 f1n; 11 // CHECK-DAG: @_ZN12_GLOBAL__N_13f1nE = internal global half 0xH0000, align 2 12 13 _Float16 f2n = 33.f16; 14 // CHECK-AARCH64-DAG: @_ZN12_GLOBAL__N_13f2nE = internal global half 0xH5020, align 2 15 // CHECK-X86-DAG: @_ZN12_GLOBAL__N_13f2nE = internal global i16 20512, align 2 16 17 _Float16 arr1n[10]; 18 // CHECK-AARCH64-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x half] zeroinitializer, align 2 19 // CHECK-X86-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x half] zeroinitializer, align 16 20 21 _Float16 arr2n[] = { 1.2, 3.0, 3.e4 }; 22 // CHECK-AARCH64-DAG: @_ZN12_GLOBAL__N_15arr2nE = internal global [3 x half] [half 0xH3CCD, half 0xH4200, half 0xH7753], align 2 23 // CHECK-X86-DAG: @_ZN12_GLOBAL__N_15arr2nE = internal global [3 x i16] [i16 15565, i16 16896, i16 30547], align 2 24 25 const volatile _Float16 func1n(const _Float16 &arg) { 26 return arg + f2n + arr1n[4] - arr2n[1]; 27 } 28 } 29 30 31 /* File */ 32 33 _Float16 f1f; 34 // CHECK-AARCH64-DAG: @f1f = global half 0xH0000, align 2 35 // CHECK-X86-DAG: @f1f = global half 0xH0000, align 2 36 37 _Float16 f2f = 32.4; 38 // CHECK-AARCH64-DAG: @f2f = global half 0xH500D, align 2 39 // CHECK-X86-DAG: @f2f = global i16 20493, align 2 40 41 _Float16 arr1f[10]; 42 // CHECK-AARCH64-DAG: @arr1f = global [10 x half] zeroinitializer, align 2 43 // CHECK-X86-DAG: @arr1f = global [10 x half] zeroinitializer, align 16 44 45 _Float16 arr2f[] = { -1.2, -3.0, -3.e4 }; 46 // CHECK-AARCH64-DAG: @arr2f = global [3 x half] [half 0xHBCCD, half 0xHC200, half 0xHF753], align 2 47 // CHECK-X86-DAG: @arr2f = global [3 x i16] [i16 -17203, i16 -15872, i16 -2221], align 2 48 49 _Float16 func1f(_Float16 arg); 50 51 52 /* Class */ 53 54 class C1 { 55 _Float16 f1c; 56 57 static const _Float16 f2c; 58 // CHECK-DAG: @_ZN2C13f2cE = external constant half, align 2 59 60 volatile _Float16 f3c; 61 62 public: 63 C1(_Float16 arg) : f1c(arg), f3c(arg) { } 64 // Check that we mangle _Float16 to DF16_ 65 // CHECK-DAG: define linkonce_odr void @_ZN2C1C2EDF16_(%class.C1*{{.*}}, half{{.*}}) 66 67 _Float16 func1c(_Float16 arg ) { 68 return f1c + arg; 69 } 70 // CHECK-DAG: define linkonce_odr half @_ZN2C16func1cEDF16_(%class.C1*{{.*}}, half{{.*}}) 71 72 static _Float16 func2c(_Float16 arg) { 73 return arg * C1::f2c; 74 } 75 // CHECK-DAG: define linkonce_odr half @_ZN2C16func2cEDF16_(half{{.*}}) 76 }; 77 78 /* Template */ 79 80 template <class C> C func1t(C arg) { 81 return arg * 2.f16; 82 } 83 // CHECK-DAG: define linkonce_odr half @_Z6func1tIDF16_ET_S0_(half{{.*}}) 84 85 template <class C> struct S1 { 86 C mem1; 87 }; 88 89 template <> struct S1<_Float16> { 90 _Float16 mem2; 91 }; 92 93 94 /* Local */ 95 96 extern int printf (const char *__restrict __format, ...); 97 98 int main(void) { 99 _Float16 f1l = 1e3f16; 100 // CHECK-DAG: store half 0xH63D0, half* %{{.*}}, align 2 101 102 _Float16 f2l = -0.f16; 103 // CHECK-DAG: store half 0xH8000, half* %{{.*}}, align 2 104 105 _Float16 f3l = 1.000976562; 106 // CHECK-DAG: store half 0xH3C01, half* %{{.*}}, align 2 107 108 C1 c1(f1l); 109 // CHECK-DAG: [[F1L:%[a-z0-9]+]] = load half, half* %{{.*}}, align 2 110 // CHECK-DAG: call void @_ZN2C1C2EDF16_(%class.C1* %{{.*}}, half %{{.*}}) 111 112 S1<_Float16> s1 = { 132.f16 }; 113 // CHECK-AARCH64-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant %struct.S1 { half 0xH5820 }, align 2 114 // CHECK-X86-DAG: @_ZZ4mainE2s1 = private unnamed_addr constant { i16 } { i16 22560 }, align 2 115 // CHECK-DAG: [[S1:%[0-9]+]] = bitcast %struct.S1* %{{.*}} to i8* 116 // CHECK-AARCH64-DAG: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[S1]], i8* bitcast (%struct.S1* @_ZZ4mainE2s1 to i8*), i64 2, i32 2, i1 false) 117 // CHECK-X86-DAG: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* bitcast ({ i16 }* @_ZZ4mainE2s1 to i8*), i64 2, i32 2, i1 false) 118 119 _Float16 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) + 120 func1t(f1l) + s1.mem2 - f1n + f2n; 121 122 auto f5l = -1.f16, *f6l = &f2l, f7l = func1t(f3l); 123 // CHECK-DAG: store half 0xHBC00, half* %{{.*}}, align 2 124 // CHECK-DAG: store half* %{{.*}}, half** %{{.*}}, align 8 125 126 _Float16 f8l = f4l++; 127 // CHECK-DAG: %{{.*}} = load half, half* %{{.*}}, align 2 128 // CHECK-DAG: [[INC:%[a-z0-9]+]] = fadd half {{.*}}, 0xH3C00 129 // CHECK-DAG: store half [[INC]], half* %{{.*}}, align 2 130 131 _Float16 arr1l[] = { -1.f16, -0.f16, -11.f16 }; 132 // CHECK-AARCH64-DAG: @_ZZ4mainE5arr1l = private unnamed_addr constant [3 x half] [half 0xHBC00, half 0xH8000, half 0xHC980], align 2 133 // CHECK-X86-DAG: @_ZZ4mainE5arr1l = private unnamed_addr constant [3 x i16] [i16 -17408, i16 -32768, i16 -13952], align 2 134 135 float cvtf = f2n; 136 //CHECK-DAG: [[H2F:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to float 137 //CHECK-DAG: store float [[H2F]], float* %{{.*}}, align 4 138 139 double cvtd = f2n; 140 //CHECK-DAG: [[H2D:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to double 141 //CHECK-DAG: store double [[H2D]], double* %{{.*}}, align 8 142 143 144 long double cvtld = f2n; 145 //CHECK-AARCh64-DAG: [[H2LD:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to fp128 146 //CHECK-AARCh64-DAG: store fp128 [[H2LD]], fp128* %{{.*}}, align 16 147 //CHECK-X86-DAG: [[H2LD:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to x86_fp80 148 //CHECK-X86-DAG: store x86_fp80 [[H2LD]], x86_fp80* %{{.*}}, align 16 149 150 _Float16 f2h = 42.0f; 151 //CHECK-DAG: store half 0xH5140, half* %{{.*}}, align 2 152 _Float16 d2h = 42.0; 153 //CHECK-DAG: store half 0xH5140, half* %{{.*}}, align 2 154 _Float16 ld2h = 42.0l; 155 //CHECK-DAG:store half 0xH5140, half* %{{.*}}, align 2 156 } 157