1*700637cbSDimitry Andric //===------ SystemZ.cpp - Emit LLVM Code for builtins ---------------------===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric // This contains code to emit Builtin calls as LLVM code.
10*700637cbSDimitry Andric //
11*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
12*700637cbSDimitry Andric
13*700637cbSDimitry Andric #include "CodeGenFunction.h"
14*700637cbSDimitry Andric #include "clang/Basic/TargetBuiltins.h"
15*700637cbSDimitry Andric #include "llvm/IR/IntrinsicsS390.h"
16*700637cbSDimitry Andric
17*700637cbSDimitry Andric using namespace clang;
18*700637cbSDimitry Andric using namespace CodeGen;
19*700637cbSDimitry Andric using namespace llvm;
20*700637cbSDimitry Andric
21*700637cbSDimitry Andric /// Handle a SystemZ function in which the final argument is a pointer
22*700637cbSDimitry Andric /// to an int that receives the post-instruction CC value. At the LLVM level
23*700637cbSDimitry Andric /// this is represented as a function that returns a {result, cc} pair.
EmitSystemZIntrinsicWithCC(CodeGenFunction & CGF,unsigned IntrinsicID,const CallExpr * E)24*700637cbSDimitry Andric static Value *EmitSystemZIntrinsicWithCC(CodeGenFunction &CGF,
25*700637cbSDimitry Andric unsigned IntrinsicID,
26*700637cbSDimitry Andric const CallExpr *E) {
27*700637cbSDimitry Andric unsigned NumArgs = E->getNumArgs() - 1;
28*700637cbSDimitry Andric SmallVector<Value *, 8> Args(NumArgs);
29*700637cbSDimitry Andric for (unsigned I = 0; I < NumArgs; ++I)
30*700637cbSDimitry Andric Args[I] = CGF.EmitScalarExpr(E->getArg(I));
31*700637cbSDimitry Andric Address CCPtr = CGF.EmitPointerWithAlignment(E->getArg(NumArgs));
32*700637cbSDimitry Andric Function *F = CGF.CGM.getIntrinsic(IntrinsicID);
33*700637cbSDimitry Andric Value *Call = CGF.Builder.CreateCall(F, Args);
34*700637cbSDimitry Andric Value *CC = CGF.Builder.CreateExtractValue(Call, 1);
35*700637cbSDimitry Andric CGF.Builder.CreateStore(CC, CCPtr);
36*700637cbSDimitry Andric return CGF.Builder.CreateExtractValue(Call, 0);
37*700637cbSDimitry Andric }
38*700637cbSDimitry Andric
EmitSystemZBuiltinExpr(unsigned BuiltinID,const CallExpr * E)39*700637cbSDimitry Andric Value *CodeGenFunction::EmitSystemZBuiltinExpr(unsigned BuiltinID,
40*700637cbSDimitry Andric const CallExpr *E) {
41*700637cbSDimitry Andric switch (BuiltinID) {
42*700637cbSDimitry Andric case SystemZ::BI__builtin_tbegin: {
43*700637cbSDimitry Andric Value *TDB = EmitScalarExpr(E->getArg(0));
44*700637cbSDimitry Andric Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff0c);
45*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::s390_tbegin);
46*700637cbSDimitry Andric return Builder.CreateCall(F, {TDB, Control});
47*700637cbSDimitry Andric }
48*700637cbSDimitry Andric case SystemZ::BI__builtin_tbegin_nofloat: {
49*700637cbSDimitry Andric Value *TDB = EmitScalarExpr(E->getArg(0));
50*700637cbSDimitry Andric Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff0c);
51*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::s390_tbegin_nofloat);
52*700637cbSDimitry Andric return Builder.CreateCall(F, {TDB, Control});
53*700637cbSDimitry Andric }
54*700637cbSDimitry Andric case SystemZ::BI__builtin_tbeginc: {
55*700637cbSDimitry Andric Value *TDB = llvm::ConstantPointerNull::get(Int8PtrTy);
56*700637cbSDimitry Andric Value *Control = llvm::ConstantInt::get(Int32Ty, 0xff08);
57*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::s390_tbeginc);
58*700637cbSDimitry Andric return Builder.CreateCall(F, {TDB, Control});
59*700637cbSDimitry Andric }
60*700637cbSDimitry Andric case SystemZ::BI__builtin_tabort: {
61*700637cbSDimitry Andric Value *Data = EmitScalarExpr(E->getArg(0));
62*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::s390_tabort);
63*700637cbSDimitry Andric return Builder.CreateCall(F, Builder.CreateSExt(Data, Int64Ty, "tabort"));
64*700637cbSDimitry Andric }
65*700637cbSDimitry Andric case SystemZ::BI__builtin_non_tx_store: {
66*700637cbSDimitry Andric Value *Address = EmitScalarExpr(E->getArg(0));
67*700637cbSDimitry Andric Value *Data = EmitScalarExpr(E->getArg(1));
68*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::s390_ntstg);
69*700637cbSDimitry Andric return Builder.CreateCall(F, {Data, Address});
70*700637cbSDimitry Andric }
71*700637cbSDimitry Andric
72*700637cbSDimitry Andric // Vector builtins. Note that most vector builtins are mapped automatically
73*700637cbSDimitry Andric // to target-specific LLVM intrinsics. The ones handled specially here can
74*700637cbSDimitry Andric // be represented via standard LLVM IR, which is preferable to enable common
75*700637cbSDimitry Andric // LLVM optimizations.
76*700637cbSDimitry Andric
77*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vclzb:
78*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vclzh:
79*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vclzf:
80*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vclzg:
81*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vclzq: {
82*700637cbSDimitry Andric llvm::Type *ResultType = ConvertType(E->getType());
83*700637cbSDimitry Andric Value *X = EmitScalarExpr(E->getArg(0));
84*700637cbSDimitry Andric Value *Undef = ConstantInt::get(Builder.getInt1Ty(), false);
85*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ResultType);
86*700637cbSDimitry Andric return Builder.CreateCall(F, {X, Undef});
87*700637cbSDimitry Andric }
88*700637cbSDimitry Andric
89*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vctzb:
90*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vctzh:
91*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vctzf:
92*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vctzg:
93*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vctzq: {
94*700637cbSDimitry Andric llvm::Type *ResultType = ConvertType(E->getType());
95*700637cbSDimitry Andric Value *X = EmitScalarExpr(E->getArg(0));
96*700637cbSDimitry Andric Value *Undef = ConstantInt::get(Builder.getInt1Ty(), false);
97*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::cttz, ResultType);
98*700637cbSDimitry Andric return Builder.CreateCall(F, {X, Undef});
99*700637cbSDimitry Andric }
100*700637cbSDimitry Andric
101*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_verllb:
102*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_verllh:
103*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_verllf:
104*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_verllg: {
105*700637cbSDimitry Andric llvm::Type *ResultType = ConvertType(E->getType());
106*700637cbSDimitry Andric llvm::Value *Src = EmitScalarExpr(E->getArg(0));
107*700637cbSDimitry Andric llvm::Value *Amt = EmitScalarExpr(E->getArg(1));
108*700637cbSDimitry Andric // Splat scalar rotate amount to vector type.
109*700637cbSDimitry Andric unsigned NumElts = cast<llvm::FixedVectorType>(ResultType)->getNumElements();
110*700637cbSDimitry Andric Amt = Builder.CreateIntCast(Amt, ResultType->getScalarType(), false);
111*700637cbSDimitry Andric Amt = Builder.CreateVectorSplat(NumElts, Amt);
112*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::fshl, ResultType);
113*700637cbSDimitry Andric return Builder.CreateCall(F, { Src, Src, Amt });
114*700637cbSDimitry Andric }
115*700637cbSDimitry Andric
116*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_verllvb:
117*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_verllvh:
118*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_verllvf:
119*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_verllvg: {
120*700637cbSDimitry Andric llvm::Type *ResultType = ConvertType(E->getType());
121*700637cbSDimitry Andric llvm::Value *Src = EmitScalarExpr(E->getArg(0));
122*700637cbSDimitry Andric llvm::Value *Amt = EmitScalarExpr(E->getArg(1));
123*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::fshl, ResultType);
124*700637cbSDimitry Andric return Builder.CreateCall(F, { Src, Src, Amt });
125*700637cbSDimitry Andric }
126*700637cbSDimitry Andric
127*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfsqsb:
128*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfsqdb: {
129*700637cbSDimitry Andric llvm::Type *ResultType = ConvertType(E->getType());
130*700637cbSDimitry Andric Value *X = EmitScalarExpr(E->getArg(0));
131*700637cbSDimitry Andric if (Builder.getIsFPConstrained()) {
132*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::experimental_constrained_sqrt, ResultType);
133*700637cbSDimitry Andric return Builder.CreateConstrainedFPCall(F, { X });
134*700637cbSDimitry Andric } else {
135*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::sqrt, ResultType);
136*700637cbSDimitry Andric return Builder.CreateCall(F, X);
137*700637cbSDimitry Andric }
138*700637cbSDimitry Andric }
139*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfmasb:
140*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfmadb: {
141*700637cbSDimitry Andric llvm::Type *ResultType = ConvertType(E->getType());
142*700637cbSDimitry Andric Value *X = EmitScalarExpr(E->getArg(0));
143*700637cbSDimitry Andric Value *Y = EmitScalarExpr(E->getArg(1));
144*700637cbSDimitry Andric Value *Z = EmitScalarExpr(E->getArg(2));
145*700637cbSDimitry Andric if (Builder.getIsFPConstrained()) {
146*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::experimental_constrained_fma, ResultType);
147*700637cbSDimitry Andric return Builder.CreateConstrainedFPCall(F, {X, Y, Z});
148*700637cbSDimitry Andric } else {
149*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType);
150*700637cbSDimitry Andric return Builder.CreateCall(F, {X, Y, Z});
151*700637cbSDimitry Andric }
152*700637cbSDimitry Andric }
153*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfmssb:
154*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfmsdb: {
155*700637cbSDimitry Andric llvm::Type *ResultType = ConvertType(E->getType());
156*700637cbSDimitry Andric Value *X = EmitScalarExpr(E->getArg(0));
157*700637cbSDimitry Andric Value *Y = EmitScalarExpr(E->getArg(1));
158*700637cbSDimitry Andric Value *Z = EmitScalarExpr(E->getArg(2));
159*700637cbSDimitry Andric if (Builder.getIsFPConstrained()) {
160*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::experimental_constrained_fma, ResultType);
161*700637cbSDimitry Andric return Builder.CreateConstrainedFPCall(F, {X, Y, Builder.CreateFNeg(Z, "neg")});
162*700637cbSDimitry Andric } else {
163*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType);
164*700637cbSDimitry Andric return Builder.CreateCall(F, {X, Y, Builder.CreateFNeg(Z, "neg")});
165*700637cbSDimitry Andric }
166*700637cbSDimitry Andric }
167*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfnmasb:
168*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfnmadb: {
169*700637cbSDimitry Andric llvm::Type *ResultType = ConvertType(E->getType());
170*700637cbSDimitry Andric Value *X = EmitScalarExpr(E->getArg(0));
171*700637cbSDimitry Andric Value *Y = EmitScalarExpr(E->getArg(1));
172*700637cbSDimitry Andric Value *Z = EmitScalarExpr(E->getArg(2));
173*700637cbSDimitry Andric if (Builder.getIsFPConstrained()) {
174*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::experimental_constrained_fma, ResultType);
175*700637cbSDimitry Andric return Builder.CreateFNeg(Builder.CreateConstrainedFPCall(F, {X, Y, Z}), "neg");
176*700637cbSDimitry Andric } else {
177*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType);
178*700637cbSDimitry Andric return Builder.CreateFNeg(Builder.CreateCall(F, {X, Y, Z}), "neg");
179*700637cbSDimitry Andric }
180*700637cbSDimitry Andric }
181*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfnmssb:
182*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfnmsdb: {
183*700637cbSDimitry Andric llvm::Type *ResultType = ConvertType(E->getType());
184*700637cbSDimitry Andric Value *X = EmitScalarExpr(E->getArg(0));
185*700637cbSDimitry Andric Value *Y = EmitScalarExpr(E->getArg(1));
186*700637cbSDimitry Andric Value *Z = EmitScalarExpr(E->getArg(2));
187*700637cbSDimitry Andric if (Builder.getIsFPConstrained()) {
188*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::experimental_constrained_fma, ResultType);
189*700637cbSDimitry Andric Value *NegZ = Builder.CreateFNeg(Z, "sub");
190*700637cbSDimitry Andric return Builder.CreateFNeg(Builder.CreateConstrainedFPCall(F, {X, Y, NegZ}));
191*700637cbSDimitry Andric } else {
192*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::fma, ResultType);
193*700637cbSDimitry Andric Value *NegZ = Builder.CreateFNeg(Z, "neg");
194*700637cbSDimitry Andric return Builder.CreateFNeg(Builder.CreateCall(F, {X, Y, NegZ}));
195*700637cbSDimitry Andric }
196*700637cbSDimitry Andric }
197*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vflpsb:
198*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vflpdb: {
199*700637cbSDimitry Andric llvm::Type *ResultType = ConvertType(E->getType());
200*700637cbSDimitry Andric Value *X = EmitScalarExpr(E->getArg(0));
201*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::fabs, ResultType);
202*700637cbSDimitry Andric return Builder.CreateCall(F, X);
203*700637cbSDimitry Andric }
204*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vflnsb:
205*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vflndb: {
206*700637cbSDimitry Andric llvm::Type *ResultType = ConvertType(E->getType());
207*700637cbSDimitry Andric Value *X = EmitScalarExpr(E->getArg(0));
208*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::fabs, ResultType);
209*700637cbSDimitry Andric return Builder.CreateFNeg(Builder.CreateCall(F, X), "neg");
210*700637cbSDimitry Andric }
211*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfisb:
212*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfidb: {
213*700637cbSDimitry Andric llvm::Type *ResultType = ConvertType(E->getType());
214*700637cbSDimitry Andric Value *X = EmitScalarExpr(E->getArg(0));
215*700637cbSDimitry Andric // Constant-fold the M4 and M5 mask arguments.
216*700637cbSDimitry Andric llvm::APSInt M4 = *E->getArg(1)->getIntegerConstantExpr(getContext());
217*700637cbSDimitry Andric llvm::APSInt M5 = *E->getArg(2)->getIntegerConstantExpr(getContext());
218*700637cbSDimitry Andric // Check whether this instance can be represented via a LLVM standard
219*700637cbSDimitry Andric // intrinsic. We only support some combinations of M4 and M5.
220*700637cbSDimitry Andric Intrinsic::ID ID = Intrinsic::not_intrinsic;
221*700637cbSDimitry Andric Intrinsic::ID CI;
222*700637cbSDimitry Andric switch (M4.getZExtValue()) {
223*700637cbSDimitry Andric default: break;
224*700637cbSDimitry Andric case 0: // IEEE-inexact exception allowed
225*700637cbSDimitry Andric switch (M5.getZExtValue()) {
226*700637cbSDimitry Andric default: break;
227*700637cbSDimitry Andric case 0: ID = Intrinsic::rint;
228*700637cbSDimitry Andric CI = Intrinsic::experimental_constrained_rint; break;
229*700637cbSDimitry Andric }
230*700637cbSDimitry Andric break;
231*700637cbSDimitry Andric case 4: // IEEE-inexact exception suppressed
232*700637cbSDimitry Andric switch (M5.getZExtValue()) {
233*700637cbSDimitry Andric default: break;
234*700637cbSDimitry Andric case 0: ID = Intrinsic::nearbyint;
235*700637cbSDimitry Andric CI = Intrinsic::experimental_constrained_nearbyint; break;
236*700637cbSDimitry Andric case 1: ID = Intrinsic::round;
237*700637cbSDimitry Andric CI = Intrinsic::experimental_constrained_round; break;
238*700637cbSDimitry Andric case 4: ID = Intrinsic::roundeven;
239*700637cbSDimitry Andric CI = Intrinsic::experimental_constrained_roundeven; break;
240*700637cbSDimitry Andric case 5: ID = Intrinsic::trunc;
241*700637cbSDimitry Andric CI = Intrinsic::experimental_constrained_trunc; break;
242*700637cbSDimitry Andric case 6: ID = Intrinsic::ceil;
243*700637cbSDimitry Andric CI = Intrinsic::experimental_constrained_ceil; break;
244*700637cbSDimitry Andric case 7: ID = Intrinsic::floor;
245*700637cbSDimitry Andric CI = Intrinsic::experimental_constrained_floor; break;
246*700637cbSDimitry Andric }
247*700637cbSDimitry Andric break;
248*700637cbSDimitry Andric }
249*700637cbSDimitry Andric if (ID != Intrinsic::not_intrinsic) {
250*700637cbSDimitry Andric if (Builder.getIsFPConstrained()) {
251*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(CI, ResultType);
252*700637cbSDimitry Andric return Builder.CreateConstrainedFPCall(F, X);
253*700637cbSDimitry Andric } else {
254*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(ID, ResultType);
255*700637cbSDimitry Andric return Builder.CreateCall(F, X);
256*700637cbSDimitry Andric }
257*700637cbSDimitry Andric }
258*700637cbSDimitry Andric switch (BuiltinID) { // FIXME: constrained version?
259*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfisb: ID = Intrinsic::s390_vfisb; break;
260*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfidb: ID = Intrinsic::s390_vfidb; break;
261*700637cbSDimitry Andric default: llvm_unreachable("Unknown BuiltinID");
262*700637cbSDimitry Andric }
263*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(ID);
264*700637cbSDimitry Andric Value *M4Value = llvm::ConstantInt::get(getLLVMContext(), M4);
265*700637cbSDimitry Andric Value *M5Value = llvm::ConstantInt::get(getLLVMContext(), M5);
266*700637cbSDimitry Andric return Builder.CreateCall(F, {X, M4Value, M5Value});
267*700637cbSDimitry Andric }
268*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfmaxsb:
269*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfmaxdb: {
270*700637cbSDimitry Andric llvm::Type *ResultType = ConvertType(E->getType());
271*700637cbSDimitry Andric Value *X = EmitScalarExpr(E->getArg(0));
272*700637cbSDimitry Andric Value *Y = EmitScalarExpr(E->getArg(1));
273*700637cbSDimitry Andric // Constant-fold the M4 mask argument.
274*700637cbSDimitry Andric llvm::APSInt M4 = *E->getArg(2)->getIntegerConstantExpr(getContext());
275*700637cbSDimitry Andric // Check whether this instance can be represented via a LLVM standard
276*700637cbSDimitry Andric // intrinsic. We only support some values of M4.
277*700637cbSDimitry Andric Intrinsic::ID ID = Intrinsic::not_intrinsic;
278*700637cbSDimitry Andric Intrinsic::ID CI;
279*700637cbSDimitry Andric switch (M4.getZExtValue()) {
280*700637cbSDimitry Andric default: break;
281*700637cbSDimitry Andric case 4: ID = Intrinsic::maxnum;
282*700637cbSDimitry Andric CI = Intrinsic::experimental_constrained_maxnum; break;
283*700637cbSDimitry Andric }
284*700637cbSDimitry Andric if (ID != Intrinsic::not_intrinsic) {
285*700637cbSDimitry Andric if (Builder.getIsFPConstrained()) {
286*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(CI, ResultType);
287*700637cbSDimitry Andric return Builder.CreateConstrainedFPCall(F, {X, Y});
288*700637cbSDimitry Andric } else {
289*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(ID, ResultType);
290*700637cbSDimitry Andric return Builder.CreateCall(F, {X, Y});
291*700637cbSDimitry Andric }
292*700637cbSDimitry Andric }
293*700637cbSDimitry Andric switch (BuiltinID) {
294*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfmaxsb: ID = Intrinsic::s390_vfmaxsb; break;
295*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfmaxdb: ID = Intrinsic::s390_vfmaxdb; break;
296*700637cbSDimitry Andric default: llvm_unreachable("Unknown BuiltinID");
297*700637cbSDimitry Andric }
298*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(ID);
299*700637cbSDimitry Andric Value *M4Value = llvm::ConstantInt::get(getLLVMContext(), M4);
300*700637cbSDimitry Andric return Builder.CreateCall(F, {X, Y, M4Value});
301*700637cbSDimitry Andric }
302*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfminsb:
303*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfmindb: {
304*700637cbSDimitry Andric llvm::Type *ResultType = ConvertType(E->getType());
305*700637cbSDimitry Andric Value *X = EmitScalarExpr(E->getArg(0));
306*700637cbSDimitry Andric Value *Y = EmitScalarExpr(E->getArg(1));
307*700637cbSDimitry Andric // Constant-fold the M4 mask argument.
308*700637cbSDimitry Andric llvm::APSInt M4 = *E->getArg(2)->getIntegerConstantExpr(getContext());
309*700637cbSDimitry Andric // Check whether this instance can be represented via a LLVM standard
310*700637cbSDimitry Andric // intrinsic. We only support some values of M4.
311*700637cbSDimitry Andric Intrinsic::ID ID = Intrinsic::not_intrinsic;
312*700637cbSDimitry Andric Intrinsic::ID CI;
313*700637cbSDimitry Andric switch (M4.getZExtValue()) {
314*700637cbSDimitry Andric default: break;
315*700637cbSDimitry Andric case 4: ID = Intrinsic::minnum;
316*700637cbSDimitry Andric CI = Intrinsic::experimental_constrained_minnum; break;
317*700637cbSDimitry Andric }
318*700637cbSDimitry Andric if (ID != Intrinsic::not_intrinsic) {
319*700637cbSDimitry Andric if (Builder.getIsFPConstrained()) {
320*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(CI, ResultType);
321*700637cbSDimitry Andric return Builder.CreateConstrainedFPCall(F, {X, Y});
322*700637cbSDimitry Andric } else {
323*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(ID, ResultType);
324*700637cbSDimitry Andric return Builder.CreateCall(F, {X, Y});
325*700637cbSDimitry Andric }
326*700637cbSDimitry Andric }
327*700637cbSDimitry Andric switch (BuiltinID) {
328*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfminsb: ID = Intrinsic::s390_vfminsb; break;
329*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vfmindb: ID = Intrinsic::s390_vfmindb; break;
330*700637cbSDimitry Andric default: llvm_unreachable("Unknown BuiltinID");
331*700637cbSDimitry Andric }
332*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(ID);
333*700637cbSDimitry Andric Value *M4Value = llvm::ConstantInt::get(getLLVMContext(), M4);
334*700637cbSDimitry Andric return Builder.CreateCall(F, {X, Y, M4Value});
335*700637cbSDimitry Andric }
336*700637cbSDimitry Andric
337*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vlbrh:
338*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vlbrf:
339*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vlbrg:
340*700637cbSDimitry Andric case SystemZ::BI__builtin_s390_vlbrq: {
341*700637cbSDimitry Andric llvm::Type *ResultType = ConvertType(E->getType());
342*700637cbSDimitry Andric Value *X = EmitScalarExpr(E->getArg(0));
343*700637cbSDimitry Andric Function *F = CGM.getIntrinsic(Intrinsic::bswap, ResultType);
344*700637cbSDimitry Andric return Builder.CreateCall(F, X);
345*700637cbSDimitry Andric }
346*700637cbSDimitry Andric
347*700637cbSDimitry Andric // Vector intrinsics that output the post-instruction CC value.
348*700637cbSDimitry Andric
349*700637cbSDimitry Andric #define INTRINSIC_WITH_CC(NAME) \
350*700637cbSDimitry Andric case SystemZ::BI__builtin_##NAME: \
351*700637cbSDimitry Andric return EmitSystemZIntrinsicWithCC(*this, Intrinsic::NAME, E)
352*700637cbSDimitry Andric
353*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vpkshs);
354*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vpksfs);
355*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vpksgs);
356*700637cbSDimitry Andric
357*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vpklshs);
358*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vpklsfs);
359*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vpklsgs);
360*700637cbSDimitry Andric
361*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vceqbs);
362*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vceqhs);
363*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vceqfs);
364*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vceqgs);
365*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vceqqs);
366*700637cbSDimitry Andric
367*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vchbs);
368*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vchhs);
369*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vchfs);
370*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vchgs);
371*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vchqs);
372*700637cbSDimitry Andric
373*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vchlbs);
374*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vchlhs);
375*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vchlfs);
376*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vchlgs);
377*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vchlqs);
378*700637cbSDimitry Andric
379*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfaebs);
380*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfaehs);
381*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfaefs);
382*700637cbSDimitry Andric
383*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfaezbs);
384*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfaezhs);
385*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfaezfs);
386*700637cbSDimitry Andric
387*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfeebs);
388*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfeehs);
389*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfeefs);
390*700637cbSDimitry Andric
391*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfeezbs);
392*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfeezhs);
393*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfeezfs);
394*700637cbSDimitry Andric
395*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfenebs);
396*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfenehs);
397*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfenefs);
398*700637cbSDimitry Andric
399*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfenezbs);
400*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfenezhs);
401*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfenezfs);
402*700637cbSDimitry Andric
403*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vistrbs);
404*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vistrhs);
405*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vistrfs);
406*700637cbSDimitry Andric
407*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vstrcbs);
408*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vstrchs);
409*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vstrcfs);
410*700637cbSDimitry Andric
411*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vstrczbs);
412*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vstrczhs);
413*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vstrczfs);
414*700637cbSDimitry Andric
415*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfcesbs);
416*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfcedbs);
417*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfchsbs);
418*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfchdbs);
419*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfchesbs);
420*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vfchedbs);
421*700637cbSDimitry Andric
422*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vftcisb);
423*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vftcidb);
424*700637cbSDimitry Andric
425*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vstrsb);
426*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vstrsh);
427*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vstrsf);
428*700637cbSDimitry Andric
429*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vstrszb);
430*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vstrszh);
431*700637cbSDimitry Andric INTRINSIC_WITH_CC(s390_vstrszf);
432*700637cbSDimitry Andric
433*700637cbSDimitry Andric #undef INTRINSIC_WITH_CC
434*700637cbSDimitry Andric
435*700637cbSDimitry Andric default:
436*700637cbSDimitry Andric return nullptr;
437*700637cbSDimitry Andric }
438*700637cbSDimitry Andric }
439