1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
2 // RUN: %clang_cc1 -no-opaque-pointers -emit-llvm -triple powerpc64-unknown-unknown \
3 // RUN:   -std=c++20 %s -o - -debug-info-kind=limited | FileCheck %s
4 // RUN: %clang_cc1 -no-opaque-pointers -emit-llvm -triple powerpc64le-unknown-unknown \
5 // RUN:   -std=c++20 %s -o - -debug-info-kind=limited | FileCheck %s
6 
7 #include <stdarg.h>
8 
9 static __ibm128 sgf;
10 __ibm128 arrgf[10];
11 __ibm128 func1(__ibm128 arg);
12 
13 class CTest {
14   __ibm128 pf;
15   static const __ibm128 scf;
16   volatile __ibm128 vf;
17 
18 public:
CTest(__ibm128 arg)19   CTest(__ibm128 arg) : pf(arg), vf(arg) {}
func2(__ibm128 arg)20   __ibm128 func2(__ibm128 arg) {
21     return pf + arg;
22   }
func3(__ibm128 arg)23   static __ibm128 func3(__ibm128 arg) {
24     return arg * CTest::scf;
25   }
26 };
27 
func_add(__ibm128 a,__ibm128 b)28 constexpr __ibm128 func_add(__ibm128 a, __ibm128 b) {
29   return a + b;
30 }
31 
32 constinit const __ibm128 ci = func_add(1.0, 2.0);
33 __ibm128 gf = ci;
34 
func_arith(__ibm128 a,__ibm128 b,__ibm128 c)35 __ibm128 func_arith(__ibm128 a, __ibm128 b, __ibm128 c) {
36   __ibm128 v1 = a + b;
37   __ibm128 v2 = a - c;
38   __ibm128 v3 = v1 * c;
39   __ibm128 v4 = v2 / v3;
40   return v4;
41 }
42 
func_vaarg(int n,...)43 __ibm128 func_vaarg(int n, ...) {
44   va_list ap;
45   va_start(ap, n);
46   __ibm128 r = va_arg(ap, __ibm128);
47   va_end(ap);
48   return r;
49 }
50 
51 template <typename T> struct T1 {
52   T mem1;
53 };
54 template <> struct T1<__ibm128> {
55   __ibm128 mem2;
56 };
57 
58 template <__ibm128 Q> struct T2 {
59   constexpr static __ibm128 mem = Q;
60 };
61 
62 typedef float w128ibm __attribute__((mode(IF)));
63 typedef _Complex float w128ibm_c __attribute__((mode(IC)));
64 
icmode_self(w128ibm x)65 w128ibm icmode_self(w128ibm x) { return x; }
icmode_self_complex(w128ibm_c x)66 w128ibm_c icmode_self_complex(w128ibm_c x) { return x; }
67 
main(void)68 int main(void) {
69   __ibm128 lf;
70   CTest ct(lf);
71   T1<__ibm128> tf;
72   __ibm128 lfi = tf.mem2 + func1(lf) - CTest::func3(lf);
73 }
74 
75 // CHECK: %class.CTest = type { ppc_fp128, ppc_fp128 }
76 // CHECK: %struct.T1 = type { ppc_fp128 }
77 
78 // CHECK: @arrgf = global [10 x ppc_fp128] zeroinitializer, align 16
79 // CHECK: @gf = global ppc_fp128 0xM40080000000000000000000000000000, align 16
80 // CHECK: @_ZN5CTest3scfE = external constant ppc_fp128, align 16
81 
82 // CHECK: define dso_local noundef ppc_fp128 @_Z10func_arithggg(ppc_fp128 noundef %a, ppc_fp128 noundef %b, ppc_fp128 noundef %c)
83 // CHECK: entry:
84 // CHECK:   store ppc_fp128 %a, ppc_fp128* %a.addr, align 16
85 // CHECK:   store ppc_fp128 %b, ppc_fp128* %b.addr, align 16
86 // CHECK:   store ppc_fp128 %c, ppc_fp128* %c.addr, align 16
87 // CHECK:   %0 = load ppc_fp128, ppc_fp128* %a.addr, align 16
88 // CHECK:   %1 = load ppc_fp128, ppc_fp128* %b.addr, align 16
89 // CHECK:   %add = fadd ppc_fp128 %0, %1
90 // CHECK:   store ppc_fp128 %add, ppc_fp128* %v1, align 16
91 // CHECK:   %2 = load ppc_fp128, ppc_fp128* %a.addr, align 16
92 // CHECK:   %3 = load ppc_fp128, ppc_fp128* %c.addr, align 16
93 // CHECK:   %sub = fsub ppc_fp128 %2, %3
94 // CHECK:   store ppc_fp128 %sub, ppc_fp128* %v2, align 16
95 // CHECK:   %4 = load ppc_fp128, ppc_fp128* %v1, align 16
96 // CHECK:   %5 = load ppc_fp128, ppc_fp128* %c.addr, align 16
97 // CHECK:   %mul = fmul ppc_fp128 %4, %5
98 // CHECK:   store ppc_fp128 %mul, ppc_fp128* %v3, align 16
99 // CHECK:   %6 = load ppc_fp128, ppc_fp128* %v2, align 16
100 // CHECK:   %7 = load ppc_fp128, ppc_fp128* %v3, align 16
101 // CHECK:   %div = fdiv ppc_fp128 %6, %7
102 // CHECK:   store ppc_fp128 %div, ppc_fp128* %v4, align 16
103 // CHECK:   %8 = load ppc_fp128, ppc_fp128* %v4, align 16
104 // CHECK:   ret ppc_fp128 %8
105 // CHECK: }
106 
107 // CHECK: define dso_local noundef ppc_fp128 @_Z10func_vaargiz(i32 noundef signext %n, ...)
108 // CHECK: entry:
109 // CHECK:   store i32 %n, i32* %n.addr, align 4
110 // CHECK:   %ap1 = bitcast i8** %ap to i8*
111 // CHECK:   call void @llvm.va_start(i8* %ap1)
112 // CHECK:   %argp.cur = load i8*, i8** %ap, align 8
113 // CHECK:   %argp.next = getelementptr inbounds i8, i8* %argp.cur, i64 16
114 // CHECK:   store i8* %argp.next, i8** %ap, align 8
115 // CHECK:   %0 = bitcast i8* %argp.cur to ppc_fp128*
116 // CHECK:   %1 = load ppc_fp128, ppc_fp128* %0, align 8
117 // CHECK:   store ppc_fp128 %1, ppc_fp128* %r, align 16
118 // CHECK:   %ap2 = bitcast i8** %ap to i8*
119 // CHECK:   call void @llvm.va_end(i8* %ap2)
120 // CHECK:   %2 = load ppc_fp128, ppc_fp128* %r, align 16
121 // CHECK:   ret ppc_fp128 %2
122 // CHECK: }
123 
124 // CHECK: define dso_local noundef ppc_fp128 @_Z11icmode_selfg(ppc_fp128 noundef %x)
125 // CHECK: define dso_local noundef { ppc_fp128, ppc_fp128 } @_Z19icmode_self_complexCg(ppc_fp128 noundef %x.coerce0, ppc_fp128 noundef %x.coerce1)
126 
127 // CHECK: define dso_local noundef signext i32 @main()
128 // CHECK: entry:
129 // CHECK:   %0 = load ppc_fp128, ppc_fp128* %lf, align 16
130 // CHECK:   call void @_ZN5CTestC1Eg(%class.CTest* noundef nonnull align 16 dereferenceable(32) %ct, ppc_fp128 noundef %0)
131 // CHECK:   %mem2 = getelementptr inbounds %struct.T1, %struct.T1* %tf, i32 0, i32 0
132 // CHECK:   %1 = load ppc_fp128, ppc_fp128* %mem2, align 16
133 // CHECK:   %2 = load ppc_fp128, ppc_fp128* %lf, align 16
134 // CHECK:   %call = call noundef ppc_fp128 @_Z5func1g(ppc_fp128 noundef %2)
135 // CHECK:   %add = fadd ppc_fp128 %1, %call
136 // CHECK:   %3 = load ppc_fp128, ppc_fp128* %lf, align 16
137 // CHECK:   %call1 = call noundef ppc_fp128 @_ZN5CTest5func3Eg(ppc_fp128 noundef %3)
138 // CHECK:   %sub = fsub ppc_fp128 %add, %call1
139 // CHECK:   store ppc_fp128 %sub, ppc_fp128* %lfi, align 16
140 // CHECK:   ret i32 0
141 // CHECK: }
142 
143 // CHECK: define linkonce_odr void @_ZN5CTestC1Eg(%class.CTest* noundef nonnull align 16 dereferenceable(32) %this, ppc_fp128 noundef %arg)
144 // CHECK: entry:
145 // CHECK:   store %class.CTest* %this, %class.CTest** %this.addr, align 8
146 // CHECK:   store ppc_fp128 %arg, ppc_fp128* %arg.addr, align 16
147 // CHECK:   %this1 = load %class.CTest*, %class.CTest** %this.addr, align 8
148 // CHECK:   %0 = load ppc_fp128, ppc_fp128* %arg.addr, align 16
149 // CHECK:   call void @_ZN5CTestC2Eg(%class.CTest* noundef nonnull align 16 dereferenceable(32) %this1, ppc_fp128 noundef %0)
150 // CHECK:   ret void
151 // CHECK: }
152 
153 // CHECK: define linkonce_odr noundef ppc_fp128 @_ZN5CTest5func3Eg(ppc_fp128 noundef %arg)
154 // CHECK: entry:
155 // CHECK:   %arg.addr = alloca ppc_fp128, align 16
156 // CHECK:   store ppc_fp128 %arg, ppc_fp128* %arg.addr, align 16
157 // CHECK:   %0 = load ppc_fp128, ppc_fp128* %arg.addr, align 16
158 // CHECK:   %1 = load ppc_fp128, ppc_fp128* @_ZN5CTest3scfE, align 16
159 // CHECK:   %mul = fmul ppc_fp128 %0, %1
160 // CHECK:   ret ppc_fp128 %mul
161 // CHECK: }
162 
163 // CHECK: define linkonce_odr void @_ZN5CTestC2Eg(%class.CTest* noundef nonnull align 16 dereferenceable(32) %this, ppc_fp128 noundef %arg)
164 // CHECK: entry:
165 // CHECK:   store %class.CTest* %this, %class.CTest** %this.addr, align 8
166 // CHECK:   store ppc_fp128 %arg, ppc_fp128* %arg.addr, align 16
167 // CHECK:   %this1 = load %class.CTest*, %class.CTest** %this.addr, align 8
168 // CHECK:   %pf = getelementptr inbounds %class.CTest, %class.CTest* %this1, i32 0, i32 0
169 // CHECK:   %0 = load ppc_fp128, ppc_fp128* %arg.addr, align 16
170 // CHECK:   store ppc_fp128 %0, ppc_fp128* %pf, align 16
171 // CHECK:   %vf = getelementptr inbounds %class.CTest, %class.CTest* %this1, i32 0, i32 1
172 // CHECK:   %1 = load ppc_fp128, ppc_fp128* %arg.addr, align 16
173 // CHECK:   store volatile ppc_fp128 %1, ppc_fp128* %vf, align 16
174 // CHECK:   ret void
175 // CHECK: }
176 
177 // CHECK: !6 = distinct !DIGlobalVariable(name: "gf", scope: !2, file: !7, line: {{[0-9]+}}, type: !8, isLocal: false, isDefinition: true)
178 // CHECK: !8 = !DIBasicType(name: "__ibm128", size: 128, encoding: DW_ATE_float)
179