summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX/float16-declarations.cpp
blob: 7e1c1e8db93caf45ee161e5039ac93bc61c5f3a3 (plain)
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
// RUN: %clang -std=c++11 --target=aarch64-arm--eabi -S -emit-llvm %s -o - | FileCheck %s  --check-prefix=CHECK --check-prefix=CHECK-AARCH64
// RUN: %clang -std=c++11 --target=x86_64 -S -emit-llvm %s -o - | FileCheck %s  --check-prefix=CHECK --check-prefix=CHECK-X86

/*  Various contexts where type _Float16 can appear. */


/*  Namespace */

namespace {
  _Float16 f1n;
// CHECK-DAG: @_ZN12_GLOBAL__N_13f1nE = internal global half 0xH0000, align 2

  _Float16 f2n = 33.f16;
// CHECK-DAG: @_ZN12_GLOBAL__N_13f2nE = internal global half 0xH5020, align 2

  _Float16 arr1n[10];
// CHECK-AARCH64-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x half] zeroinitializer, align 2
// CHECK-X86-DAG:     @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x half] zeroinitializer, align 16

  _Float16 arr2n[] = { 1.2, 3.0, 3.e4 };
// CHECK-DAG: @_ZN12_GLOBAL__N_15arr2nE = internal global [3 x half] [half 0xH3CCD, half 0xH4200, half 0xH7753], align 2

  const volatile _Float16 func1n(const _Float16 &arg) {
    return arg + f2n + arr1n[4] - arr2n[1];
  }
}


/* File */

_Float16 f1f;
// CHECK-AARCH64-DAG: @f1f = dso_local global half 0xH0000, align 2
// CHECK-X86-DAG: @f1f = dso_local global half 0xH0000, align 2

_Float16 f2f = 32.4;
// CHECK-DAG: @f2f = dso_local global half 0xH500D, align 2

_Float16 arr1f[10];
// CHECK-AARCH64-DAG: @arr1f = dso_local global [10 x half] zeroinitializer, align 2
// CHECK-X86-DAG: @arr1f = dso_local global [10 x half] zeroinitializer, align 16

_Float16 arr2f[] = { -1.2, -3.0, -3.e4 };
// CHECK-DAG: @arr2f = dso_local global [3 x half] [half 0xHBCCD, half 0xHC200, half 0xHF753], align 2

_Float16 func1f(_Float16 arg);


/* Class */

class C1 {
  _Float16 f1c;

  static const _Float16 f2c;
// CHECK-DAG: @_ZN2C13f2cE = external dso_local constant half, align 2

  volatile _Float16 f3c;

public:
  C1(_Float16 arg) : f1c(arg), f3c(arg) { }
// Check that we mangle _Float16 to DF16_
// CHECK-DAG: define linkonce_odr dso_local void @_ZN2C1C2EDF16_(%class.C1*{{.*}}, half{{.*}})

  _Float16 func1c(_Float16 arg ) {
    return f1c + arg;
  }
// CHECK-DAG: define linkonce_odr dso_local half @_ZN2C16func1cEDF16_(%class.C1*{{.*}}, half{{.*}})

  static _Float16 func2c(_Float16 arg) {
    return arg * C1::f2c;
  }
// CHECK-DAG: define linkonce_odr dso_local half @_ZN2C16func2cEDF16_(half{{.*}})
};

/*  Template */

template <class C> C func1t(C arg) {
  return arg * 2.f16;
}
// CHECK-DAG: define linkonce_odr dso_local half @_Z6func1tIDF16_ET_S0_(half{{.*}})

template <class C> struct S1 {
  C mem1;
};

template <> struct S1<_Float16> {
  _Float16 mem2;
};


/* Local */

extern int printf (const char *__restrict __format, ...);

int main(void) {
  _Float16 f1l = 1e3f16;
// CHECK-DAG: store half 0xH63D0, half* %{{.*}}, align 2

  _Float16 f2l = -0.f16;
// CHECK-DAG: store half 0xH8000, half* %{{.*}}, align 2

  _Float16 f3l = 1.000976562;
// CHECK-DAG: store half 0xH3C01, half* %{{.*}}, align 2

  C1 c1(f1l);
// CHECK-DAG:  [[F1L:%[a-z0-9]+]] = load half, half* %{{.*}}, align 2
// CHECK-DAG:  call void @_ZN2C1C2EDF16_(%class.C1* %{{.*}}, half %{{.*}})

  S1<_Float16> s1 = { 132.f16 };
// CHECK-DAG: @__const.main.s1 = private unnamed_addr constant %struct.S1 { half 0xH5820 }, align 2
// CHECK-DAG:  [[S1:%[0-9]+]] = bitcast %struct.S1* %{{.*}} to i8*
// CHECK-DAG: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 2 [[S1]], i8* align 2 bitcast (%struct.S1* @__const.main.s1 to i8*), i64 2, i1 false)

  _Float16 f4l = func1n(f1l)  + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) +
    func1t(f1l) + s1.mem2 - f1n + f2n;

  auto f5l = -1.f16, *f6l = &f2l, f7l = func1t(f3l);
// CHECK-DAG:  store half 0xHBC00, half* %{{.*}}, align 2
// CHECK-DAG:  store half* %{{.*}}, half** %{{.*}}, align 8

  _Float16 f8l = f4l++;
// CHECK-DAG:  %{{.*}} = load half, half* %{{.*}}, align 2
// CHECK-DAG:  [[INC:%[a-z0-9]+]] = fadd half {{.*}}, 0xH3C00
// CHECK-DAG:  store half [[INC]], half* %{{.*}}, align 2

  _Float16 arr1l[] = { -1.f16, -0.f16, -11.f16 };
// CHECK-DAG: @__const.main.arr1l = private unnamed_addr constant [3 x half] [half 0xHBC00, half 0xH8000, half 0xHC980], align 2

  float cvtf = f2n;
//CHECK-DAG: [[H2F:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to float
//CHECK-DAG:  store float [[H2F]], float* %{{.*}}, align 4

  double cvtd = f2n;
//CHECK-DAG: [[H2D:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to double
//CHECK-DAG: store double [[H2D]], double* %{{.*}}, align 8


  long double cvtld = f2n;
//CHECK-AARCh64-DAG: [[H2LD:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to fp128
//CHECK-AARCh64-DAG: store fp128 [[H2LD]], fp128* %{{.*}}, align 16
//CHECK-X86-DAG:     [[H2LD:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to x86_fp80
//CHECK-X86-DAG:     store x86_fp80 [[H2LD]], x86_fp80* %{{.*}}, align 16

  _Float16 f2h = 42.0f;
//CHECK-DAG: store half 0xH5140, half* %{{.*}}, align 2
  _Float16 d2h = 42.0;
//CHECK-DAG: store half 0xH5140, half* %{{.*}}, align 2
  _Float16 ld2h = 42.0l;
//CHECK-DAG:store half 0xH5140, half* %{{.*}}, align 2
}