clang 24.0.0git
CIRGenBuiltinX86.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code to emit x86/x86_64 Builtin calls as CIR or a function
10// call to be later resolved.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CIRGenBuilder.h"
15#include "CIRGenFunction.h"
16#include "CIRGenModule.h"
17#include "mlir/IR/Attributes.h"
18#include "mlir/IR/BuiltinAttributes.h"
19#include "mlir/IR/Location.h"
20#include "mlir/IR/Types.h"
21#include "mlir/IR/ValueRange.h"
27#include "llvm/ADT/Sequence.h"
28#include "llvm/Support/ErrorHandling.h"
29#include <string>
30
31using namespace clang;
32using namespace clang::CIRGen;
33
34// OG has unordered comparison as a form of optimization in addition to
35// ordered comparison, while CIR doesn't.
36//
37// This means that we can't encode the comparison code of UGT (unordered
38// greater than), at least not at the CIR level.
39//
40// The boolean shouldInvert compensates for this.
41// For example: to get to the comparison code UGT, we pass in
42// emitVectorFCmp (OLE, shouldInvert = true) since OLE is the inverse of UGT.
43
44// There are several ways to support this otherwise:
45// - register extra CmpOpKind for unordered comparison types and build the
46// translation code for
47// to go from CIR -> LLVM dialect. Notice we get this naturally with
48// shouldInvert, benefiting from existing infrastructure, albeit having to
49// generate an extra `not` at CIR).
50// - Just add extra comparison code to a new VecCmpOpKind instead of
51// cluttering CmpOpKind.
52// - Add a boolean in VecCmpOp to indicate if it's doing unordered or ordered
53// comparison
54// - Just emit the intrinsics call instead of calling this helper, see how the
55// LLVM lowering handles this.
56static mlir::Value emitVectorFCmp(CIRGenFunction &cgf, const CallExpr &expr,
58 cir::CmpOpKind pred, bool shouldInvert) {
60 // TODO(cir): Add isSignaling boolean once emitConstrainedFPCall implemented
63 mlir::Value cmp = builder.createVecCompare(cgf.getLoc(expr.getExprLoc()),
64 pred, ops[0], ops[1]);
65 mlir::Value bitCast = builder.createBitcast(
66 shouldInvert ? builder.createNot(cmp) : cmp, ops[0].getType());
67 return bitCast;
68}
69
70static mlir::Value getMaskVecValue(CIRGenBuilderTy &builder, mlir::Location loc,
71 mlir::Value mask, unsigned numElems) {
72 auto maskTy = cir::VectorType::get(
73 builder.getSIntNTy(1), cast<cir::IntType>(mask.getType()).getWidth());
74 mlir::Value maskVec = builder.createBitcast(mask, maskTy);
75
76 // If we have less than 8 elements, then the starting mask was an i8 and
77 // we need to extract down to the right number of elements.
78 if (numElems < 8) {
80 mlir::Type i32Ty = builder.getSInt32Ty();
81 for (auto i : llvm::seq<unsigned>(0, numElems))
82 indices.push_back(cir::IntAttr::get(i32Ty, i));
83
84 maskVec = builder.createVecShuffle(loc, maskVec, maskVec, indices);
85 }
86 return maskVec;
87}
88
89static mlir::Value emitX86CompressStore(CIRGenBuilderTy &builder,
90 mlir::Location loc,
92 auto resultTy = cast<cir::VectorType>(ops[1].getType());
93 mlir::Value maskValue =
94 getMaskVecValue(builder, loc, ops[2], resultTy.getSize());
95
96 return builder.emitIntrinsicCallOp(
97 loc, "masked.compressstore", cir::VoidType::get(builder.getContext()),
98 mlir::ValueRange{ops[1], ops[0], maskValue});
99}
100
101// Builds the VecShuffleOp for pshuflw and pshufhw x86 builtins.
102//
103// The vector is split into lanes of 8 word elements (16 bits). The lower or
104// upper half of each lane, controlled by `isLow`, is shuffled in the following
105// way: The immediate is truncated to 8 bits, separated into 4 2-bit fields. The
106// i-th field's value represents the resulting index of the i-th element in the
107// half lane after shuffling. The other half of the lane remains unchanged.
108static cir::VecShuffleOp emitPshufWord(CIRGenBuilderTy &builder,
109 const mlir::Value vec,
110 const mlir::Value immediate,
111 const mlir::Location loc,
112 const bool isLow) {
114
115 auto vecTy = cast<cir::VectorType>(vec.getType());
116 unsigned numElts = vecTy.getSize();
117
118 unsigned firstHalfStart = isLow ? 0 : 4;
119 unsigned secondHalfStart = 4 - firstHalfStart;
120
121 // Splat the 8-bits of immediate 4 times to help the loop wrap around.
122 imm = (imm & 0xff) * 0x01010101;
123
124 int64_t indices[32];
125 for (unsigned l = 0; l != numElts; l += 8) {
126 for (unsigned i = firstHalfStart; i != firstHalfStart + 4; ++i) {
127 indices[l + i] = l + (imm & 3) + firstHalfStart;
128 imm >>= 2;
129 }
130 for (unsigned i = secondHalfStart; i != secondHalfStart + 4; ++i)
131 indices[l + i] = l + i;
132 }
133
134 return builder.createVecShuffle(loc, vec, ArrayRef(indices, numElts));
135}
136
137// Builds the shuffle mask for pshufd and shufpd/shufps x86 builtins.
138// The shuffle mask is written to outIndices.
139static void
140computeFullLaneShuffleMask(CIRGenFunction &cgf, const mlir::Value vec,
141 uint32_t imm, const bool isShufP,
142 llvm::SmallVectorImpl<int64_t> &outIndices) {
143 auto vecTy = cast<cir::VectorType>(vec.getType());
144 unsigned numElts = vecTy.getSize();
145 unsigned numLanes = cgf.cgm.getDataLayout().getTypeSizeInBits(vecTy) / 128;
146 unsigned numLaneElts = numElts / numLanes;
147
148 // Splat the 8-bits of immediate 4 times to help the loop wrap around.
149 imm = (imm & 0xff) * 0x01010101;
150
151 for (unsigned l = 0; l != numElts; l += numLaneElts) {
152 for (unsigned i = 0; i != numLaneElts; ++i) {
153 uint32_t idx = imm % numLaneElts;
154 imm /= numLaneElts;
155 if (isShufP && i >= (numLaneElts / 2))
156 idx += numElts;
157 outIndices[l + i] = l + idx;
158 }
159 }
160
161 outIndices.resize(numElts);
162}
163
164static mlir::Value emitPrefetch(CIRGenFunction &cgf, unsigned builtinID,
165 const CallExpr *e,
166 const SmallVector<mlir::Value> &ops) {
167 CIRGenBuilderTy &builder = cgf.getBuilder();
168 mlir::Location location = cgf.getLoc(e->getExprLoc());
169 mlir::Type voidTy = builder.getVoidTy();
170 mlir::Value address = builder.createPtrBitcast(ops[0], voidTy);
171 bool isWrite{};
172 int locality{};
173
174 assert(builtinID == X86::BI_mm_prefetch || builtinID == X86::BI_m_prefetchw ||
175 builtinID == X86::BI_m_prefetch && "Expected prefetch builtin");
176
177 if (builtinID == X86::BI_mm_prefetch) {
178 int hint = cgf.getSExtIntValueFromConstOp(ops[1]);
179 isWrite = (hint >> 2) & 0x1;
180 locality = hint & 0x3;
181 } else {
182 isWrite = (builtinID == X86::BI_m_prefetchw);
183 locality = 0x3;
184 }
185
186 cir::PrefetchOp::create(builder, location, address, locality, isWrite);
187 return {};
188}
189
190static mlir::Value emitX86CompressExpand(CIRGenBuilderTy &builder,
191 mlir::Location loc, mlir::Value source,
192 mlir::Value mask,
193 mlir::Value inputVector,
194 const std::string &id) {
195 auto resultTy = cast<cir::VectorType>(mask.getType());
196 mlir::Value maskValue = getMaskVecValue(
197 builder, loc, inputVector, cast<cir::VectorType>(resultTy).getSize());
198 return builder.emitIntrinsicCallOp(loc, id, resultTy,
199 mlir::ValueRange{source, mask, maskValue});
200}
201
202static mlir::Value
203emitEncodeKey(mlir::MLIRContext *context, CIRGenBuilderTy &builder,
204 const mlir::Location &location, mlir::ValueRange inputOperands,
205 mlir::Value outputOperand, std::uint8_t vecOutputCount,
206 const std::string &intrinsicName, std::uint8_t numResults) {
207 cir::VectorType resVector = cir::VectorType::get(builder.getUInt64Ty(), 2);
209 llvm::append_range(members,
210 llvm::SmallVector<mlir::Type>(vecOutputCount, resVector));
211 cir::StructType resRecord = cir::StructType::get(
212 context, members, /*packed=*/false, /*padded=*/false, /*is_class=*/false);
213
214 mlir::Value outputPtr =
215 builder.createBitcast(outputOperand, cir::PointerType::get(resVector));
216 mlir::Value call = builder.emitIntrinsicCallOp(location, intrinsicName,
217 resRecord, inputOperands);
218 for (std::uint8_t i = 0; i < numResults; ++i) {
219 mlir::Value vecValue =
220 cir::ExtractMemberOp::create(builder, location, call, i + 1);
221 mlir::Value index = builder.getSInt32(i, location);
222 mlir::Value ptr = builder.createPtrStride(location, outputPtr, index);
223 builder.createStore(location, vecValue, Address{ptr, CharUnits::One()});
224 }
225 return cir::ExtractMemberOp::create(builder, location, call, 0);
226}
227
228static mlir::Value emitX86Select(CIRGenBuilderTy &builder, mlir::Location loc,
229 mlir::Value mask, mlir::Value op0,
230 mlir::Value op1) {
231 auto constOp = mlir::dyn_cast_or_null<cir::ConstantOp>(mask.getDefiningOp());
232 // If the mask is all ones just return first argument.
233 if (constOp && constOp.isAllOnesValue())
234 return op0;
235
236 mask = getMaskVecValue(builder, loc, mask,
237 cast<cir::VectorType>(op0.getType()).getSize());
238
239 return cir::VecTernaryOp::create(builder, loc, mask, op0, op1);
240}
241
242// Helper function to extract zero-bit from a mask as a boolean
243static mlir::Value getMaskZeroBitAsBool(CIRGenBuilderTy &builder,
244 mlir::Location loc, mlir::Value mask) {
245 // Get the mask as a vector of i1 and extract bit 0
246 auto intTy = mlir::dyn_cast<cir::IntType>(mask.getType());
247 assert(intTy && "mask must be an integer type");
248 unsigned width = intTy.getWidth();
249
250 auto maskVecTy = cir::VectorType::get(builder.getSIntNTy(1), width);
251 mlir::Value maskVec = builder.createBitcast(mask, maskVecTy);
252
253 // Extract bit 0 from the mask vector
254 mlir::Value bit0 = builder.createExtractElement(loc, maskVec, uint64_t(0));
255
256 // Convert i1 to bool for select
257 auto boolTy = cir::BoolType::get(builder.getContext());
258 return cir::CastOp::create(builder, loc, boolTy, cir::CastKind::int_to_bool,
259 bit0);
260}
261
262static mlir::Value emitX86ScalarSelect(CIRGenBuilderTy &builder,
263 mlir::Location loc, mlir::Value mask,
264 mlir::Value op0, mlir::Value op1) {
265
266 // If the mask is all ones just return first argument.
267 if (auto c = mlir::dyn_cast_or_null<cir::ConstantOp>(mask.getDefiningOp()))
268 if (c.isAllOnesValue())
269 return op0;
270
271 mlir::Value cond = getMaskZeroBitAsBool(builder, loc, mask);
272 return builder.createSelect(loc, cond, op0, op1);
273}
274
275static mlir::Value emitX86MaskAddLogic(CIRGenBuilderTy &builder,
276 mlir::Location loc,
277 const std::string &intrinsicName,
279
280 auto intTy = cast<cir::IntType>(ops[0].getType());
281 unsigned numElts = intTy.getWidth();
282 mlir::Value lhsVec = getMaskVecValue(builder, loc, ops[0], numElts);
283 mlir::Value rhsVec = getMaskVecValue(builder, loc, ops[1], numElts);
284 mlir::Type vecTy = lhsVec.getType();
285 mlir::Value resVec = builder.emitIntrinsicCallOp(
286 loc, intrinsicName, vecTy, mlir::ValueRange{lhsVec, rhsVec});
287 return builder.createBitcast(resVec, ops[0].getType());
288}
289
290static mlir::Value emitX86MaskUnpack(CIRGenBuilderTy &builder,
291 mlir::Location loc,
292 const std::string &intrinsicName,
294 unsigned numElems = cast<cir::IntType>(ops[0].getType()).getWidth();
295
296 // Convert both operands to mask vectors.
297 mlir::Value lhs = getMaskVecValue(builder, loc, ops[0], numElems);
298 mlir::Value rhs = getMaskVecValue(builder, loc, ops[1], numElems);
299
300 mlir::Type i32Ty = builder.getSInt32Ty();
301
302 // Create indices for extracting the first half of each vector.
304 for (auto i : llvm::seq<unsigned>(0, numElems / 2))
305 halfIndices.push_back(cir::IntAttr::get(i32Ty, i));
306
307 // Extract first half of each vector. This gives better codegen than
308 // doing it in a single shuffle.
309 mlir::Value lhsHalf = builder.createVecShuffle(loc, lhs, lhs, halfIndices);
310 mlir::Value rhsHalf = builder.createVecShuffle(loc, rhs, rhs, halfIndices);
311
312 // Create indices for concatenating the vectors.
313 // NOTE: Operands are swapped to match the intrinsic definition.
314 // After the half extraction, both vectors have numElems/2 elements.
315 // In createVecShuffle(rhsHalf, lhsHalf, indices), indices [0..numElems/2-1]
316 // select from rhsHalf, and indices [numElems/2..numElems-1] select from
317 // lhsHalf.
319 for (auto i : llvm::seq<unsigned>(0, numElems))
320 concatIndices.push_back(cir::IntAttr::get(i32Ty, i));
321
322 // Concat the vectors (RHS first, then LHS).
323 mlir::Value res =
324 builder.createVecShuffle(loc, rhsHalf, lhsHalf, concatIndices);
325 return builder.createBitcast(res, ops[0].getType());
326}
327
328template <typename BinOp>
329static mlir::Value
330emitX86MaskLogic(CIRGenBuilderTy &builder, mlir::Location loc,
331 SmallVectorImpl<mlir::Value> &ops, bool invertLHS = false) {
332 unsigned numElts = cast<cir::IntType>(ops[0].getType()).getWidth();
333 mlir::Value lhs = getMaskVecValue(builder, loc, ops[0], numElts);
334 mlir::Value rhs = getMaskVecValue(builder, loc, ops[1], numElts);
335
336 if (invertLHS)
337 lhs = builder.createNot(lhs);
338 return builder.createBitcast(BinOp::create(builder, loc, lhs, rhs),
339 ops[0].getType());
340}
341
342static mlir::Value emitX86MaskTest(CIRGenBuilderTy &builder, mlir::Location loc,
343 const std::string &intrinsicName,
345 auto intTy = cast<cir::IntType>(ops[0].getType());
346 unsigned numElts = intTy.getWidth();
347 mlir::Value lhsVec = getMaskVecValue(builder, loc, ops[0], numElts);
348 mlir::Value rhsVec = getMaskVecValue(builder, loc, ops[1], numElts);
349 mlir::Type resTy = builder.getSInt32Ty();
350 return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy,
351 mlir::ValueRange{lhsVec, rhsVec});
352}
353
354static mlir::Value emitX86MaskedCompareResult(CIRGenBuilderTy &builder,
355 mlir::Value cmp, unsigned numElts,
356 mlir::Value maskIn,
357 mlir::Location loc) {
358 if (maskIn) {
359 auto c = mlir::dyn_cast_or_null<cir::ConstantOp>(maskIn.getDefiningOp());
360 if (!c || !c.isAllOnesValue())
361 cmp = builder.createAnd(loc, cmp,
362 getMaskVecValue(builder, loc, maskIn, numElts));
363 }
364 if (numElts < 8) {
366 mlir::Type i64Ty = builder.getSInt64Ty();
367
368 for (unsigned i = 0; i != numElts; ++i)
369 indices.push_back(cir::IntAttr::get(i64Ty, i));
370 for (unsigned i = numElts; i != 8; ++i)
371 indices.push_back(cir::IntAttr::get(i64Ty, i % numElts + numElts));
372
373 // This should shuffle between cmp (first vector) and null (second vector)
374 mlir::Value nullVec = builder.getNullValue(cmp.getType(), loc);
375 cmp = builder.createVecShuffle(loc, cmp, nullVec, indices);
376 }
377 return builder.createBitcast(cmp, builder.getUIntNTy(std::max(numElts, 8U)));
378}
379
380// TODO: The cgf parameter should be removed when all the NYI cases are
381// implemented.
382static std::optional<mlir::Value>
383emitX86MaskedCompare(CIRGenBuilderTy &builder, unsigned cc, bool isSigned,
384 ArrayRef<mlir::Value> ops, mlir::Location loc) {
385 assert((ops.size() == 2 || ops.size() == 4) &&
386 "Unexpected number of arguments");
387 unsigned numElts = cast<cir::VectorType>(ops[0].getType()).getSize();
388 mlir::Value cmp;
389 if (cc == 3) {
390 cmp = builder.getNullValue(
391 cir::VectorType::get(builder.getSIntNTy(1), numElts), loc);
392 } else if (cc == 7) {
393 cir::VectorType resultTy =
394 cir::VectorType::get(builder.getSIntNTy(1), numElts);
395 llvm::APInt allOnes = llvm::APInt::getAllOnes(1);
396 cmp = cir::VecSplatOp::create(
397 builder, loc, resultTy,
398 builder.getConstAPInt(loc, builder.getSIntNTy(1), allOnes));
399 } else {
400 cir::CmpOpKind pred;
401 switch (cc) {
402 default:
403 llvm_unreachable("Unknown condition code");
404 case 0:
405 pred = cir::CmpOpKind::eq;
406 break;
407 case 1:
408 pred = cir::CmpOpKind::lt;
409 break;
410 case 2:
411 pred = cir::CmpOpKind::le;
412 break;
413 case 4:
414 pred = cir::CmpOpKind::ne;
415 break;
416 case 5:
417 pred = cir::CmpOpKind::ge;
418 break;
419 case 6:
420 pred = cir::CmpOpKind::gt;
421 break;
422 }
423
424 auto resultTy = cir::VectorType::get(builder.getSIntNTy(1), numElts);
425 cmp = cir::VecCmpOp::create(builder, loc, resultTy, pred, ops[0], ops[1]);
426 }
427
428 mlir::Value maskIn;
429 if (ops.size() == 4)
430 maskIn = ops[3];
431
432 return emitX86MaskedCompareResult(builder, cmp, numElts, maskIn, loc);
433}
434
435// TODO: The cgf parameter should be removed when all the NYI cases are
436// implemented.
437static std::optional<mlir::Value> emitX86ConvertToMask(CIRGenFunction &cgf,
438 CIRGenBuilderTy &builder,
439 mlir::Value in,
440 mlir::Location loc) {
441 cir::ConstantOp zero = builder.getNullValue(in.getType(), loc);
442 return emitX86MaskedCompare(builder, 1, true, {in, zero}, loc);
443}
444
445static std::optional<mlir::Value> emitX86SExtMask(CIRGenBuilderTy &builder,
446 mlir::Value op,
447 mlir::Type dstTy,
448 mlir::Location loc) {
449 unsigned numberOfElements = cast<cir::VectorType>(dstTy).getSize();
450 mlir::Value mask = getMaskVecValue(builder, loc, op, numberOfElements);
451
452 return builder.createCast(loc, cir::CastKind::integral, mask, dstTy);
453}
454
455static mlir::Value emitVecInsert(CIRGenBuilderTy &builder, mlir::Location loc,
456 mlir::Value vec, mlir::Value value,
457 mlir::Value indexOp) {
458 unsigned numElts = cast<cir::VectorType>(vec.getType()).getSize();
459
460 uint64_t index =
461 indexOp.getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue();
462
463 index &= numElts - 1;
464
465 cir::ConstantOp indexVal = builder.getUInt64(index, loc);
466
467 return cir::VecInsertOp::create(builder, loc, vec, value, indexVal);
468}
469
470static mlir::Value emitX86FunnelShift(CIRGenBuilderTy &builder,
471 mlir::Location location, mlir::Value &op0,
472 mlir::Value &op1, mlir::Value &amt,
473 bool isRight) {
474 mlir::Type op0Ty = op0.getType();
475
476 // Amount may be scalar immediate, in which case create a splat vector.
477 // Funnel shifts amounts are treated as modulo and types are all power-of-2
478 // so we only care about the lowest log2 bits anyway.
479 if (amt.getType() != op0Ty) {
480 auto vecTy = mlir::cast<cir::VectorType>(op0Ty);
481 uint64_t numElems = vecTy.getSize();
482
483 auto amtTy = mlir::cast<cir::IntType>(amt.getType());
484 auto vecElemTy = mlir::cast<cir::IntType>(vecTy.getElementType());
485
486 // If signed, cast to the same width but unsigned first to
487 // ensure zero-extension when casting to a bigger unsigned `vecElemeTy`.
488 if (amtTy.isSigned()) {
489 cir::IntType unsignedAmtTy = builder.getUIntNTy(amtTy.getWidth());
490 amt = builder.createIntCast(amt, unsignedAmtTy);
491 }
492 cir::IntType unsignedVecElemType = builder.getUIntNTy(vecElemTy.getWidth());
493 amt = builder.createIntCast(amt, unsignedVecElemType);
494 amt = cir::VecSplatOp::create(
495 builder, location, cir::VectorType::get(unsignedVecElemType, numElems),
496 amt);
497 }
498
499 const StringRef intrinsicName = isRight ? "fshr" : "fshl";
500 return builder.emitIntrinsicCallOp(location, intrinsicName, op0Ty,
501 mlir::ValueRange{op0, op1, amt});
502}
503
504static mlir::Value emitX86Muldq(CIRGenBuilderTy &builder, mlir::Location loc,
505 bool isSigned,
507 unsigned opTypePrimitiveSizeInBits) {
508 mlir::Type ty = cir::VectorType::get(builder.getSInt64Ty(),
509 opTypePrimitiveSizeInBits / 64);
510 mlir::Value lhs = builder.createBitcast(loc, ops[0], ty);
511 mlir::Value rhs = builder.createBitcast(loc, ops[1], ty);
512 if (isSigned) {
513 cir::ConstantOp shiftAmt =
514 builder.getConstant(loc, cir::IntAttr::get(builder.getSInt64Ty(), 32));
515 cir::VecSplatOp shiftSplatVecOp =
516 cir::VecSplatOp::create(builder, loc, ty, shiftAmt.getResult());
517 mlir::Value shiftSplatValue = shiftSplatVecOp.getResult();
518 // In CIR, right-shift operations are automatically lowered to either an
519 // arithmetic or logical shift depending on the operand type. The purpose
520 // of the shifts here is to propagate the sign bit of the 32-bit input
521 // into the upper bits of each vector lane.
522 lhs = builder.createShift(loc, lhs, shiftSplatValue, true);
523 lhs = builder.createShift(loc, lhs, shiftSplatValue, false);
524 rhs = builder.createShift(loc, rhs, shiftSplatValue, true);
525 rhs = builder.createShift(loc, rhs, shiftSplatValue, false);
526 } else {
527 cir::ConstantOp maskScalar = builder.getConstant(
528 loc, cir::IntAttr::get(builder.getSInt64Ty(), 0xffffffff));
529 cir::VecSplatOp mask =
530 cir::VecSplatOp::create(builder, loc, ty, maskScalar.getResult());
531 // Clear the upper bits
532 lhs = builder.createAnd(loc, lhs, mask);
533 rhs = builder.createAnd(loc, rhs, mask);
534 }
535 return builder.createMul(loc, lhs, rhs);
536}
537
538// Convert f16 half values to floats.
539static mlir::Value emitX86CvtF16ToFloatExpr(CIRGenBuilderTy &builder,
540 mlir::Location loc,
542 mlir::Type dstTy) {
543 assert((ops.size() == 1 || ops.size() == 3 || ops.size() == 4) &&
544 "Unknown cvtph2ps intrinsic");
545
546 // If the SAE intrinsic doesn't use default rounding then we can't upgrade.
547 if (ops.size() == 4) {
548 auto constOp = ops[3].getDefiningOp<cir::ConstantOp>();
549 assert(constOp && "Expected constant operand");
550 if (constOp.getIntValue().getZExtValue() != 4) {
551 return builder.emitIntrinsicCallOp(loc, "x86.avx512.mask.vcvtph2ps.512",
552 dstTy, ops);
553 }
554 }
555
556 unsigned numElts = cast<cir::VectorType>(dstTy).getSize();
557 mlir::Value src = ops[0];
558
559 // Extract the subvector
560 if (numElts != cast<cir::VectorType>(src.getType()).getSize()) {
561 assert(numElts == 4 && "Unexpected vector size");
562 src = builder.createVecShuffle(loc, src, {0, 1, 2, 3});
563 }
564
565 // Bitcast from vXi16 to vXf16.
566 cir::VectorType halfTy =
567 cir::VectorType::get(cir::FP16Type::get(builder.getContext()), numElts);
568
569 src = builder.createCast(cir::CastKind::bitcast, src, halfTy);
570
571 // Perform the fp-extension
572 mlir::Value res = builder.createCast(cir::CastKind::floating, src, dstTy);
573
574 if (ops.size() >= 3)
575 res = emitX86Select(builder, loc, ops[2], res, ops[1]);
576 return res;
577}
578
579static mlir::Value emitX86vpcom(CIRGenBuilderTy &builder, mlir::Location loc,
581 bool isSigned) {
582 mlir::Value op0 = ops[0];
583 mlir::Value op1 = ops[1];
584
585 cir::VectorType ty = cast<cir::VectorType>(op0.getType());
586 cir::IntType elementTy = cast<cir::IntType>(ty.getElementType());
587
588 uint64_t imm = CIRGenFunction::getZExtIntValueFromConstOp(ops[2]) & 0x7;
589
590 cir::CmpOpKind pred;
591 switch (imm) {
592 case 0x0:
593 pred = cir::CmpOpKind::lt;
594 break;
595 case 0x1:
596 pred = cir::CmpOpKind::le;
597 break;
598 case 0x2:
599 pred = cir::CmpOpKind::gt;
600 break;
601 case 0x3:
602 pred = cir::CmpOpKind::ge;
603 break;
604 case 0x4:
605 pred = cir::CmpOpKind::eq;
606 break;
607 case 0x5:
608 pred = cir::CmpOpKind::ne;
609 break;
610 case 0x6:
611 return builder.getNullValue(ty, loc); // FALSE
612 case 0x7: {
613 llvm::APInt allOnes = llvm::APInt::getAllOnes(elementTy.getWidth());
614 return cir::VecSplatOp::create(
615 builder, loc, ty,
616 builder.getConstAPInt(loc, elementTy, allOnes)); // TRUE
617 }
618 default:
619 llvm_unreachable("Unexpected XOP vpcom/vpcomu predicate");
620 }
621
622 if ((!isSigned && elementTy.isSigned()) ||
623 (isSigned && elementTy.isUnsigned())) {
624 elementTy = elementTy.isSigned() ? builder.getUIntNTy(elementTy.getWidth())
625 : builder.getSIntNTy(elementTy.getWidth());
626 ty = cir::VectorType::get(elementTy, ty.getSize());
627 op0 = builder.createBitcast(op0, ty);
628 op1 = builder.createBitcast(op1, ty);
629 }
630
631 return builder.createVecCompare(loc, pred, op0, op1);
632}
633
634static mlir::Value emitX86Fpclass(CIRGenBuilderTy &builder, mlir::Location loc,
635 unsigned builtinID,
637 unsigned numElts = cast<cir::VectorType>(ops[0].getType()).getSize();
638 mlir::Value maskIn = ops[2];
639 ops.erase(ops.begin() + 2);
640
641 StringRef intrinsicName;
642 switch (builtinID) {
643 default:
644 llvm_unreachable("Unsupported fpclass builtin");
645 case X86::BI__builtin_ia32_vfpclassbf16128_mask:
646 intrinsicName = "x86.avx10.fpclass.bf16.128";
647 break;
648 case X86::BI__builtin_ia32_vfpclassbf16256_mask:
649 intrinsicName = "x86.avx10.fpclass.bf16.256";
650 break;
651 case X86::BI__builtin_ia32_vfpclassbf16512_mask:
652 intrinsicName = "x86.avx10.fpclass.bf16.512";
653 break;
654 case X86::BI__builtin_ia32_fpclassph128_mask:
655 intrinsicName = "x86.avx512fp16.fpclass.ph.128";
656 break;
657 case X86::BI__builtin_ia32_fpclassph256_mask:
658 intrinsicName = "x86.avx512fp16.fpclass.ph.256";
659 break;
660 case X86::BI__builtin_ia32_fpclassph512_mask:
661 intrinsicName = "x86.avx512fp16.fpclass.ph.512";
662 break;
663 case X86::BI__builtin_ia32_fpclassps128_mask:
664 intrinsicName = "x86.avx512.fpclass.ps.128";
665 break;
666 case X86::BI__builtin_ia32_fpclassps256_mask:
667 intrinsicName = "x86.avx512.fpclass.ps.256";
668 break;
669 case X86::BI__builtin_ia32_fpclassps512_mask:
670 intrinsicName = "x86.avx512.fpclass.ps.512";
671 break;
672 case X86::BI__builtin_ia32_fpclasspd128_mask:
673 intrinsicName = "x86.avx512.fpclass.pd.128";
674 break;
675 case X86::BI__builtin_ia32_fpclasspd256_mask:
676 intrinsicName = "x86.avx512.fpclass.pd.256";
677 break;
678 case X86::BI__builtin_ia32_fpclasspd512_mask:
679 intrinsicName = "x86.avx512.fpclass.pd.512";
680 break;
681 }
682
683 auto cmpResultTy = cir::VectorType::get(builder.getSIntNTy(1), numElts);
684 mlir::Value fpclass =
685 builder.emitIntrinsicCallOp(loc, intrinsicName, cmpResultTy, ops);
686 return emitX86MaskedCompareResult(builder, fpclass, numElts, maskIn, loc);
687}
688
689static mlir::Value emitX86Aes(CIRGenBuilderTy &builder, mlir::Location loc,
690 llvm::StringRef intrinsicName, mlir::Type retType,
692 // Create return struct type and call intrinsic function.
693 mlir::Type vecType =
694 mlir::cast<cir::PointerType>(ops[0].getType()).getPointee();
695 cir::RecordType rstRecTy = builder.getAnonRecordTy({retType, vecType});
696 mlir::Value rstValueRec = builder.emitIntrinsicCallOp(
697 loc, intrinsicName, rstRecTy, mlir::ValueRange{ops[1], ops[2]});
698
699 // Extract the first return value and truncate it to 1 bit, then cast result
700 // to bool value.
701 mlir::Value flag =
702 cir::ExtractMemberOp::create(builder, loc, rstValueRec, /*index=*/0);
703 mlir::Value flagBit0 = builder.createCast(loc, cir::CastKind::integral, flag,
704 builder.getUIntNTy(1));
705 mlir::Value succ = builder.createCast(loc, cir::CastKind::int_to_bool,
706 flagBit0, builder.getBoolTy());
707
708 // Extract the second return value, store it to output address if success.
709 mlir::Value out =
710 cir::ExtractMemberOp::create(builder, loc, rstValueRec, /*index=*/1);
711 Address outAddr(ops[0], /*align=*/CharUnits::fromQuantity(16));
712 cir::IfOp::create(
713 builder, loc, succ, /*withElseRegion=*/true,
714 /*thenBuilder=*/
715 [&](mlir::OpBuilder &b, mlir::Location) {
716 builder.createStore(loc, out, outAddr);
717 builder.createYield(loc);
718 },
719 /*elseBuilder=*/
720 [&](mlir::OpBuilder &b, mlir::Location) {
721 mlir::Value zero = builder.getNullValue(vecType, loc);
722 builder.createStore(loc, zero, outAddr);
723 builder.createYield(loc);
724 });
725
726 return cir::ExtractMemberOp::create(builder, loc, rstValueRec, /*index=*/0);
727}
728
729static mlir::Value emitX86Aeswide(CIRGenBuilderTy &builder, mlir::Location loc,
730 llvm::StringRef intrinsicName,
731 mlir::Type retType,
733 mlir::Type vecType =
734 mlir::cast<cir::PointerType>(ops[1].getType()).getPointee();
735
736 // Create struct for return type and load input arguments, then call
737 // intrinsic function.
738 mlir::Type recTypes[9] = {retType, vecType, vecType, vecType, vecType,
739 vecType, vecType, vecType, vecType};
740 mlir::Value arguments[9];
741 arguments[0] = ops[2];
742 for (int i = 0; i < 8; i++) {
743 // Loading each vector argument from input address.
744 cir::ConstantOp idx = builder.getUInt32(i, loc);
745 mlir::Value nextInElePtr =
746 builder.getArrayElement(loc, loc, ops[1], vecType, idx,
747 /*shouldDecay=*/false);
748 arguments[i + 1] =
749 builder.createAlignedLoad(loc, vecType, nextInElePtr,
750 /*align=*/CharUnits::fromQuantity(16));
751 }
752 cir::RecordType rstRecTy = builder.getAnonRecordTy(recTypes);
753 mlir::Value rstValueRec =
754 builder.emitIntrinsicCallOp(loc, intrinsicName, rstRecTy, arguments);
755
756 // Extract the first return value and truncate it to 1 bit, then cast result
757 // to bool value.
758 mlir::Value flag =
759 cir::ExtractMemberOp::create(builder, loc, rstValueRec, /*index=*/0);
760 mlir::Value flagBit0 = builder.createCast(loc, cir::CastKind::integral, flag,
761 builder.getUIntNTy(1));
762 mlir::Value succ = builder.createCast(loc, cir::CastKind::int_to_bool,
763 flagBit0, builder.getBoolTy());
764
765 // Extract other return values, store those to output address if success.
766 cir::IfOp::create(
767 builder, loc, succ, /*withElseRegion=*/true,
768 /*thenBuilder=*/
769 [&](mlir::OpBuilder &b, mlir::Location) {
770 for (int i = 0; i < 8; i++) {
771 mlir::Value out =
772 cir::ExtractMemberOp::create(builder, loc, rstValueRec,
773 /*index=*/i + 1);
774 cir::ConstantOp idx = builder.getUInt32(i, loc);
775 mlir::Value nextOutEleAddr =
776 builder.getArrayElement(loc, loc, ops[0], vecType, idx,
777 /*shouldDecay=*/false);
778 Address outAddr(nextOutEleAddr,
779 /*align=*/CharUnits::fromQuantity(16));
780 builder.createStore(loc, out, outAddr);
781 }
782 builder.createYield(loc);
783 },
784 /*elseBuilder=*/
785 [&](mlir::OpBuilder &b, mlir::Location) {
786 mlir::Value zero = builder.getNullValue(vecType, loc);
787 for (int i = 0; i < 8; i++) {
788 cir::ConstantOp idx = builder.getUInt32(i, loc);
789 mlir::Value nextOutEleAddr =
790 builder.getArrayElement(loc, loc, ops[0], vecType, idx,
791 /*shouldDecay=*/false);
792 Address outAddr(nextOutEleAddr,
793 /*align=*/CharUnits::fromQuantity(16));
794 builder.createStore(loc, zero, outAddr);
795 }
796 builder.createYield(loc);
797 });
798
799 return cir::ExtractMemberOp::create(builder, loc, rstValueRec, /*index=*/0);
800}
801
802static mlir::Value emitX86MaskedLoad(CIRGenBuilderTy &builder,
804 llvm::Align alignment,
805 mlir::Location loc) {
806 mlir::Type ty = ops[1].getType();
807 mlir::Value ptr = ops[0];
808 mlir::Value maskVec = getMaskVecValue(builder, loc, ops[2],
809 cast<cir::VectorType>(ty).getSize());
810
811 return builder.createMaskedLoad(loc, ty, ptr, alignment, maskVec, ops[1]);
812}
813
814static mlir::Value emitX86VPerm2f128(CIRGenBuilderTy &builder,
815 mlir::Location loc,
817 auto inputType = cast<cir::VectorType>(ops[0].getType());
818 assert(!inputType.getIsScalable() &&
819 "This is only intended for fixed-width vectors");
820
822 mlir::Value zeroVec = builder.getZero(loc, inputType);
823
824 // If both lanes are zero, return a zero result.
825 if ((imm & 0x80) && (imm & 0x08))
826 return zeroVec;
827
828 mlir::Value lanes[2];
830
831 cir::IntType i32Ty = builder.getSInt32Ty();
832 const unsigned numElts = inputType.getSize();
833 // We must evaluated each lane(128 bits) separetely
834 for (auto lane : llvm::seq(0, 2)) {
835 bool isZeroBit = imm & (1 << ((lane * 4) + 3)),
836 isSourceB = imm & (1 << ((lane * 4) + 1)),
837 isUpperHalf = imm & (1 << (lane * 4));
838
839 // Determine the source for this lane
840 if (isZeroBit)
841 lanes[lane] = zeroVec;
842 else
843 lanes[lane] = isSourceB ? ops[1] : ops[0];
844
845 // We need to built the shuffle mask selecting the right half
846 for (auto elt : llvm::seq(0u, numElts / 2u)) {
847 unsigned idx = (lane * numElts) + elt;
848 if (isUpperHalf)
849 idx += numElts / 2;
850 mask.push_back(cir::IntAttr::get(i32Ty, idx));
851 }
852 }
853
854 return builder.createVecShuffle(loc, lanes[0], lanes[1], mask);
855}
856
857static mlir::Value emitX86PackedByteShift(CIRGenBuilderTy &builder,
858 unsigned builtinID,
859 mlir::Location loc,
861 llvm::Boolean isLeftShift) {
862 auto byteVecType = cast<cir::VectorType>(ops[0].getType());
863 assert(!byteVecType.getIsScalable() &&
864 "This is only intended for fixed-width vectors");
865
866 unsigned shiftVal = CIRGenFunction::getZExtIntValueFromConstOp(ops[1]) & 0xFF;
867 mlir::Value zeroVector = builder.getZero(loc, byteVecType);
868
869 // If pslldq is shifting the vector more than 15 bytes, emit zero.
870 // This matches the hardware behavior where shifting by 16+ bytes
871 // clears the entire 128-bit lane.
872 if (shiftVal >= 16)
873 return zeroVector;
874
875 uint64_t numElts = byteVecType.getSize();
876 assert(numElts % 16 == 0 && "Expected a multiple of 16");
877
879
880 constexpr unsigned laneSize = 16;
881 const int switchOperand = numElts - laneSize;
882
883 // 256/512-bit pslldq/psrldq operates on 128-bit lanes so we need to
884 // handle that
885 for (auto laneOffset = 0ull; laneOffset < numElts; laneOffset += laneSize) {
886 for (auto elt : llvm::seq<unsigned>(0, laneSize)) {
887 unsigned idx =
888 isLeftShift ? (numElts + elt - shiftVal) : (elt + shiftVal);
889
890 bool isZeroPadding = isLeftShift ? (idx < numElts) : (idx >= laneSize);
891 if (isZeroPadding)
892 idx += isLeftShift ? (-switchOperand) : switchOperand;
893
894 shuffleMask.push_back(idx + laneOffset);
895 }
896 }
897
898 // Perform the shuffle
899 // (left concatenating zeros on left, right concatenating zeros on right)
900 auto [firstOperand, secondOperand] = isLeftShift
901 ? std::make_pair(zeroVector, ops[0])
902 : std::make_pair(ops[0], zeroVector);
903
904 // Mask the result using circular arithmetic on concatenated buffer
905 mlir::Value shuffleResult =
906 builder.createVecShuffle(loc, firstOperand, secondOperand, shuffleMask);
907
908 return shuffleResult;
909}
910
911std::optional<mlir::Value>
913 if (builtinID == Builtin::BI__builtin_cpu_is) {
914 cgm.errorNYI(expr->getSourceRange(), "__builtin_cpu_is");
915 return mlir::Value{};
916 }
917 if (builtinID == Builtin::BI__builtin_cpu_supports) {
918 cgm.errorNYI(expr->getSourceRange(), "__builtin_cpu_supports");
919 return mlir::Value{};
920 }
921 if (builtinID == Builtin::BI__builtin_cpu_init) {
922 cgm.errorNYI(expr->getSourceRange(), "__builtin_cpu_init");
923 return mlir::Value{};
924 }
925
926 // Handle MSVC intrinsics before argument evaluation to prevent double
927 // evaluation.
929
930 // Find out if any arguments are required to be integer constant expressions.
932
933 // The operands of the builtin call
935
936 // `ICEArguments` is a bitmap indicating whether the argument at the i-th bit
937 // is required to be a constant integer expression.
938 unsigned iceArguments = 0;
940 getContext().GetBuiltinType(builtinID, error, &iceArguments);
941 assert(error == ASTContext::GE_None && "Error while getting builtin type.");
942
943 for (auto [idx, arg] : llvm::enumerate(expr->arguments()))
944 ops.push_back(emitScalarOrConstFoldImmArg(iceArguments, idx, arg));
945
946 CIRGenBuilderTy &builder = getBuilder();
947 mlir::Type voidTy = builder.getVoidTy();
948
949 switch (builtinID) {
950 default:
951 return std::nullopt;
952 case X86::BI_mm_clflush:
953 return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()),
954 "x86.sse2.clflush", voidTy, ops[0]);
955 case X86::BI_mm_lfence:
956 return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()),
957 "x86.sse2.lfence", voidTy);
958 case X86::BI_mm_pause:
959 return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()),
960 "x86.sse2.pause", voidTy);
961 case X86::BI_mm_mfence:
962 return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()),
963 "x86.sse2.mfence", voidTy);
964 case X86::BI_mm_sfence:
965 return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()),
966 "x86.sse.sfence", voidTy);
967 case X86::BI_mm_prefetch:
968 case X86::BI_m_prefetch:
969 case X86::BI_m_prefetchw:
970 return emitPrefetch(*this, builtinID, expr, ops);
971 case X86::BI__rdtsc:
972 return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()), "x86.rdtsc",
973 builder.getUInt64Ty());
974 case X86::BI__builtin_ia32_rdtscp: {
975 mlir::Location loc = getLoc(expr->getExprLoc());
976 mlir::Type i64Ty = builder.getUInt64Ty();
977 mlir::Type i32Ty = builder.getUInt32Ty();
978 mlir::Type structTy = builder.getAnonRecordTy({i64Ty, i32Ty});
979 mlir::Value result =
980 builder.emitIntrinsicCallOp(loc, "x86.rdtscp", structTy);
981
982 // Extract and store processor_id (element 1 of the returned struct)
983 mlir::Value processorId =
984 cir::ExtractMemberOp::create(builder, loc, i32Ty, result, 1);
985 // ops[0] is the address to store the processor ID
986 builder.createStore(loc, processorId, Address{ops[0], CharUnits::One()});
987
988 // Return timestamp (element 0 of the returned struct)
989 return cir::ExtractMemberOp::create(builder, loc, i64Ty, result, 0);
990 }
991 case X86::BI__builtin_ia32_lzcnt_u16:
992 case X86::BI__builtin_ia32_lzcnt_u32:
993 case X86::BI__builtin_ia32_lzcnt_u64: {
994 mlir::Location loc = getLoc(expr->getExprLoc());
995 mlir::Value isZeroPoison = builder.getFalse(loc);
996 return builder.emitIntrinsicCallOp(loc, "ctlz", ops[0].getType(),
997 mlir::ValueRange{ops[0], isZeroPoison});
998 }
999 case X86::BI__builtin_ia32_tzcnt_u16:
1000 case X86::BI__builtin_ia32_tzcnt_u32:
1001 case X86::BI__builtin_ia32_tzcnt_u64: {
1002 mlir::Location loc = getLoc(expr->getExprLoc());
1003 mlir::Value isZeroPoison = builder.getFalse(loc);
1004 return builder.emitIntrinsicCallOp(loc, "cttz", ops[0].getType(),
1005 mlir::ValueRange{ops[0], isZeroPoison});
1006 }
1007 case X86::BI__builtin_ia32_undef128:
1008 case X86::BI__builtin_ia32_undef256:
1009 case X86::BI__builtin_ia32_undef512:
1010 // The x86 definition of "undef" is not the same as the LLVM definition
1011 // (PR32176). We leave optimizing away an unnecessary zero constant to the
1012 // IR optimizer and backend.
1013 // TODO: If we had a "freeze" IR instruction to generate a fixed undef
1014 // value, we should use that here instead of a zero.
1015 return builder.getNullValue(convertType(expr->getType()),
1016 getLoc(expr->getExprLoc()));
1017 case X86::BI__builtin_ia32_vec_ext_v4hi:
1018 case X86::BI__builtin_ia32_vec_ext_v16qi:
1019 case X86::BI__builtin_ia32_vec_ext_v8hi:
1020 case X86::BI__builtin_ia32_vec_ext_v4si:
1021 case X86::BI__builtin_ia32_vec_ext_v4sf:
1022 case X86::BI__builtin_ia32_vec_ext_v2di:
1023 case X86::BI__builtin_ia32_vec_ext_v32qi:
1024 case X86::BI__builtin_ia32_vec_ext_v16hi:
1025 case X86::BI__builtin_ia32_vec_ext_v8si:
1026 case X86::BI__builtin_ia32_vec_ext_v4di: {
1027 unsigned numElts = cast<cir::VectorType>(ops[0].getType()).getSize();
1028
1029 uint64_t index = getZExtIntValueFromConstOp(ops[1]);
1030 index &= numElts - 1;
1031
1032 cir::ConstantOp indexVal =
1033 builder.getUInt64(index, getLoc(expr->getExprLoc()));
1034
1035 // These builtins exist so we can ensure the index is an ICE and in range.
1036 // Otherwise we could just do this in the header file.
1037 return cir::VecExtractOp::create(builder, getLoc(expr->getExprLoc()),
1038 ops[0], indexVal);
1039 }
1040 case X86::BI__builtin_ia32_vec_set_v4hi:
1041 case X86::BI__builtin_ia32_vec_set_v16qi:
1042 case X86::BI__builtin_ia32_vec_set_v8hi:
1043 case X86::BI__builtin_ia32_vec_set_v4si:
1044 case X86::BI__builtin_ia32_vec_set_v2di:
1045 case X86::BI__builtin_ia32_vec_set_v32qi:
1046 case X86::BI__builtin_ia32_vec_set_v16hi:
1047 case X86::BI__builtin_ia32_vec_set_v8si:
1048 case X86::BI__builtin_ia32_vec_set_v4di: {
1049 return emitVecInsert(builder, getLoc(expr->getExprLoc()), ops[0], ops[1],
1050 ops[2]);
1051 }
1052 case X86::BI__builtin_ia32_kunpckhi:
1053 return emitX86MaskUnpack(builder, getLoc(expr->getExprLoc()),
1054 "x86.avx512.kunpackb", ops);
1055 case X86::BI__builtin_ia32_kunpcksi:
1056 return emitX86MaskUnpack(builder, getLoc(expr->getExprLoc()),
1057 "x86.avx512.kunpackw", ops);
1058 case X86::BI__builtin_ia32_kunpckdi:
1059 return emitX86MaskUnpack(builder, getLoc(expr->getExprLoc()),
1060 "x86.avx512.kunpackd", ops);
1061 case X86::BI_mm_setcsr:
1062 case X86::BI__builtin_ia32_ldmxcsr: {
1063 mlir::Location loc = getLoc(expr->getExprLoc());
1064 Address tmp = createMemTemp(expr->getArg(0)->getType(), loc);
1065 builder.createStore(loc, ops[0], tmp);
1066 return builder.emitIntrinsicCallOp(loc, "x86.sse.ldmxcsr",
1067 builder.getVoidTy(), tmp.getPointer());
1068 }
1069 case X86::BI_mm_getcsr:
1070 case X86::BI__builtin_ia32_stmxcsr: {
1071 mlir::Location loc = getLoc(expr->getExprLoc());
1072 Address tmp = createMemTemp(expr->getType(), loc);
1073 builder.emitIntrinsicCallOp(loc, "x86.sse.stmxcsr", builder.getVoidTy(),
1074 tmp.getPointer());
1075 return builder.createLoad(loc, tmp);
1076 }
1077 case X86::BI__builtin_ia32_xsave:
1078 case X86::BI__builtin_ia32_xsave64:
1079 case X86::BI__builtin_ia32_xrstor:
1080 case X86::BI__builtin_ia32_xrstor64:
1081 case X86::BI__builtin_ia32_xsaveopt:
1082 case X86::BI__builtin_ia32_xsaveopt64:
1083 case X86::BI__builtin_ia32_xrstors:
1084 case X86::BI__builtin_ia32_xrstors64:
1085 case X86::BI__builtin_ia32_xsavec:
1086 case X86::BI__builtin_ia32_xsavec64:
1087 case X86::BI__builtin_ia32_xsaves:
1088 case X86::BI__builtin_ia32_xsaves64:
1089 case X86::BI__builtin_ia32_xsetbv:
1090 case X86::BI_xsetbv: {
1091 mlir::Location loc = getLoc(expr->getExprLoc());
1092 StringRef intrinsicName;
1093 switch (builtinID) {
1094 default:
1095 llvm_unreachable("Unexpected builtin");
1096 case X86::BI__builtin_ia32_xsave:
1097 intrinsicName = "x86.xsave";
1098 break;
1099 case X86::BI__builtin_ia32_xsave64:
1100 intrinsicName = "x86.xsave64";
1101 break;
1102 case X86::BI__builtin_ia32_xrstor:
1103 intrinsicName = "x86.xrstor";
1104 break;
1105 case X86::BI__builtin_ia32_xrstor64:
1106 intrinsicName = "x86.xrstor64";
1107 break;
1108 case X86::BI__builtin_ia32_xsaveopt:
1109 intrinsicName = "x86.xsaveopt";
1110 break;
1111 case X86::BI__builtin_ia32_xsaveopt64:
1112 intrinsicName = "x86.xsaveopt64";
1113 break;
1114 case X86::BI__builtin_ia32_xrstors:
1115 intrinsicName = "x86.xrstors";
1116 break;
1117 case X86::BI__builtin_ia32_xrstors64:
1118 intrinsicName = "x86.xrstors64";
1119 break;
1120 case X86::BI__builtin_ia32_xsavec:
1121 intrinsicName = "x86.xsavec";
1122 break;
1123 case X86::BI__builtin_ia32_xsavec64:
1124 intrinsicName = "x86.xsavec64";
1125 break;
1126 case X86::BI__builtin_ia32_xsaves:
1127 intrinsicName = "x86.xsaves";
1128 break;
1129 case X86::BI__builtin_ia32_xsaves64:
1130 intrinsicName = "x86.xsaves64";
1131 break;
1132 case X86::BI__builtin_ia32_xsetbv:
1133 case X86::BI_xsetbv:
1134 intrinsicName = "x86.xsetbv";
1135 break;
1136 }
1137
1138 // The xsave family of instructions take a 64-bit mask that specifies
1139 // which processor state components to save/restore. The hardware expects
1140 // this mask split into two 32-bit registers: EDX (high 32 bits) and
1141 // EAX (low 32 bits).
1142 mlir::Type i32Ty = builder.getSInt32Ty();
1143
1144 // Mhi = (uint32_t)(ops[1] >> 32) - extract high 32 bits via right shift
1145 cir::ConstantOp shift32 = builder.getSInt64(32, loc);
1146 mlir::Value mhi = builder.createShift(loc, ops[1], shift32.getResult(),
1147 /*isShiftLeft=*/false);
1148 mhi = builder.createIntCast(mhi, i32Ty);
1149
1150 // Mlo = (uint32_t)ops[1] - extract low 32 bits by truncation
1151 mlir::Value mlo = builder.createIntCast(ops[1], i32Ty);
1152
1153 return builder.emitIntrinsicCallOp(loc, intrinsicName, voidTy,
1154 mlir::ValueRange{ops[0], mhi, mlo});
1155 }
1156 case X86::BI__builtin_ia32_xgetbv:
1157 case X86::BI_xgetbv:
1158 // xgetbv reads the extended control register specified by ops[0] (ECX)
1159 // and returns the 64-bit value
1160 return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()), "x86.xgetbv",
1161 builder.getUInt64Ty(), ops[0]);
1162 case X86::BI__builtin_ia32_storedqudi128_mask:
1163 case X86::BI__builtin_ia32_storedqusi128_mask:
1164 case X86::BI__builtin_ia32_storedquhi128_mask:
1165 case X86::BI__builtin_ia32_storedquqi128_mask:
1166 case X86::BI__builtin_ia32_storeupd128_mask:
1167 case X86::BI__builtin_ia32_storeups128_mask:
1168 case X86::BI__builtin_ia32_storedqudi256_mask:
1169 case X86::BI__builtin_ia32_storedqusi256_mask:
1170 case X86::BI__builtin_ia32_storedquhi256_mask:
1171 case X86::BI__builtin_ia32_storedquqi256_mask:
1172 case X86::BI__builtin_ia32_storeupd256_mask:
1173 case X86::BI__builtin_ia32_storeups256_mask:
1174 case X86::BI__builtin_ia32_storedqudi512_mask:
1175 case X86::BI__builtin_ia32_storedqusi512_mask:
1176 case X86::BI__builtin_ia32_storedquhi512_mask:
1177 case X86::BI__builtin_ia32_storedquqi512_mask:
1178 case X86::BI__builtin_ia32_storeupd512_mask:
1179 case X86::BI__builtin_ia32_storeups512_mask:
1180 case X86::BI__builtin_ia32_storesbf16128_mask:
1181 case X86::BI__builtin_ia32_storesh128_mask:
1182 case X86::BI__builtin_ia32_storess128_mask:
1183 case X86::BI__builtin_ia32_storesd128_mask:
1184 cgm.errorNYI(expr->getSourceRange(),
1185 std::string("unimplemented x86 builtin call: ") +
1186 getContext().BuiltinInfo.getName(builtinID));
1187 return mlir::Value{};
1188 case X86::BI__builtin_ia32_cvtmask2b128:
1189 case X86::BI__builtin_ia32_cvtmask2b256:
1190 case X86::BI__builtin_ia32_cvtmask2b512:
1191 case X86::BI__builtin_ia32_cvtmask2w128:
1192 case X86::BI__builtin_ia32_cvtmask2w256:
1193 case X86::BI__builtin_ia32_cvtmask2w512:
1194 case X86::BI__builtin_ia32_cvtmask2d128:
1195 case X86::BI__builtin_ia32_cvtmask2d256:
1196 case X86::BI__builtin_ia32_cvtmask2d512:
1197 case X86::BI__builtin_ia32_cvtmask2q128:
1198 case X86::BI__builtin_ia32_cvtmask2q256:
1199 case X86::BI__builtin_ia32_cvtmask2q512:
1200 return emitX86SExtMask(this->getBuilder(), ops[0],
1201 convertType(expr->getType()),
1202 getLoc(expr->getExprLoc()));
1203 case X86::BI__builtin_ia32_cvtb2mask128:
1204 case X86::BI__builtin_ia32_cvtb2mask256:
1205 case X86::BI__builtin_ia32_cvtb2mask512:
1206 case X86::BI__builtin_ia32_cvtw2mask128:
1207 case X86::BI__builtin_ia32_cvtw2mask256:
1208 case X86::BI__builtin_ia32_cvtw2mask512:
1209 case X86::BI__builtin_ia32_cvtd2mask128:
1210 case X86::BI__builtin_ia32_cvtd2mask256:
1211 case X86::BI__builtin_ia32_cvtd2mask512:
1212 case X86::BI__builtin_ia32_cvtq2mask128:
1213 case X86::BI__builtin_ia32_cvtq2mask256:
1214 case X86::BI__builtin_ia32_cvtq2mask512:
1215 return emitX86ConvertToMask(*this, this->getBuilder(), ops[0],
1216 getLoc(expr->getExprLoc()));
1217 case X86::BI__builtin_ia32_cvtdq2ps512_mask:
1218 case X86::BI__builtin_ia32_cvtqq2ps512_mask:
1219 case X86::BI__builtin_ia32_cvtqq2pd512_mask:
1220 case X86::BI__builtin_ia32_vcvtw2ph512_mask:
1221 case X86::BI__builtin_ia32_vcvtdq2ph512_mask:
1222 case X86::BI__builtin_ia32_vcvtqq2ph512_mask:
1223 case X86::BI__builtin_ia32_cvtudq2ps512_mask:
1224 case X86::BI__builtin_ia32_cvtuqq2ps512_mask:
1225 case X86::BI__builtin_ia32_cvtuqq2pd512_mask:
1226 case X86::BI__builtin_ia32_vcvtuw2ph512_mask:
1227 case X86::BI__builtin_ia32_vcvtudq2ph512_mask:
1228 case X86::BI__builtin_ia32_vcvtuqq2ph512_mask:
1229 case X86::BI__builtin_ia32_vfmaddsh3_mask:
1230 case X86::BI__builtin_ia32_vfmaddss3_mask:
1231 case X86::BI__builtin_ia32_vfmaddsd3_mask:
1232 case X86::BI__builtin_ia32_vfmaddsh3_maskz:
1233 case X86::BI__builtin_ia32_vfmaddss3_maskz:
1234 case X86::BI__builtin_ia32_vfmaddsd3_maskz:
1235 case X86::BI__builtin_ia32_vfmaddsh3_mask3:
1236 case X86::BI__builtin_ia32_vfmaddss3_mask3:
1237 case X86::BI__builtin_ia32_vfmaddsd3_mask3:
1238 case X86::BI__builtin_ia32_vfmsubsh3_mask3:
1239 case X86::BI__builtin_ia32_vfmsubss3_mask3:
1240 case X86::BI__builtin_ia32_vfmsubsd3_mask3:
1241 case X86::BI__builtin_ia32_vfmaddph512_mask:
1242 case X86::BI__builtin_ia32_vfmaddph512_maskz:
1243 case X86::BI__builtin_ia32_vfmaddph512_mask3:
1244 case X86::BI__builtin_ia32_vfmaddps512_mask:
1245 case X86::BI__builtin_ia32_vfmaddps512_maskz:
1246 case X86::BI__builtin_ia32_vfmaddps512_mask3:
1247 case X86::BI__builtin_ia32_vfmsubps512_mask3:
1248 case X86::BI__builtin_ia32_vfmaddpd512_mask:
1249 case X86::BI__builtin_ia32_vfmaddpd512_maskz:
1250 case X86::BI__builtin_ia32_vfmaddpd512_mask3:
1251 case X86::BI__builtin_ia32_vfmsubpd512_mask3:
1252 case X86::BI__builtin_ia32_vfmsubph512_mask3:
1253 case X86::BI__builtin_ia32_vfmaddsubph512_mask:
1254 case X86::BI__builtin_ia32_vfmaddsubph512_maskz:
1255 case X86::BI__builtin_ia32_vfmaddsubph512_mask3:
1256 case X86::BI__builtin_ia32_vfmsubaddph512_mask3:
1257 case X86::BI__builtin_ia32_vfmaddsubps512_mask:
1258 case X86::BI__builtin_ia32_vfmaddsubps512_maskz:
1259 case X86::BI__builtin_ia32_vfmaddsubps512_mask3:
1260 case X86::BI__builtin_ia32_vfmsubaddps512_mask3:
1261 case X86::BI__builtin_ia32_vfmaddsubpd512_mask:
1262 case X86::BI__builtin_ia32_vfmaddsubpd512_maskz:
1263 case X86::BI__builtin_ia32_vfmaddsubpd512_mask3:
1264 case X86::BI__builtin_ia32_vfmsubaddpd512_mask3:
1265 case X86::BI__builtin_ia32_movdqa32store128_mask:
1266 case X86::BI__builtin_ia32_movdqa64store128_mask:
1267 case X86::BI__builtin_ia32_storeaps128_mask:
1268 case X86::BI__builtin_ia32_storeapd128_mask:
1269 case X86::BI__builtin_ia32_movdqa32store256_mask:
1270 case X86::BI__builtin_ia32_movdqa64store256_mask:
1271 case X86::BI__builtin_ia32_storeaps256_mask:
1272 case X86::BI__builtin_ia32_storeapd256_mask:
1273 case X86::BI__builtin_ia32_movdqa32store512_mask:
1274 case X86::BI__builtin_ia32_movdqa64store512_mask:
1275 case X86::BI__builtin_ia32_storeaps512_mask:
1276 case X86::BI__builtin_ia32_storeapd512_mask:
1277 cgm.errorNYI(expr->getSourceRange(),
1278 std::string("unimplemented X86 builtin call: ") +
1279 getContext().BuiltinInfo.getName(builtinID));
1280 return {};
1281
1282 case X86::BI__builtin_ia32_loadups128_mask:
1283 case X86::BI__builtin_ia32_loadups256_mask:
1284 case X86::BI__builtin_ia32_loadups512_mask:
1285 case X86::BI__builtin_ia32_loadupd128_mask:
1286 case X86::BI__builtin_ia32_loadupd256_mask:
1287 case X86::BI__builtin_ia32_loadupd512_mask:
1288 case X86::BI__builtin_ia32_loaddquqi128_mask:
1289 case X86::BI__builtin_ia32_loaddquqi256_mask:
1290 case X86::BI__builtin_ia32_loaddquqi512_mask:
1291 case X86::BI__builtin_ia32_loaddquhi128_mask:
1292 case X86::BI__builtin_ia32_loaddquhi256_mask:
1293 case X86::BI__builtin_ia32_loaddquhi512_mask:
1294 case X86::BI__builtin_ia32_loaddqusi128_mask:
1295 case X86::BI__builtin_ia32_loaddqusi256_mask:
1296 case X86::BI__builtin_ia32_loaddqusi512_mask:
1297 case X86::BI__builtin_ia32_loaddqudi128_mask:
1298 case X86::BI__builtin_ia32_loaddqudi256_mask:
1299 case X86::BI__builtin_ia32_loaddqudi512_mask:
1300 case X86::BI__builtin_ia32_loadsbf16128_mask:
1301 case X86::BI__builtin_ia32_loadsh128_mask:
1302 case X86::BI__builtin_ia32_loadss128_mask:
1303 case X86::BI__builtin_ia32_loadsd128_mask:
1304 return emitX86MaskedLoad(builder, ops, llvm::Align(1),
1305 getLoc(expr->getExprLoc()));
1306
1307 case X86::BI__builtin_ia32_loadaps128_mask:
1308 case X86::BI__builtin_ia32_loadaps256_mask:
1309 case X86::BI__builtin_ia32_loadaps512_mask:
1310 case X86::BI__builtin_ia32_loadapd128_mask:
1311 case X86::BI__builtin_ia32_loadapd256_mask:
1312 case X86::BI__builtin_ia32_loadapd512_mask:
1313 case X86::BI__builtin_ia32_movdqa32load128_mask:
1314 case X86::BI__builtin_ia32_movdqa32load256_mask:
1315 case X86::BI__builtin_ia32_movdqa32load512_mask:
1316 case X86::BI__builtin_ia32_movdqa64load128_mask:
1317 case X86::BI__builtin_ia32_movdqa64load256_mask:
1318 case X86::BI__builtin_ia32_movdqa64load512_mask:
1319 return emitX86MaskedLoad(
1320 builder, ops,
1321 getContext()
1322 .getTypeAlignInChars(expr->getArg(1)->getType())
1323 .getAsAlign(),
1324 getLoc(expr->getExprLoc()));
1325
1326 case X86::BI__builtin_ia32_expandloaddf128_mask:
1327 case X86::BI__builtin_ia32_expandloaddf256_mask:
1328 case X86::BI__builtin_ia32_expandloaddf512_mask:
1329 case X86::BI__builtin_ia32_expandloadsf128_mask:
1330 case X86::BI__builtin_ia32_expandloadsf256_mask:
1331 case X86::BI__builtin_ia32_expandloadsf512_mask:
1332 case X86::BI__builtin_ia32_expandloaddi128_mask:
1333 case X86::BI__builtin_ia32_expandloaddi256_mask:
1334 case X86::BI__builtin_ia32_expandloaddi512_mask:
1335 case X86::BI__builtin_ia32_expandloadsi128_mask:
1336 case X86::BI__builtin_ia32_expandloadsi256_mask:
1337 case X86::BI__builtin_ia32_expandloadsi512_mask:
1338 case X86::BI__builtin_ia32_expandloadhi128_mask:
1339 case X86::BI__builtin_ia32_expandloadhi256_mask:
1340 case X86::BI__builtin_ia32_expandloadhi512_mask:
1341 case X86::BI__builtin_ia32_expandloadqi128_mask:
1342 case X86::BI__builtin_ia32_expandloadqi256_mask:
1343 case X86::BI__builtin_ia32_expandloadqi512_mask: {
1344 cgm.errorNYI(expr->getSourceRange(),
1345 std::string("unimplemented X86 builtin call: ") +
1346 getContext().BuiltinInfo.getName(builtinID));
1347 return {};
1348 }
1349 case X86::BI__builtin_ia32_compressstoredf128_mask:
1350 case X86::BI__builtin_ia32_compressstoredf256_mask:
1351 case X86::BI__builtin_ia32_compressstoredf512_mask:
1352 case X86::BI__builtin_ia32_compressstoresf128_mask:
1353 case X86::BI__builtin_ia32_compressstoresf256_mask:
1354 case X86::BI__builtin_ia32_compressstoresf512_mask:
1355 case X86::BI__builtin_ia32_compressstoredi128_mask:
1356 case X86::BI__builtin_ia32_compressstoredi256_mask:
1357 case X86::BI__builtin_ia32_compressstoredi512_mask:
1358 case X86::BI__builtin_ia32_compressstoresi128_mask:
1359 case X86::BI__builtin_ia32_compressstoresi256_mask:
1360 case X86::BI__builtin_ia32_compressstoresi512_mask:
1361 case X86::BI__builtin_ia32_compressstorehi128_mask:
1362 case X86::BI__builtin_ia32_compressstorehi256_mask:
1363 case X86::BI__builtin_ia32_compressstorehi512_mask:
1364 case X86::BI__builtin_ia32_compressstoreqi128_mask:
1365 case X86::BI__builtin_ia32_compressstoreqi256_mask:
1366 case X86::BI__builtin_ia32_compressstoreqi512_mask:
1367 return emitX86CompressStore(builder, getLoc(expr->getExprLoc()), ops);
1368 case X86::BI__builtin_ia32_expanddf128_mask:
1369 case X86::BI__builtin_ia32_expanddf256_mask:
1370 case X86::BI__builtin_ia32_expanddf512_mask:
1371 case X86::BI__builtin_ia32_expandsf128_mask:
1372 case X86::BI__builtin_ia32_expandsf256_mask:
1373 case X86::BI__builtin_ia32_expandsf512_mask:
1374 case X86::BI__builtin_ia32_expanddi128_mask:
1375 case X86::BI__builtin_ia32_expanddi256_mask:
1376 case X86::BI__builtin_ia32_expanddi512_mask:
1377 case X86::BI__builtin_ia32_expandsi128_mask:
1378 case X86::BI__builtin_ia32_expandsi256_mask:
1379 case X86::BI__builtin_ia32_expandsi512_mask:
1380 case X86::BI__builtin_ia32_expandhi128_mask:
1381 case X86::BI__builtin_ia32_expandhi256_mask:
1382 case X86::BI__builtin_ia32_expandhi512_mask:
1383 case X86::BI__builtin_ia32_expandqi128_mask:
1384 case X86::BI__builtin_ia32_expandqi256_mask:
1385 case X86::BI__builtin_ia32_expandqi512_mask: {
1386 mlir::Location loc = getLoc(expr->getExprLoc());
1387 return emitX86CompressExpand(builder, loc, ops[0], ops[1], ops[2],
1388 "x86.avx512.mask.expand");
1389 }
1390 case X86::BI__builtin_ia32_compressdf128_mask:
1391 case X86::BI__builtin_ia32_compressdf256_mask:
1392 case X86::BI__builtin_ia32_compressdf512_mask:
1393 case X86::BI__builtin_ia32_compresssf128_mask:
1394 case X86::BI__builtin_ia32_compresssf256_mask:
1395 case X86::BI__builtin_ia32_compresssf512_mask:
1396 case X86::BI__builtin_ia32_compressdi128_mask:
1397 case X86::BI__builtin_ia32_compressdi256_mask:
1398 case X86::BI__builtin_ia32_compressdi512_mask:
1399 case X86::BI__builtin_ia32_compresssi128_mask:
1400 case X86::BI__builtin_ia32_compresssi256_mask:
1401 case X86::BI__builtin_ia32_compresssi512_mask:
1402 case X86::BI__builtin_ia32_compresshi128_mask:
1403 case X86::BI__builtin_ia32_compresshi256_mask:
1404 case X86::BI__builtin_ia32_compresshi512_mask:
1405 case X86::BI__builtin_ia32_compressqi128_mask:
1406 case X86::BI__builtin_ia32_compressqi256_mask:
1407 case X86::BI__builtin_ia32_compressqi512_mask: {
1408 mlir::Location loc = getLoc(expr->getExprLoc());
1409 return emitX86CompressExpand(builder, loc, ops[0], ops[1], ops[2],
1410 "x86.avx512.mask.compress");
1411 }
1412 case X86::BI__builtin_ia32_gather3div2df:
1413 case X86::BI__builtin_ia32_gather3div2di:
1414 case X86::BI__builtin_ia32_gather3div4df:
1415 case X86::BI__builtin_ia32_gather3div4di:
1416 case X86::BI__builtin_ia32_gather3div4sf:
1417 case X86::BI__builtin_ia32_gather3div4si:
1418 case X86::BI__builtin_ia32_gather3div8sf:
1419 case X86::BI__builtin_ia32_gather3div8si:
1420 case X86::BI__builtin_ia32_gather3siv2df:
1421 case X86::BI__builtin_ia32_gather3siv2di:
1422 case X86::BI__builtin_ia32_gather3siv4df:
1423 case X86::BI__builtin_ia32_gather3siv4di:
1424 case X86::BI__builtin_ia32_gather3siv4sf:
1425 case X86::BI__builtin_ia32_gather3siv4si:
1426 case X86::BI__builtin_ia32_gather3siv8sf:
1427 case X86::BI__builtin_ia32_gather3siv8si:
1428 case X86::BI__builtin_ia32_gathersiv8df:
1429 case X86::BI__builtin_ia32_gathersiv16sf:
1430 case X86::BI__builtin_ia32_gatherdiv8df:
1431 case X86::BI__builtin_ia32_gatherdiv16sf:
1432 case X86::BI__builtin_ia32_gathersiv8di:
1433 case X86::BI__builtin_ia32_gathersiv16si:
1434 case X86::BI__builtin_ia32_gatherdiv8di:
1435 case X86::BI__builtin_ia32_gatherdiv16si: {
1436 StringRef intrinsicName;
1437 switch (builtinID) {
1438 default:
1439 llvm_unreachable("Unexpected builtin");
1440 case X86::BI__builtin_ia32_gather3div2df:
1441 intrinsicName = "x86.avx512.mask.gather3div2.df";
1442 break;
1443 case X86::BI__builtin_ia32_gather3div2di:
1444 intrinsicName = "x86.avx512.mask.gather3div2.di";
1445 break;
1446 case X86::BI__builtin_ia32_gather3div4df:
1447 intrinsicName = "x86.avx512.mask.gather3div4.df";
1448 break;
1449 case X86::BI__builtin_ia32_gather3div4di:
1450 intrinsicName = "x86.avx512.mask.gather3div4.di";
1451 break;
1452 case X86::BI__builtin_ia32_gather3div4sf:
1453 intrinsicName = "x86.avx512.mask.gather3div4.sf";
1454 break;
1455 case X86::BI__builtin_ia32_gather3div4si:
1456 intrinsicName = "x86.avx512.mask.gather3div4.si";
1457 break;
1458 case X86::BI__builtin_ia32_gather3div8sf:
1459 intrinsicName = "x86.avx512.mask.gather3div8.sf";
1460 break;
1461 case X86::BI__builtin_ia32_gather3div8si:
1462 intrinsicName = "x86.avx512.mask.gather3div8.si";
1463 break;
1464 case X86::BI__builtin_ia32_gather3siv2df:
1465 intrinsicName = "x86.avx512.mask.gather3siv2.df";
1466 break;
1467 case X86::BI__builtin_ia32_gather3siv2di:
1468 intrinsicName = "x86.avx512.mask.gather3siv2.di";
1469 break;
1470 case X86::BI__builtin_ia32_gather3siv4df:
1471 intrinsicName = "x86.avx512.mask.gather3siv4.df";
1472 break;
1473 case X86::BI__builtin_ia32_gather3siv4di:
1474 intrinsicName = "x86.avx512.mask.gather3siv4.di";
1475 break;
1476 case X86::BI__builtin_ia32_gather3siv4sf:
1477 intrinsicName = "x86.avx512.mask.gather3siv4.sf";
1478 break;
1479 case X86::BI__builtin_ia32_gather3siv4si:
1480 intrinsicName = "x86.avx512.mask.gather3siv4.si";
1481 break;
1482 case X86::BI__builtin_ia32_gather3siv8sf:
1483 intrinsicName = "x86.avx512.mask.gather3siv8.sf";
1484 break;
1485 case X86::BI__builtin_ia32_gather3siv8si:
1486 intrinsicName = "x86.avx512.mask.gather3siv8.si";
1487 break;
1488 case X86::BI__builtin_ia32_gathersiv8df:
1489 intrinsicName = "x86.avx512.mask.gather.dpd.512";
1490 break;
1491 case X86::BI__builtin_ia32_gathersiv16sf:
1492 intrinsicName = "x86.avx512.mask.gather.dps.512";
1493 break;
1494 case X86::BI__builtin_ia32_gatherdiv8df:
1495 intrinsicName = "x86.avx512.mask.gather.qpd.512";
1496 break;
1497 case X86::BI__builtin_ia32_gatherdiv16sf:
1498 intrinsicName = "x86.avx512.mask.gather.qps.512";
1499 break;
1500 case X86::BI__builtin_ia32_gathersiv8di:
1501 intrinsicName = "x86.avx512.mask.gather.dpq.512";
1502 break;
1503 case X86::BI__builtin_ia32_gathersiv16si:
1504 intrinsicName = "x86.avx512.mask.gather.dpi.512";
1505 break;
1506 case X86::BI__builtin_ia32_gatherdiv8di:
1507 intrinsicName = "x86.avx512.mask.gather.qpq.512";
1508 break;
1509 case X86::BI__builtin_ia32_gatherdiv16si:
1510 intrinsicName = "x86.avx512.mask.gather.qpi.512";
1511 break;
1512 }
1513
1514 mlir::Location loc = getLoc(expr->getExprLoc());
1515 unsigned minElts =
1516 std::min(cast<cir::VectorType>(ops[0].getType()).getSize(),
1517 cast<cir::VectorType>(ops[2].getType()).getSize());
1518 ops[3] = getMaskVecValue(builder, loc, ops[3], minElts);
1519 return builder.emitIntrinsicCallOp(loc, intrinsicName,
1520 convertType(expr->getType()), ops);
1521 }
1522 case X86::BI__builtin_ia32_scattersiv8df:
1523 case X86::BI__builtin_ia32_scattersiv16sf:
1524 case X86::BI__builtin_ia32_scatterdiv8df:
1525 case X86::BI__builtin_ia32_scatterdiv16sf:
1526 case X86::BI__builtin_ia32_scattersiv8di:
1527 case X86::BI__builtin_ia32_scattersiv16si:
1528 case X86::BI__builtin_ia32_scatterdiv8di:
1529 case X86::BI__builtin_ia32_scatterdiv16si:
1530 case X86::BI__builtin_ia32_scatterdiv2df:
1531 case X86::BI__builtin_ia32_scatterdiv2di:
1532 case X86::BI__builtin_ia32_scatterdiv4df:
1533 case X86::BI__builtin_ia32_scatterdiv4di:
1534 case X86::BI__builtin_ia32_scatterdiv4sf:
1535 case X86::BI__builtin_ia32_scatterdiv4si:
1536 case X86::BI__builtin_ia32_scatterdiv8sf:
1537 case X86::BI__builtin_ia32_scatterdiv8si:
1538 case X86::BI__builtin_ia32_scattersiv2df:
1539 case X86::BI__builtin_ia32_scattersiv2di:
1540 case X86::BI__builtin_ia32_scattersiv4df:
1541 case X86::BI__builtin_ia32_scattersiv4di:
1542 case X86::BI__builtin_ia32_scattersiv4sf:
1543 case X86::BI__builtin_ia32_scattersiv4si:
1544 case X86::BI__builtin_ia32_scattersiv8sf:
1545 case X86::BI__builtin_ia32_scattersiv8si: {
1546 llvm::StringRef intrinsicName;
1547 switch (builtinID) {
1548 default:
1549 llvm_unreachable("Unexpected builtin");
1550 case X86::BI__builtin_ia32_scattersiv8df:
1551 intrinsicName = "x86.avx512.mask.scatter.dpd.512";
1552 break;
1553 case X86::BI__builtin_ia32_scattersiv16sf:
1554 intrinsicName = "x86.avx512.mask.scatter.dps.512";
1555 break;
1556 case X86::BI__builtin_ia32_scatterdiv8df:
1557 intrinsicName = "x86.avx512.mask.scatter.qpd.512";
1558 break;
1559 case X86::BI__builtin_ia32_scatterdiv16sf:
1560 intrinsicName = "x86.avx512.mask.scatter.qps.512";
1561 break;
1562 case X86::BI__builtin_ia32_scattersiv8di:
1563 intrinsicName = "x86.avx512.mask.scatter.dpq.512";
1564 break;
1565 case X86::BI__builtin_ia32_scattersiv16si:
1566 intrinsicName = "x86.avx512.mask.scatter.dpi.512";
1567 break;
1568 case X86::BI__builtin_ia32_scatterdiv8di:
1569 intrinsicName = "x86.avx512.mask.scatter.qpq.512";
1570 break;
1571 case X86::BI__builtin_ia32_scatterdiv16si:
1572 intrinsicName = "x86.avx512.mask.scatter.qpi.512";
1573 break;
1574 case X86::BI__builtin_ia32_scatterdiv2df:
1575 intrinsicName = "x86.avx512.mask.scatterdiv2.df";
1576 break;
1577 case X86::BI__builtin_ia32_scatterdiv2di:
1578 intrinsicName = "x86.avx512.mask.scatterdiv2.di";
1579 break;
1580 case X86::BI__builtin_ia32_scatterdiv4df:
1581 intrinsicName = "x86.avx512.mask.scatterdiv4.df";
1582 break;
1583 case X86::BI__builtin_ia32_scatterdiv4di:
1584 intrinsicName = "x86.avx512.mask.scatterdiv4.di";
1585 break;
1586 case X86::BI__builtin_ia32_scatterdiv4sf:
1587 intrinsicName = "x86.avx512.mask.scatterdiv4.sf";
1588 break;
1589 case X86::BI__builtin_ia32_scatterdiv4si:
1590 intrinsicName = "x86.avx512.mask.scatterdiv4.si";
1591 break;
1592 case X86::BI__builtin_ia32_scatterdiv8sf:
1593 intrinsicName = "x86.avx512.mask.scatterdiv8.sf";
1594 break;
1595 case X86::BI__builtin_ia32_scatterdiv8si:
1596 intrinsicName = "x86.avx512.mask.scatterdiv8.si";
1597 break;
1598 case X86::BI__builtin_ia32_scattersiv2df:
1599 intrinsicName = "x86.avx512.mask.scattersiv2.df";
1600 break;
1601 case X86::BI__builtin_ia32_scattersiv2di:
1602 intrinsicName = "x86.avx512.mask.scattersiv2.di";
1603 break;
1604 case X86::BI__builtin_ia32_scattersiv4df:
1605 intrinsicName = "x86.avx512.mask.scattersiv4.df";
1606 break;
1607 case X86::BI__builtin_ia32_scattersiv4di:
1608 intrinsicName = "x86.avx512.mask.scattersiv4.di";
1609 break;
1610 case X86::BI__builtin_ia32_scattersiv4sf:
1611 intrinsicName = "x86.avx512.mask.scattersiv4.sf";
1612 break;
1613 case X86::BI__builtin_ia32_scattersiv4si:
1614 intrinsicName = "x86.avx512.mask.scattersiv4.si";
1615 break;
1616 case X86::BI__builtin_ia32_scattersiv8sf:
1617 intrinsicName = "x86.avx512.mask.scattersiv8.sf";
1618 break;
1619 case X86::BI__builtin_ia32_scattersiv8si:
1620 intrinsicName = "x86.avx512.mask.scattersiv8.si";
1621 break;
1622 }
1623
1624 mlir::Location loc = getLoc(expr->getExprLoc());
1625 unsigned minElts =
1626 std::min(cast<cir::VectorType>(ops[2].getType()).getSize(),
1627 cast<cir::VectorType>(ops[3].getType()).getSize());
1628 ops[1] = getMaskVecValue(builder, loc, ops[1], minElts);
1629
1630 return builder.emitIntrinsicCallOp(loc, intrinsicName,
1631 convertType(expr->getType()), ops);
1632 }
1633 case X86::BI__builtin_ia32_vextractf128_pd256:
1634 case X86::BI__builtin_ia32_vextractf128_ps256:
1635 case X86::BI__builtin_ia32_vextractf128_si256:
1636 case X86::BI__builtin_ia32_extract128i256:
1637 case X86::BI__builtin_ia32_extractf64x4_mask:
1638 case X86::BI__builtin_ia32_extractf32x4_mask:
1639 case X86::BI__builtin_ia32_extracti64x4_mask:
1640 case X86::BI__builtin_ia32_extracti32x4_mask:
1641 case X86::BI__builtin_ia32_extractf32x8_mask:
1642 case X86::BI__builtin_ia32_extracti32x8_mask:
1643 case X86::BI__builtin_ia32_extractf32x4_256_mask:
1644 case X86::BI__builtin_ia32_extracti32x4_256_mask:
1645 case X86::BI__builtin_ia32_extractf64x2_256_mask:
1646 case X86::BI__builtin_ia32_extracti64x2_256_mask:
1647 case X86::BI__builtin_ia32_extractf64x2_512_mask:
1648 case X86::BI__builtin_ia32_extracti64x2_512_mask: {
1649 mlir::Location loc = getLoc(expr->getExprLoc());
1650 cir::VectorType dstTy = cast<cir::VectorType>(convertType(expr->getType()));
1651 unsigned numElts = dstTy.getSize();
1652 unsigned srcNumElts = cast<cir::VectorType>(ops[0].getType()).getSize();
1653 unsigned subVectors = srcNumElts / numElts;
1654 assert(llvm::isPowerOf2_32(subVectors) && "Expected power of 2 subvectors");
1655 unsigned index =
1656 ops[1].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue();
1657
1658 index &= subVectors - 1; // Remove any extra bits.
1659 index *= numElts;
1660
1661 int64_t indices[16];
1662 std::iota(indices, indices + numElts, index);
1663
1664 mlir::Value poison =
1665 builder.getConstant(loc, cir::PoisonAttr::get(ops[0].getType()));
1666 mlir::Value res = builder.createVecShuffle(loc, ops[0], poison,
1667 ArrayRef(indices, numElts));
1668 if (ops.size() == 4)
1669 res = emitX86Select(builder, loc, ops[3], res, ops[2]);
1670
1671 return res;
1672 }
1673 case X86::BI__builtin_ia32_vinsertf128_pd256:
1674 case X86::BI__builtin_ia32_vinsertf128_ps256:
1675 case X86::BI__builtin_ia32_vinsertf128_si256:
1676 case X86::BI__builtin_ia32_insert128i256:
1677 case X86::BI__builtin_ia32_insertf64x4:
1678 case X86::BI__builtin_ia32_insertf32x4:
1679 case X86::BI__builtin_ia32_inserti64x4:
1680 case X86::BI__builtin_ia32_inserti32x4:
1681 case X86::BI__builtin_ia32_insertf32x8:
1682 case X86::BI__builtin_ia32_inserti32x8:
1683 case X86::BI__builtin_ia32_insertf32x4_256:
1684 case X86::BI__builtin_ia32_inserti32x4_256:
1685 case X86::BI__builtin_ia32_insertf64x2_256:
1686 case X86::BI__builtin_ia32_inserti64x2_256:
1687 case X86::BI__builtin_ia32_insertf64x2_512:
1688 case X86::BI__builtin_ia32_inserti64x2_512: {
1689 unsigned dstNumElts = cast<cir::VectorType>(ops[0].getType()).getSize();
1690 unsigned srcNumElts = cast<cir::VectorType>(ops[1].getType()).getSize();
1691 unsigned subVectors = dstNumElts / srcNumElts;
1692 assert(llvm::isPowerOf2_32(subVectors) && "Expected power of 2 subvectors");
1693 assert(dstNumElts <= 16);
1694
1695 uint64_t index = getZExtIntValueFromConstOp(ops[2]);
1696 index &= subVectors - 1; // Remove any extra bits.
1697 index *= srcNumElts;
1698
1699 llvm::SmallVector<int64_t, 16> mask(dstNumElts);
1700 for (unsigned i = 0; i != dstNumElts; ++i)
1701 mask[i] = (i >= srcNumElts) ? srcNumElts + (i % srcNumElts) : i;
1702
1703 mlir::Value op1 =
1704 builder.createVecShuffle(getLoc(expr->getExprLoc()), ops[1], mask);
1705
1706 for (unsigned i = 0; i != dstNumElts; ++i) {
1707 if (i >= index && i < (index + srcNumElts))
1708 mask[i] = (i - index) + dstNumElts;
1709 else
1710 mask[i] = i;
1711 }
1712
1713 return builder.createVecShuffle(getLoc(expr->getExprLoc()), ops[0], op1,
1714 mask);
1715 }
1716 case X86::BI__builtin_ia32_pmovqd512_mask:
1717 case X86::BI__builtin_ia32_pmovwb512_mask: {
1718 mlir::Value Res =
1719 builder.createIntCast(ops[0], cast<cir::VectorType>(ops[1].getType()));
1720 return emitX86Select(builder, getLoc(expr->getExprLoc()), ops[2], Res,
1721 ops[1]);
1722 }
1723 case X86::BI__builtin_ia32_pblendw128:
1724 case X86::BI__builtin_ia32_blendpd:
1725 case X86::BI__builtin_ia32_blendps:
1726 case X86::BI__builtin_ia32_blendpd256:
1727 case X86::BI__builtin_ia32_blendps256:
1728 case X86::BI__builtin_ia32_pblendw256:
1729 case X86::BI__builtin_ia32_pblendd128:
1730 case X86::BI__builtin_ia32_pblendd256: {
1731 uint32_t imm = getZExtIntValueFromConstOp(ops[2]);
1732 unsigned numElts = cast<cir::VectorType>(ops[0].getType()).getSize();
1733
1735 // If there are more than 8 elements, the immediate is used twice so make
1736 // sure we handle that.
1737 mlir::Type i32Ty = builder.getSInt32Ty();
1738 for (unsigned i = 0; i != numElts; ++i)
1739 indices.push_back(
1740 cir::IntAttr::get(i32Ty, ((imm >> (i % 8)) & 0x1) ? numElts + i : i));
1741
1742 return builder.createVecShuffle(getLoc(expr->getExprLoc()), ops[0], ops[1],
1743 indices);
1744 }
1745 case X86::BI__builtin_ia32_pshuflw:
1746 case X86::BI__builtin_ia32_pshuflw256:
1747 case X86::BI__builtin_ia32_pshuflw512:
1748 return emitPshufWord(builder, ops[0], ops[1], getLoc(expr->getExprLoc()),
1749 true);
1750 case X86::BI__builtin_ia32_pshufhw:
1751 case X86::BI__builtin_ia32_pshufhw256:
1752 case X86::BI__builtin_ia32_pshufhw512:
1753 return emitPshufWord(builder, ops[0], ops[1], getLoc(expr->getExprLoc()),
1754 false);
1755 case X86::BI__builtin_ia32_pshufd:
1756 case X86::BI__builtin_ia32_pshufd256:
1757 case X86::BI__builtin_ia32_pshufd512:
1758 case X86::BI__builtin_ia32_vpermilpd:
1759 case X86::BI__builtin_ia32_vpermilps:
1760 case X86::BI__builtin_ia32_vpermilpd256:
1761 case X86::BI__builtin_ia32_vpermilps256:
1762 case X86::BI__builtin_ia32_vpermilpd512:
1763 case X86::BI__builtin_ia32_vpermilps512: {
1764 const uint32_t imm = getSExtIntValueFromConstOp(ops[1]);
1765
1767 computeFullLaneShuffleMask(*this, ops[0], imm, false, mask);
1768
1769 return builder.createVecShuffle(getLoc(expr->getExprLoc()), ops[0], mask);
1770 }
1771 case X86::BI__builtin_ia32_shufpd:
1772 case X86::BI__builtin_ia32_shufpd256:
1773 case X86::BI__builtin_ia32_shufpd512:
1774 case X86::BI__builtin_ia32_shufps:
1775 case X86::BI__builtin_ia32_shufps256:
1776 case X86::BI__builtin_ia32_shufps512: {
1777 const uint32_t imm = getZExtIntValueFromConstOp(ops[2]);
1778
1780 computeFullLaneShuffleMask(*this, ops[0], imm, true, mask);
1781
1782 return builder.createVecShuffle(getLoc(expr->getExprLoc()), ops[0], ops[1],
1783 mask);
1784 }
1785 case X86::BI__builtin_ia32_permdi256:
1786 case X86::BI__builtin_ia32_permdf256:
1787 case X86::BI__builtin_ia32_permdi512:
1788 case X86::BI__builtin_ia32_permdf512: {
1789 unsigned imm =
1790 ops[1].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue();
1791 unsigned numElts = cast<cir::VectorType>(ops[0].getType()).getSize();
1792
1793 // These intrinsics operate on 256-bit lanes of four 64-bit elements.
1794 int64_t Indices[8];
1795
1796 for (unsigned l = 0; l != numElts; l += 4)
1797 for (unsigned i = 0; i != 4; ++i)
1798 Indices[l + i] = l + ((imm >> (2 * i)) & 0x3);
1799
1800 return builder.createVecShuffle(getLoc(expr->getExprLoc()), ops[0],
1801 ArrayRef(Indices, numElts));
1802 }
1803 case X86::BI__builtin_ia32_palignr128:
1804 case X86::BI__builtin_ia32_palignr256:
1805 case X86::BI__builtin_ia32_palignr512: {
1806 uint32_t shiftVal = getZExtIntValueFromConstOp(ops[2]) & 0xff;
1807
1808 unsigned numElts = cast<cir::VectorType>(ops[0].getType()).getSize();
1809 assert(numElts % 16 == 0);
1810
1811 // If palignr is shifting the pair of vectors more than the size of two
1812 // lanes, emit zero.
1813 if (shiftVal >= 32)
1814 return builder.getNullValue(convertType(expr->getType()),
1815 getLoc(expr->getExprLoc()));
1816
1817 // If palignr is shifting the pair of input vectors more than one lane,
1818 // but less than two lanes, convert to shifting in zeroes.
1819 if (shiftVal > 16) {
1820 shiftVal -= 16;
1821 ops[1] = ops[0];
1822 ops[0] =
1823 builder.getNullValue(ops[0].getType(), getLoc(expr->getExprLoc()));
1824 }
1825
1826 int64_t indices[64];
1827 // 256-bit palignr operates on 128-bit lanes so we need to handle that
1828 for (unsigned l = 0; l != numElts; l += 16) {
1829 for (unsigned i = 0; i != 16; ++i) {
1830 uint32_t idx = shiftVal + i;
1831 if (idx >= 16)
1832 idx += numElts - 16; // End of lane, switch operand.
1833 indices[l + i] = l + idx;
1834 }
1835 }
1836
1837 return builder.createVecShuffle(getLoc(expr->getExprLoc()), ops[1], ops[0],
1838 ArrayRef(indices, numElts));
1839 }
1840 case X86::BI__builtin_ia32_alignd128:
1841 case X86::BI__builtin_ia32_alignd256:
1842 case X86::BI__builtin_ia32_alignd512:
1843 case X86::BI__builtin_ia32_alignq128:
1844 case X86::BI__builtin_ia32_alignq256:
1845 case X86::BI__builtin_ia32_alignq512: {
1846 unsigned numElts = cast<cir::VectorType>(ops[0].getType()).getSize();
1847 unsigned shiftVal =
1848 ops[2].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue() &
1849 0xff;
1850
1851 // Mask the shift amount to width of a vector.
1852 shiftVal &= numElts - 1;
1853
1855 mlir::Type i32Ty = builder.getSInt32Ty();
1856 for (unsigned i = 0; i != numElts; ++i)
1857 indices.push_back(cir::IntAttr::get(i32Ty, i + shiftVal));
1858
1859 return builder.createVecShuffle(getLoc(expr->getExprLoc()), ops[0], ops[1],
1860 indices);
1861 }
1862 case X86::BI__builtin_ia32_shuf_f32x4_256:
1863 case X86::BI__builtin_ia32_shuf_f64x2_256:
1864 case X86::BI__builtin_ia32_shuf_i32x4_256:
1865 case X86::BI__builtin_ia32_shuf_i64x2_256:
1866 case X86::BI__builtin_ia32_shuf_f32x4:
1867 case X86::BI__builtin_ia32_shuf_f64x2:
1868 case X86::BI__builtin_ia32_shuf_i32x4:
1869 case X86::BI__builtin_ia32_shuf_i64x2: {
1870 mlir::Value src1 = ops[0];
1871 mlir::Value src2 = ops[1];
1872
1873 unsigned imm =
1874 ops[2].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue();
1875
1876 unsigned numElems = cast<cir::VectorType>(src1.getType()).getSize();
1877 unsigned totalBits = getContext().getTypeSize(expr->getArg(0)->getType());
1878 unsigned numLanes = totalBits == 512 ? 4 : 2;
1879 unsigned numElemsPerLane = numElems / numLanes;
1880
1882 mlir::Type i32Ty = builder.getSInt32Ty();
1883
1884 for (unsigned l = 0; l != numElems; l += numElemsPerLane) {
1885 unsigned index = (imm % numLanes) * numElemsPerLane;
1886 imm /= numLanes;
1887 if (l >= (numElems / 2))
1888 index += numElems;
1889 for (unsigned i = 0; i != numElemsPerLane; ++i) {
1890 indices.push_back(cir::IntAttr::get(i32Ty, index + i));
1891 }
1892 }
1893
1894 return builder.createVecShuffle(getLoc(expr->getExprLoc()), src1, src2,
1895 indices);
1896 }
1897 case X86::BI__builtin_ia32_vperm2f128_pd256:
1898 case X86::BI__builtin_ia32_vperm2f128_ps256:
1899 case X86::BI__builtin_ia32_vperm2f128_si256:
1900 case X86::BI__builtin_ia32_permti256:
1901 return emitX86VPerm2f128(builder, getLoc(expr->getExprLoc()), ops);
1902 case X86::BI__builtin_ia32_pslldqi128_byteshift:
1903 case X86::BI__builtin_ia32_pslldqi256_byteshift:
1904 case X86::BI__builtin_ia32_pslldqi512_byteshift:
1905 return emitX86PackedByteShift(builder, builtinID,
1906 getLoc(expr->getExprLoc()), ops,
1907 /**isLeftShift=*/true);
1908 case X86::BI__builtin_ia32_psrldqi128_byteshift:
1909 case X86::BI__builtin_ia32_psrldqi256_byteshift:
1910 case X86::BI__builtin_ia32_psrldqi512_byteshift:
1911 return emitX86PackedByteShift(builder, builtinID,
1912 getLoc(expr->getExprLoc()), ops,
1913 /**isLeftShift=*/false);
1914 case X86::BI__builtin_ia32_kshiftliqi:
1915 case X86::BI__builtin_ia32_kshiftlihi:
1916 case X86::BI__builtin_ia32_kshiftlisi:
1917 case X86::BI__builtin_ia32_kshiftlidi: {
1918 mlir::Location loc = getLoc(expr->getExprLoc());
1919 unsigned shiftVal =
1920 ops[1].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue() &
1921 0xff;
1922 unsigned numElems = cast<cir::IntType>(ops[0].getType()).getWidth();
1923
1924 if (shiftVal >= numElems)
1925 return builder.getNullValue(ops[0].getType(), loc);
1926
1927 mlir::Value in = getMaskVecValue(builder, loc, ops[0], numElems);
1928
1930 mlir::Type i32Ty = builder.getSInt32Ty();
1931 for (auto i : llvm::seq<unsigned>(0, numElems))
1932 indices.push_back(cir::IntAttr::get(i32Ty, numElems + i - shiftVal));
1933
1934 mlir::Value zero = builder.getNullValue(in.getType(), loc);
1935 mlir::Value sv = builder.createVecShuffle(loc, zero, in, indices);
1936 return builder.createBitcast(sv, ops[0].getType());
1937 }
1938 case X86::BI__builtin_ia32_kshiftriqi:
1939 case X86::BI__builtin_ia32_kshiftrihi:
1940 case X86::BI__builtin_ia32_kshiftrisi:
1941 case X86::BI__builtin_ia32_kshiftridi: {
1942 mlir::Location loc = getLoc(expr->getExprLoc());
1943 unsigned shiftVal =
1944 ops[1].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue() &
1945 0xff;
1946 unsigned numElems = cast<cir::IntType>(ops[0].getType()).getWidth();
1947
1948 if (shiftVal >= numElems)
1949 return builder.getNullValue(ops[0].getType(), loc);
1950
1951 mlir::Value in = getMaskVecValue(builder, loc, ops[0], numElems);
1952
1954 mlir::Type i32Ty = builder.getSInt32Ty();
1955 for (auto i : llvm::seq<unsigned>(0, numElems))
1956 indices.push_back(cir::IntAttr::get(i32Ty, i + shiftVal));
1957
1958 mlir::Value zero = builder.getNullValue(in.getType(), loc);
1959 mlir::Value sv = builder.createVecShuffle(loc, in, zero, indices);
1960 return builder.createBitcast(sv, ops[0].getType());
1961 }
1962 case X86::BI__builtin_ia32_movnti:
1963 case X86::BI__builtin_ia32_movnti64:
1964 case X86::BI__builtin_ia32_movntsd:
1965 case X86::BI__builtin_ia32_movntss: {
1966 mlir::Location loc = getLoc(expr->getExprLoc());
1967
1968 Address dest = Address{ops[0], CharUnits::One()};
1969 mlir::Value src = ops[1];
1970
1971 if (builtinID == X86::BI__builtin_ia32_movntsd ||
1972 builtinID == X86::BI__builtin_ia32_movntss)
1973 src = builder.createExtractElement(loc, ops[1], 0);
1974
1975 cir::StoreOp so =
1976 builder.createStore(loc, src, dest,
1977 /*isVolatile=*/false, /*isNontemporal=*/true);
1978 return so.getValue();
1979 }
1980 case X86::BI__builtin_ia32_vprotbi:
1981 case X86::BI__builtin_ia32_vprotwi:
1982 case X86::BI__builtin_ia32_vprotdi:
1983 case X86::BI__builtin_ia32_vprotqi:
1984 case X86::BI__builtin_ia32_prold128:
1985 case X86::BI__builtin_ia32_prold256:
1986 case X86::BI__builtin_ia32_prold512:
1987 case X86::BI__builtin_ia32_prolq128:
1988 case X86::BI__builtin_ia32_prolq256:
1989 case X86::BI__builtin_ia32_prolq512:
1990 return emitX86FunnelShift(builder, getLoc(expr->getExprLoc()), ops[0],
1991 ops[0], ops[1], false);
1992 case X86::BI__builtin_ia32_prord128:
1993 case X86::BI__builtin_ia32_prord256:
1994 case X86::BI__builtin_ia32_prord512:
1995 case X86::BI__builtin_ia32_prorq128:
1996 case X86::BI__builtin_ia32_prorq256:
1997 case X86::BI__builtin_ia32_prorq512:
1998 return emitX86FunnelShift(builder, getLoc(expr->getExprLoc()), ops[0],
1999 ops[0], ops[1], true);
2000 case X86::BI__builtin_ia32_selectb_128:
2001 case X86::BI__builtin_ia32_selectb_256:
2002 case X86::BI__builtin_ia32_selectb_512:
2003 case X86::BI__builtin_ia32_selectw_128:
2004 case X86::BI__builtin_ia32_selectw_256:
2005 case X86::BI__builtin_ia32_selectw_512:
2006 case X86::BI__builtin_ia32_selectd_128:
2007 case X86::BI__builtin_ia32_selectd_256:
2008 case X86::BI__builtin_ia32_selectd_512:
2009 case X86::BI__builtin_ia32_selectq_128:
2010 case X86::BI__builtin_ia32_selectq_256:
2011 case X86::BI__builtin_ia32_selectq_512:
2012 case X86::BI__builtin_ia32_selectph_128:
2013 case X86::BI__builtin_ia32_selectph_256:
2014 case X86::BI__builtin_ia32_selectph_512:
2015 case X86::BI__builtin_ia32_selectpbf_128:
2016 case X86::BI__builtin_ia32_selectpbf_256:
2017 case X86::BI__builtin_ia32_selectpbf_512:
2018 case X86::BI__builtin_ia32_selectps_128:
2019 case X86::BI__builtin_ia32_selectps_256:
2020 case X86::BI__builtin_ia32_selectps_512:
2021 case X86::BI__builtin_ia32_selectpd_128:
2022 case X86::BI__builtin_ia32_selectpd_256:
2023 case X86::BI__builtin_ia32_selectpd_512:
2024 return emitX86Select(builder, getLoc(expr->getExprLoc()), ops[0], ops[1],
2025 ops[2]);
2026 case X86::BI__builtin_ia32_selectsh_128:
2027 case X86::BI__builtin_ia32_selectsbf_128:
2028 case X86::BI__builtin_ia32_selectss_128:
2029 case X86::BI__builtin_ia32_selectsd_128: {
2030 mlir::Location loc = getLoc(expr->getExprLoc());
2031 mlir::Value scalar1 =
2032 builder.createExtractElement(loc, ops[1], uint64_t(0));
2033 mlir::Value scalar2 =
2034 builder.createExtractElement(loc, ops[2], uint64_t(0));
2035 mlir::Value result =
2036 emitX86ScalarSelect(builder, loc, ops[0], scalar1, scalar2);
2037 return builder.createInsertElement(loc, ops[1], result, uint64_t(0));
2038 }
2039 case X86::BI__builtin_ia32_cmpb128_mask:
2040 case X86::BI__builtin_ia32_cmpb256_mask:
2041 case X86::BI__builtin_ia32_cmpb512_mask:
2042 case X86::BI__builtin_ia32_cmpw128_mask:
2043 case X86::BI__builtin_ia32_cmpw256_mask:
2044 case X86::BI__builtin_ia32_cmpw512_mask:
2045 case X86::BI__builtin_ia32_cmpd128_mask:
2046 case X86::BI__builtin_ia32_cmpd256_mask:
2047 case X86::BI__builtin_ia32_cmpd512_mask:
2048 case X86::BI__builtin_ia32_cmpq128_mask:
2049 case X86::BI__builtin_ia32_cmpq256_mask:
2050 case X86::BI__builtin_ia32_cmpq512_mask:
2051 case X86::BI__builtin_ia32_ucmpb128_mask:
2052 case X86::BI__builtin_ia32_ucmpb256_mask:
2053 case X86::BI__builtin_ia32_ucmpb512_mask:
2054 case X86::BI__builtin_ia32_ucmpw128_mask:
2055 case X86::BI__builtin_ia32_ucmpw256_mask:
2056 case X86::BI__builtin_ia32_ucmpw512_mask:
2057 case X86::BI__builtin_ia32_ucmpd128_mask:
2058 case X86::BI__builtin_ia32_ucmpd256_mask:
2059 case X86::BI__builtin_ia32_ucmpd512_mask:
2060 case X86::BI__builtin_ia32_ucmpq128_mask:
2061 case X86::BI__builtin_ia32_ucmpq256_mask:
2062 case X86::BI__builtin_ia32_ucmpq512_mask: {
2063 int64_t cc = CIRGenFunction::getZExtIntValueFromConstOp(ops[2]) & 0x7;
2064 return emitX86MaskedCompare(builder, cc, 1, ops,
2065 getLoc(expr->getExprLoc()));
2066 }
2067 case X86::BI__builtin_ia32_vpcomb:
2068 case X86::BI__builtin_ia32_vpcomw:
2069 case X86::BI__builtin_ia32_vpcomd:
2070 case X86::BI__builtin_ia32_vpcomq:
2071 return emitX86vpcom(builder, getLoc(expr->getExprLoc()), ops, true);
2072 case X86::BI__builtin_ia32_vpcomub:
2073 case X86::BI__builtin_ia32_vpcomuw:
2074 case X86::BI__builtin_ia32_vpcomud:
2075 case X86::BI__builtin_ia32_vpcomuq:
2076 return emitX86vpcom(builder, getLoc(expr->getExprLoc()), ops, false);
2077 case X86::BI__builtin_ia32_kortestcqi:
2078 case X86::BI__builtin_ia32_kortestchi:
2079 case X86::BI__builtin_ia32_kortestcsi:
2080 case X86::BI__builtin_ia32_kortestcdi: {
2081 mlir::Location loc = getLoc(expr->getExprLoc());
2082 cir::IntType ty = cast<cir::IntType>(ops[0].getType());
2083 mlir::Value allOnesOp =
2084 builder.getConstAPInt(loc, ty, APInt::getAllOnes(ty.getWidth()));
2085 mlir::Value orOp = emitX86MaskLogic<cir::OrOp>(builder, loc, ops);
2086 mlir::Value cmp =
2087 cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, orOp, allOnesOp);
2088 return builder.createCast(cir::CastKind::bool_to_int, cmp,
2089 cgm.convertType(expr->getType()));
2090 }
2091 case X86::BI__builtin_ia32_kortestzqi:
2092 case X86::BI__builtin_ia32_kortestzhi:
2093 case X86::BI__builtin_ia32_kortestzsi:
2094 case X86::BI__builtin_ia32_kortestzdi: {
2095 mlir::Location loc = getLoc(expr->getExprLoc());
2096 cir::IntType ty = cast<cir::IntType>(ops[0].getType());
2097 mlir::Value allZerosOp = builder.getNullValue(ty, loc).getResult();
2098 mlir::Value orOp = emitX86MaskLogic<cir::OrOp>(builder, loc, ops);
2099 mlir::Value cmp =
2100 cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, orOp, allZerosOp);
2101 return builder.createCast(cir::CastKind::bool_to_int, cmp,
2102 cgm.convertType(expr->getType()));
2103 }
2104 case X86::BI__builtin_ia32_ktestcqi:
2105 return emitX86MaskTest(builder, getLoc(expr->getExprLoc()),
2106 "x86.avx512.ktestc.b", ops);
2107 case X86::BI__builtin_ia32_ktestzqi:
2108 return emitX86MaskTest(builder, getLoc(expr->getExprLoc()),
2109 "x86.avx512.ktestz.b", ops);
2110 case X86::BI__builtin_ia32_ktestchi:
2111 return emitX86MaskTest(builder, getLoc(expr->getExprLoc()),
2112 "x86.avx512.ktestc.w", ops);
2113 case X86::BI__builtin_ia32_ktestzhi:
2114 return emitX86MaskTest(builder, getLoc(expr->getExprLoc()),
2115 "x86.avx512.ktestz.w", ops);
2116 case X86::BI__builtin_ia32_ktestcsi:
2117 return emitX86MaskTest(builder, getLoc(expr->getExprLoc()),
2118 "x86.avx512.ktestc.d", ops);
2119 case X86::BI__builtin_ia32_ktestzsi:
2120 return emitX86MaskTest(builder, getLoc(expr->getExprLoc()),
2121 "x86.avx512.ktestz.d", ops);
2122 case X86::BI__builtin_ia32_ktestcdi:
2123 return emitX86MaskTest(builder, getLoc(expr->getExprLoc()),
2124 "x86.avx512.ktestc.q", ops);
2125 case X86::BI__builtin_ia32_ktestzdi:
2126 return emitX86MaskTest(builder, getLoc(expr->getExprLoc()),
2127 "x86.avx512.ktestz.q", ops);
2128 case X86::BI__builtin_ia32_kaddqi:
2129 return emitX86MaskAddLogic(builder, getLoc(expr->getExprLoc()),
2130 "x86.avx512.kadd.b", ops);
2131 case X86::BI__builtin_ia32_kaddhi:
2132 return emitX86MaskAddLogic(builder, getLoc(expr->getExprLoc()),
2133 "x86.avx512.kadd.w", ops);
2134 case X86::BI__builtin_ia32_kaddsi:
2135 return emitX86MaskAddLogic(builder, getLoc(expr->getExprLoc()),
2136 "x86.avx512.kadd.d", ops);
2137 case X86::BI__builtin_ia32_kadddi:
2138 return emitX86MaskAddLogic(builder, getLoc(expr->getExprLoc()),
2139 "x86.avx512.kadd.q", ops);
2140 case X86::BI__builtin_ia32_kandqi:
2141 case X86::BI__builtin_ia32_kandhi:
2142 case X86::BI__builtin_ia32_kandsi:
2143 case X86::BI__builtin_ia32_kanddi:
2144 return emitX86MaskLogic<cir::AndOp>(builder, getLoc(expr->getExprLoc()),
2145 ops);
2146 case X86::BI__builtin_ia32_kandnqi:
2147 case X86::BI__builtin_ia32_kandnhi:
2148 case X86::BI__builtin_ia32_kandnsi:
2149 case X86::BI__builtin_ia32_kandndi:
2150 return emitX86MaskLogic<cir::AndOp>(builder, getLoc(expr->getExprLoc()),
2151 ops, /*invertLHS=*/true);
2152 case X86::BI__builtin_ia32_korqi:
2153 case X86::BI__builtin_ia32_korhi:
2154 case X86::BI__builtin_ia32_korsi:
2155 case X86::BI__builtin_ia32_kordi:
2156 return emitX86MaskLogic<cir::OrOp>(builder, getLoc(expr->getExprLoc()),
2157 ops);
2158 case X86::BI__builtin_ia32_kxnorqi:
2159 case X86::BI__builtin_ia32_kxnorhi:
2160 case X86::BI__builtin_ia32_kxnorsi:
2161 case X86::BI__builtin_ia32_kxnordi:
2162 return emitX86MaskLogic<cir::XorOp>(builder, getLoc(expr->getExprLoc()),
2163 ops, /*invertLHS=*/true);
2164 case X86::BI__builtin_ia32_kxorqi:
2165 case X86::BI__builtin_ia32_kxorhi:
2166 case X86::BI__builtin_ia32_kxorsi:
2167 case X86::BI__builtin_ia32_kxordi:
2168 return emitX86MaskLogic<cir::XorOp>(builder, getLoc(expr->getExprLoc()),
2169 ops);
2170 case X86::BI__builtin_ia32_knotqi:
2171 case X86::BI__builtin_ia32_knothi:
2172 case X86::BI__builtin_ia32_knotsi:
2173 case X86::BI__builtin_ia32_knotdi: {
2174 cir::IntType intTy = cast<cir::IntType>(ops[0].getType());
2175 unsigned numElts = intTy.getWidth();
2176 mlir::Value resVec =
2177 getMaskVecValue(builder, getLoc(expr->getExprLoc()), ops[0], numElts);
2178 return builder.createBitcast(builder.createNot(resVec), ops[0].getType());
2179 }
2180 case X86::BI__builtin_ia32_kmovb:
2181 case X86::BI__builtin_ia32_kmovw:
2182 case X86::BI__builtin_ia32_kmovd:
2183 case X86::BI__builtin_ia32_kmovq: {
2184 // Bitcast to vXi1 type and then back to integer. This gets the mask
2185 // register type into the IR, but might be optimized out depending on
2186 // what's around it.
2187 cir::IntType intTy = cast<cir::IntType>(ops[0].getType());
2188 unsigned numElts = intTy.getWidth();
2189 mlir::Value resVec =
2190 getMaskVecValue(builder, getLoc(expr->getExprLoc()), ops[0], numElts);
2191 return builder.createBitcast(resVec, ops[0].getType());
2192 }
2193 case X86::BI__builtin_ia32_sqrtsh_round_mask:
2194 case X86::BI__builtin_ia32_sqrtsd_round_mask:
2195 case X86::BI__builtin_ia32_sqrtss_round_mask:
2196 cgm.errorNYI(expr->getSourceRange(),
2197 std::string("unimplemented X86 builtin call: ") +
2198 getContext().BuiltinInfo.getName(builtinID));
2199 return mlir::Value{};
2200 case X86::BI__builtin_ia32_sqrtph512:
2201 case X86::BI__builtin_ia32_sqrtps512:
2202 case X86::BI__builtin_ia32_sqrtpd512: {
2203 mlir::Location loc = getLoc(expr->getExprLoc());
2204 mlir::Value arg = ops[0];
2205 return cir::SqrtOp::create(builder, loc, arg.getType(), arg).getResult();
2206 }
2207 case X86::BI__builtin_ia32_pmuludq128:
2208 case X86::BI__builtin_ia32_pmuludq256:
2209 case X86::BI__builtin_ia32_pmuludq512: {
2210 unsigned opTypePrimitiveSizeInBits =
2211 cgm.getDataLayout().getTypeSizeInBits(ops[0].getType());
2212 return emitX86Muldq(builder, getLoc(expr->getExprLoc()), /*isSigned*/ false,
2213 ops, opTypePrimitiveSizeInBits);
2214 }
2215 case X86::BI__builtin_ia32_pmuldq128:
2216 case X86::BI__builtin_ia32_pmuldq256:
2217 case X86::BI__builtin_ia32_pmuldq512: {
2218 unsigned opTypePrimitiveSizeInBits =
2219 cgm.getDataLayout().getTypeSizeInBits(ops[0].getType());
2220 return emitX86Muldq(builder, getLoc(expr->getExprLoc()), /*isSigned*/ true,
2221 ops, opTypePrimitiveSizeInBits);
2222 }
2223 case X86::BI__builtin_ia32_pternlogd512_mask:
2224 case X86::BI__builtin_ia32_pternlogq512_mask:
2225 case X86::BI__builtin_ia32_pternlogd128_mask:
2226 case X86::BI__builtin_ia32_pternlogd256_mask:
2227 case X86::BI__builtin_ia32_pternlogq128_mask:
2228 case X86::BI__builtin_ia32_pternlogq256_mask:
2229 case X86::BI__builtin_ia32_pternlogd512_maskz:
2230 case X86::BI__builtin_ia32_pternlogq512_maskz:
2231 case X86::BI__builtin_ia32_pternlogd128_maskz:
2232 case X86::BI__builtin_ia32_pternlogd256_maskz:
2233 case X86::BI__builtin_ia32_pternlogq128_maskz:
2234 case X86::BI__builtin_ia32_pternlogq256_maskz:
2235 cgm.errorNYI(expr->getSourceRange(),
2236 std::string("unimplemented X86 builtin call: ") +
2237 getContext().BuiltinInfo.getName(builtinID));
2238 return mlir::Value{};
2239 case X86::BI__builtin_ia32_vpshldd128:
2240 case X86::BI__builtin_ia32_vpshldd256:
2241 case X86::BI__builtin_ia32_vpshldd512:
2242 case X86::BI__builtin_ia32_vpshldq128:
2243 case X86::BI__builtin_ia32_vpshldq256:
2244 case X86::BI__builtin_ia32_vpshldq512:
2245 case X86::BI__builtin_ia32_vpshldw128:
2246 case X86::BI__builtin_ia32_vpshldw256:
2247 case X86::BI__builtin_ia32_vpshldw512:
2248 return emitX86FunnelShift(builder, getLoc(expr->getExprLoc()), ops[0],
2249 ops[1], ops[2], false);
2250 case X86::BI__builtin_ia32_vpshrdd128:
2251 case X86::BI__builtin_ia32_vpshrdd256:
2252 case X86::BI__builtin_ia32_vpshrdd512:
2253 case X86::BI__builtin_ia32_vpshrdq128:
2254 case X86::BI__builtin_ia32_vpshrdq256:
2255 case X86::BI__builtin_ia32_vpshrdq512:
2256 case X86::BI__builtin_ia32_vpshrdw128:
2257 case X86::BI__builtin_ia32_vpshrdw256:
2258 case X86::BI__builtin_ia32_vpshrdw512:
2259 // Ops 0 and 1 are swapped.
2260 return emitX86FunnelShift(builder, getLoc(expr->getExprLoc()), ops[1],
2261 ops[0], ops[2], true);
2262 case X86::BI__builtin_ia32_reduce_fadd_pd512:
2263 case X86::BI__builtin_ia32_reduce_fadd_ps512:
2264 case X86::BI__builtin_ia32_reduce_fadd_ph512:
2265 case X86::BI__builtin_ia32_reduce_fadd_ph256:
2266 case X86::BI__builtin_ia32_reduce_fadd_ph128: {
2268 return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()),
2269 "vector.reduce.fadd", ops[0].getType(),
2270 mlir::ValueRange{ops[0], ops[1]});
2271 }
2272 case X86::BI__builtin_ia32_reduce_fmul_pd512:
2273 case X86::BI__builtin_ia32_reduce_fmul_ps512:
2274 case X86::BI__builtin_ia32_reduce_fmul_ph512:
2275 case X86::BI__builtin_ia32_reduce_fmul_ph256:
2276 case X86::BI__builtin_ia32_reduce_fmul_ph128: {
2278 return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()),
2279 "vector.reduce.fmul", ops[0].getType(),
2280 mlir::ValueRange{ops[0], ops[1]});
2281 }
2282 case X86::BI__builtin_ia32_reduce_fmax_pd512:
2283 case X86::BI__builtin_ia32_reduce_fmax_ps512:
2284 case X86::BI__builtin_ia32_reduce_fmax_ph512:
2285 case X86::BI__builtin_ia32_reduce_fmax_ph256:
2286 case X86::BI__builtin_ia32_reduce_fmax_ph128: {
2288 cir::VectorType vecTy = cast<cir::VectorType>(ops[0].getType());
2289 return builder.emitIntrinsicCallOp(
2290 getLoc(expr->getExprLoc()), "vector.reduce.fmax",
2291 vecTy.getElementType(), mlir::ValueRange{ops[0]});
2292 }
2293 case X86::BI__builtin_ia32_reduce_fmin_pd512:
2294 case X86::BI__builtin_ia32_reduce_fmin_ps512:
2295 case X86::BI__builtin_ia32_reduce_fmin_ph512:
2296 case X86::BI__builtin_ia32_reduce_fmin_ph256:
2297 case X86::BI__builtin_ia32_reduce_fmin_ph128: {
2299 cir::VectorType vecTy = cast<cir::VectorType>(ops[0].getType());
2300 return builder.emitIntrinsicCallOp(
2301 getLoc(expr->getExprLoc()), "vector.reduce.fmin",
2302 vecTy.getElementType(), mlir::ValueRange{ops[0]});
2303 }
2304 case X86::BI__builtin_ia32_rdrand16_step:
2305 case X86::BI__builtin_ia32_rdrand32_step:
2306 case X86::BI__builtin_ia32_rdrand64_step:
2307 case X86::BI__builtin_ia32_rdseed16_step:
2308 case X86::BI__builtin_ia32_rdseed32_step:
2309 case X86::BI__builtin_ia32_rdseed64_step: {
2310 llvm::StringRef intrinsicName;
2311 switch (builtinID) {
2312 default:
2313 llvm_unreachable("Unsupported intrinsic!");
2314 case X86::BI__builtin_ia32_rdrand16_step:
2315 intrinsicName = "x86.rdrand.16";
2316 break;
2317 case X86::BI__builtin_ia32_rdrand32_step:
2318 intrinsicName = "x86.rdrand.32";
2319 break;
2320 case X86::BI__builtin_ia32_rdrand64_step:
2321 intrinsicName = "x86.rdrand.64";
2322 break;
2323 case X86::BI__builtin_ia32_rdseed16_step:
2324 intrinsicName = "x86.rdseed.16";
2325 break;
2326 case X86::BI__builtin_ia32_rdseed32_step:
2327 intrinsicName = "x86.rdseed.32";
2328 break;
2329 case X86::BI__builtin_ia32_rdseed64_step:
2330 intrinsicName = "x86.rdseed.64";
2331 break;
2332 }
2333
2334 mlir::Location loc = getLoc(expr->getExprLoc());
2335 mlir::Type randTy = cast<cir::PointerType>(ops[0].getType()).getPointee();
2336 llvm::SmallVector<mlir::Type, 2> resultTypes = {randTy,
2337 builder.getUInt32Ty()};
2338 cir::StructType resRecord =
2339 cir::StructType::get(&getMLIRContext(), resultTypes, /*packed=*/false,
2340 /*padded=*/false, /*is_class=*/false);
2341
2342 mlir::Value call =
2343 builder.emitIntrinsicCallOp(loc, intrinsicName, resRecord);
2344 mlir::Value rand =
2345 cir::ExtractMemberOp::create(builder, loc, randTy, call, 0);
2346 builder.CIRBaseBuilderTy::createStore(loc, rand, ops[0]);
2347
2348 return cir::ExtractMemberOp::create(builder, loc, builder.getUInt32Ty(),
2349 call, 1);
2350 }
2351 case X86::BI__builtin_ia32_addcarryx_u32:
2352 case X86::BI__builtin_ia32_addcarryx_u64:
2353 case X86::BI__builtin_ia32_subborrow_u32:
2354 case X86::BI__builtin_ia32_subborrow_u64:
2355 cgm.errorNYI(expr->getSourceRange(),
2356 std::string("unimplemented X86 builtin call: ") +
2357 getContext().BuiltinInfo.getName(builtinID));
2358 return mlir::Value{};
2359 case X86::BI__builtin_ia32_fpclassps128_mask:
2360 case X86::BI__builtin_ia32_fpclassps256_mask:
2361 case X86::BI__builtin_ia32_fpclassps512_mask:
2362 case X86::BI__builtin_ia32_vfpclassbf16128_mask:
2363 case X86::BI__builtin_ia32_vfpclassbf16256_mask:
2364 case X86::BI__builtin_ia32_vfpclassbf16512_mask:
2365 case X86::BI__builtin_ia32_fpclassph128_mask:
2366 case X86::BI__builtin_ia32_fpclassph256_mask:
2367 case X86::BI__builtin_ia32_fpclassph512_mask:
2368 case X86::BI__builtin_ia32_fpclasspd128_mask:
2369 case X86::BI__builtin_ia32_fpclasspd256_mask:
2370 case X86::BI__builtin_ia32_fpclasspd512_mask:
2371 return emitX86Fpclass(builder, getLoc(expr->getExprLoc()), builtinID, ops);
2372 case X86::BI__builtin_ia32_vp2intersect_q_512:
2373 case X86::BI__builtin_ia32_vp2intersect_q_256:
2374 case X86::BI__builtin_ia32_vp2intersect_q_128:
2375 case X86::BI__builtin_ia32_vp2intersect_d_512:
2376 case X86::BI__builtin_ia32_vp2intersect_d_256:
2377 case X86::BI__builtin_ia32_vp2intersect_d_128: {
2378 unsigned numElts = cast<cir::VectorType>(ops[0].getType()).getSize();
2379 mlir::Location loc = getLoc(expr->getExprLoc());
2380 StringRef intrinsicName;
2381
2382 switch (builtinID) {
2383 default:
2384 llvm_unreachable("Unexpected builtin");
2385 case X86::BI__builtin_ia32_vp2intersect_q_512:
2386 intrinsicName = "x86.avx512.vp2intersect.q.512";
2387 break;
2388 case X86::BI__builtin_ia32_vp2intersect_q_256:
2389 intrinsicName = "x86.avx512.vp2intersect.q.256";
2390 break;
2391 case X86::BI__builtin_ia32_vp2intersect_q_128:
2392 intrinsicName = "x86.avx512.vp2intersect.q.128";
2393 break;
2394 case X86::BI__builtin_ia32_vp2intersect_d_512:
2395 intrinsicName = "x86.avx512.vp2intersect.d.512";
2396 break;
2397 case X86::BI__builtin_ia32_vp2intersect_d_256:
2398 intrinsicName = "x86.avx512.vp2intersect.d.256";
2399 break;
2400 case X86::BI__builtin_ia32_vp2intersect_d_128:
2401 intrinsicName = "x86.avx512.vp2intersect.d.128";
2402 break;
2403 }
2404
2405 auto resVector = cir::VectorType::get(builder.getBoolTy(), numElts);
2406
2407 cir::StructType resRecord =
2408 cir::StructType::get(&getMLIRContext(), {resVector, resVector},
2409 /*packed=*/false, /*padded=*/false,
2410 /*is_class=*/false);
2411
2412 mlir::Value call = builder.emitIntrinsicCallOp(
2413 getLoc(expr->getExprLoc()), intrinsicName, resRecord,
2414 mlir::ValueRange{ops[0], ops[1]});
2415 mlir::Value result =
2416 cir::ExtractMemberOp::create(builder, loc, resVector, call, 0);
2417 result = emitX86MaskedCompareResult(builder, result, numElts, nullptr, loc);
2418 Address addr = Address(
2419 ops[2], clang::CharUnits::fromQuantity(std::max(1U, numElts / 8)));
2420 builder.createStore(loc, result, addr);
2421
2422 result = cir::ExtractMemberOp::create(builder, loc, resVector, call, 1);
2423 result = emitX86MaskedCompareResult(builder, result, numElts, nullptr, loc);
2424 addr = Address(ops[3],
2425 clang::CharUnits::fromQuantity(std::max(1U, numElts / 8)));
2426 builder.createStore(loc, result, addr);
2427 return mlir::Value{};
2428 }
2429 case X86::BI__builtin_ia32_vpmultishiftqb128:
2430 case X86::BI__builtin_ia32_vpmultishiftqb256:
2431 case X86::BI__builtin_ia32_vpmultishiftqb512:
2432 case X86::BI__builtin_ia32_vpshufbitqmb128_mask:
2433 case X86::BI__builtin_ia32_vpshufbitqmb256_mask:
2434 case X86::BI__builtin_ia32_vpshufbitqmb512_mask:
2435 case X86::BI__builtin_ia32_cmpeqps:
2436 case X86::BI__builtin_ia32_cmpeqpd:
2437 return emitVectorFCmp(*this, *expr, ops, cir::CmpOpKind::eq,
2438 /*shouldInvert=*/false);
2439 case X86::BI__builtin_ia32_cmpltps:
2440 case X86::BI__builtin_ia32_cmpltpd:
2441 return emitVectorFCmp(*this, *expr, ops, cir::CmpOpKind::lt,
2442 /*shouldInvert=*/false);
2443 case X86::BI__builtin_ia32_cmpleps:
2444 case X86::BI__builtin_ia32_cmplepd:
2445 return emitVectorFCmp(*this, *expr, ops, cir::CmpOpKind::le,
2446 /*shouldInvert=*/false);
2447 case X86::BI__builtin_ia32_cmpunordps:
2448 case X86::BI__builtin_ia32_cmpunordpd:
2449 return emitVectorFCmp(*this, *expr, ops, cir::CmpOpKind::uno,
2450 /*shouldInvert=*/false);
2451 case X86::BI__builtin_ia32_cmpneqps:
2452 case X86::BI__builtin_ia32_cmpneqpd:
2453 return emitVectorFCmp(*this, *expr, ops, cir::CmpOpKind::ne,
2454 /*shouldInvert=*/false);
2455 case X86::BI__builtin_ia32_cmpnltps:
2456 case X86::BI__builtin_ia32_cmpnltpd:
2457 return emitVectorFCmp(*this, *expr, ops, cir::CmpOpKind::lt,
2458 /*shouldInvert=*/true);
2459 case X86::BI__builtin_ia32_cmpnleps:
2460 case X86::BI__builtin_ia32_cmpnlepd:
2461 return emitVectorFCmp(*this, *expr, ops, cir::CmpOpKind::le,
2462 /*shouldInvert=*/true);
2463 case X86::BI__builtin_ia32_cmpordps:
2464 case X86::BI__builtin_ia32_cmpordpd:
2465 return emitVectorFCmp(*this, *expr, ops, cir::CmpOpKind::uno,
2466 /*shouldInvert=*/true);
2467 case X86::BI__builtin_ia32_cmpph128_mask:
2468 case X86::BI__builtin_ia32_cmpph256_mask:
2469 case X86::BI__builtin_ia32_cmpph512_mask:
2470 case X86::BI__builtin_ia32_cmpps128_mask:
2471 case X86::BI__builtin_ia32_cmpps256_mask:
2472 case X86::BI__builtin_ia32_cmpps512_mask:
2473 case X86::BI__builtin_ia32_cmppd128_mask:
2474 case X86::BI__builtin_ia32_cmppd256_mask:
2475 case X86::BI__builtin_ia32_cmppd512_mask:
2476 case X86::BI__builtin_ia32_vcmpbf16512_mask:
2477 case X86::BI__builtin_ia32_vcmpbf16256_mask:
2478 case X86::BI__builtin_ia32_vcmpbf16128_mask:
2479 case X86::BI__builtin_ia32_cmpps:
2480 case X86::BI__builtin_ia32_cmpps256:
2481 case X86::BI__builtin_ia32_cmppd:
2482 case X86::BI__builtin_ia32_cmppd256:
2483 case X86::BI__builtin_ia32_cmpeqss:
2484 case X86::BI__builtin_ia32_cmpltss:
2485 case X86::BI__builtin_ia32_cmpless:
2486 case X86::BI__builtin_ia32_cmpunordss:
2487 case X86::BI__builtin_ia32_cmpneqss:
2488 case X86::BI__builtin_ia32_cmpnltss:
2489 case X86::BI__builtin_ia32_cmpnless:
2490 case X86::BI__builtin_ia32_cmpordss:
2491 case X86::BI__builtin_ia32_cmpeqsd:
2492 case X86::BI__builtin_ia32_cmpltsd:
2493 case X86::BI__builtin_ia32_cmplesd:
2494 case X86::BI__builtin_ia32_cmpunordsd:
2495 case X86::BI__builtin_ia32_cmpneqsd:
2496 case X86::BI__builtin_ia32_cmpnltsd:
2497 case X86::BI__builtin_ia32_cmpnlesd:
2498 case X86::BI__builtin_ia32_cmpordsd:
2499 cgm.errorNYI(expr->getSourceRange(),
2500 std::string("unimplemented X86 builtin call: ") +
2501 getContext().BuiltinInfo.getName(builtinID));
2502 return {};
2503 case X86::BI__builtin_ia32_vcvtph2ps_mask:
2504 case X86::BI__builtin_ia32_vcvtph2ps256_mask:
2505 case X86::BI__builtin_ia32_vcvtph2ps512_mask: {
2506 mlir::Location loc = getLoc(expr->getExprLoc());
2507 return emitX86CvtF16ToFloatExpr(builder, loc, ops,
2508 convertType(expr->getType()));
2509 }
2510 case X86::BI__builtin_ia32_cvtneps2bf16_128_mask: {
2511 mlir::Location loc = getLoc(expr->getExprLoc());
2512 cir::VectorType resTy = cast<cir::VectorType>(convertType(expr->getType()));
2513
2514 cir::VectorType inputTy = cast<cir::VectorType>(ops[0].getType());
2515 unsigned numElts = inputTy.getSize();
2516
2517 mlir::Value mask = getMaskVecValue(builder, loc, ops[2], numElts);
2518
2520 args.push_back(ops[0]);
2521 args.push_back(ops[1]);
2522 args.push_back(mask);
2523
2524 return builder.emitIntrinsicCallOp(
2525 loc, "x86.avx512bf16.mask.cvtneps2bf16.128", resTy, args);
2526 }
2527 case X86::BI__builtin_ia32_cvtneps2bf16_256_mask:
2528 case X86::BI__builtin_ia32_cvtneps2bf16_512_mask: {
2529 mlir::Location loc = getLoc(expr->getExprLoc());
2530 cir::VectorType resTy = cast<cir::VectorType>(convertType(expr->getType()));
2531 StringRef intrinsicName;
2532 if (builtinID == X86::BI__builtin_ia32_cvtneps2bf16_256_mask) {
2533 intrinsicName = "x86.avx512bf16.cvtneps2bf16.256";
2534 } else {
2535 assert(builtinID == X86::BI__builtin_ia32_cvtneps2bf16_512_mask);
2536 intrinsicName = "x86.avx512bf16.cvtneps2bf16.512";
2537 }
2538
2539 mlir::Value res = builder.emitIntrinsicCallOp(loc, intrinsicName, resTy,
2540 mlir::ValueRange{ops[0]});
2541
2542 return emitX86Select(builder, loc, ops[2], res, ops[1]);
2543 }
2544 case X86::BI__cpuid:
2545 case X86::BI__cpuidex: {
2546 mlir::Location loc = getLoc(expr->getExprLoc());
2547 mlir::Value subFuncId = builtinID == X86::BI__cpuidex
2548 ? ops[2]
2549 : builder.getConstInt(loc, sInt32Ty, 0);
2550 cir::CpuIdOp::create(builder, loc, /*cpuInfo=*/ops[0],
2551 /*functionId=*/ops[1], /*subFunctionId=*/subFuncId);
2552 return mlir::Value{};
2553 }
2554 case X86::BI__emul:
2555 case X86::BI__emulu:
2556 case X86::BI__mulh:
2557 case X86::BI__umulh:
2558 case X86::BI_mul128:
2559 case X86::BI_umul128: {
2560 cgm.errorNYI(expr->getSourceRange(),
2561 std::string("unimplemented X86 builtin call: ") +
2562 getContext().BuiltinInfo.getName(builtinID));
2563 return mlir::Value{};
2564 }
2565 case X86::BI__faststorefence: {
2566 cir::AtomicFenceOp::create(
2567 builder, getLoc(expr->getExprLoc()),
2568 cir::MemOrder::SequentiallyConsistent,
2569 cir::SyncScopeKindAttr::get(&getMLIRContext(),
2570 cir::SyncScopeKind::System));
2571 return mlir::Value{};
2572 }
2573 case X86::BI__shiftleft128:
2574 case X86::BI__shiftright128: {
2575 // Flip low/high ops and zero-extend amount to matching type.
2576 // shiftleft128(Low, High, Amt) -> fshl(High, Low, Amt)
2577 // shiftright128(Low, High, Amt) -> fshr(High, Low, Amt)
2578 std::swap(ops[0], ops[1]);
2579
2580 // Zero-extend shift amount to i64 if needed
2581 auto amtTy = mlir::cast<cir::IntType>(ops[2].getType());
2582 cir::IntType i64Ty = builder.getUInt64Ty();
2583
2584 if (amtTy != i64Ty)
2585 ops[2] = builder.createIntCast(ops[2], i64Ty);
2586
2587 const StringRef intrinsicName =
2588 (builtinID == X86::BI__shiftleft128) ? "fshl" : "fshr";
2589 return builder.emitIntrinsicCallOp(
2590 getLoc(expr->getExprLoc()), intrinsicName, i64Ty,
2591 mlir::ValueRange{ops[0], ops[1], ops[2]});
2592 }
2593 case X86::BI_ReadWriteBarrier:
2594 case X86::BI_ReadBarrier:
2595 case X86::BI_WriteBarrier: {
2596 cir::AtomicFenceOp::create(
2597 builder, getLoc(expr->getExprLoc()),
2598 cir::MemOrder::SequentiallyConsistent,
2599 cir::SyncScopeKindAttr::get(&getMLIRContext(),
2600 cir::SyncScopeKind::SingleThread));
2601 return mlir::Value{};
2602 }
2603 case X86::BI_AddressOfReturnAddress: {
2604 mlir::Location loc = getLoc(expr->getExprLoc());
2605 mlir::Value addr =
2606 cir::AddrOfReturnAddrOp::create(builder, loc, allocaInt8PtrTy);
2607 return builder.createCast(loc, cir::CastKind::bitcast, addr, voidPtrTy);
2608 }
2609 case X86::BI__stosb:
2610 case X86::BI__ud2:
2611 case X86::BI__int2c:
2612 case X86::BI__readfsbyte:
2613 case X86::BI__readfsword:
2614 case X86::BI__readfsdword:
2615 case X86::BI__readfsqword:
2616 case X86::BI__readgsbyte:
2617 case X86::BI__readgsword:
2618 case X86::BI__readgsdword:
2619 case X86::BI__readgsqword: {
2620 cgm.errorNYI(expr->getSourceRange(),
2621 std::string("unimplemented X86 builtin call: ") +
2622 getContext().BuiltinInfo.getName(builtinID));
2623 return mlir::Value{};
2624 }
2625 case X86::BI__builtin_ia32_encodekey128_u32: {
2626 return emitEncodeKey(&getMLIRContext(), builder, getLoc(expr->getExprLoc()),
2627 {ops[0], ops[1]}, ops[2], 6, "x86.encodekey128", 3);
2628 }
2629 case X86::BI__builtin_ia32_encodekey256_u32: {
2630
2631 return emitEncodeKey(&getMLIRContext(), builder, getLoc(expr->getExprLoc()),
2632 {ops[0], ops[1], ops[2]}, ops[3], 7,
2633 "x86.encodekey256", 4);
2634 }
2635
2636 case X86::BI__builtin_ia32_aesenc128kl_u8:
2637 case X86::BI__builtin_ia32_aesdec128kl_u8:
2638 case X86::BI__builtin_ia32_aesenc256kl_u8:
2639 case X86::BI__builtin_ia32_aesdec256kl_u8: {
2640 llvm::StringRef intrinsicName;
2641 switch (builtinID) {
2642 default:
2643 llvm_unreachable("Unexpected builtin");
2644 case X86::BI__builtin_ia32_aesenc128kl_u8:
2645 intrinsicName = "x86.aesenc128kl";
2646 break;
2647 case X86::BI__builtin_ia32_aesdec128kl_u8:
2648 intrinsicName = "x86.aesdec128kl";
2649 break;
2650 case X86::BI__builtin_ia32_aesenc256kl_u8:
2651 intrinsicName = "x86.aesenc256kl";
2652 break;
2653 case X86::BI__builtin_ia32_aesdec256kl_u8:
2654 intrinsicName = "x86.aesdec256kl";
2655 break;
2656 }
2657
2658 return emitX86Aes(builder, getLoc(expr->getExprLoc()), intrinsicName,
2659 convertType(expr->getType()), ops);
2660 }
2661 case X86::BI__builtin_ia32_aesencwide128kl_u8:
2662 case X86::BI__builtin_ia32_aesdecwide128kl_u8:
2663 case X86::BI__builtin_ia32_aesencwide256kl_u8:
2664 case X86::BI__builtin_ia32_aesdecwide256kl_u8: {
2665 llvm::StringRef intrinsicName;
2666 switch (builtinID) {
2667 default:
2668 llvm_unreachable("Unexpected builtin");
2669 case X86::BI__builtin_ia32_aesencwide128kl_u8:
2670 intrinsicName = "x86.aesencwide128kl";
2671 break;
2672 case X86::BI__builtin_ia32_aesdecwide128kl_u8:
2673 intrinsicName = "x86.aesdecwide128kl";
2674 break;
2675 case X86::BI__builtin_ia32_aesencwide256kl_u8:
2676 intrinsicName = "x86.aesencwide256kl";
2677 break;
2678 case X86::BI__builtin_ia32_aesdecwide256kl_u8:
2679 intrinsicName = "x86.aesdecwide256kl";
2680 break;
2681 }
2682
2683 return emitX86Aeswide(builder, getLoc(expr->getExprLoc()), intrinsicName,
2684 convertType(expr->getType()), ops);
2685 }
2686 case X86::BI__builtin_ia32_vfcmaddcph512_mask:
2687 case X86::BI__builtin_ia32_vfmaddcph512_mask:
2688 case X86::BI__builtin_ia32_vfcmaddcsh_round_mask:
2689 case X86::BI__builtin_ia32_vfmaddcsh_round_mask:
2690 case X86::BI__builtin_ia32_vfcmaddcsh_round_mask3:
2691 case X86::BI__builtin_ia32_vfmaddcsh_round_mask3:
2692 case X86::BI__builtin_ia32_prefetchi:
2693 cgm.errorNYI(expr->getSourceRange(),
2694 std::string("unimplemented X86 builtin call: ") +
2695 getContext().BuiltinInfo.getName(builtinID));
2696 return mlir::Value{};
2697 }
2698}
Defines enum values for all the target-independent builtin functions.
static mlir::Value emitX86MaskLogic(CIRGenBuilderTy &builder, mlir::Location loc, SmallVectorImpl< mlir::Value > &ops, bool invertLHS=false)
static mlir::Value emitX86vpcom(CIRGenBuilderTy &builder, mlir::Location loc, llvm::SmallVector< mlir::Value > ops, bool isSigned)
static std::optional< mlir::Value > emitX86ConvertToMask(CIRGenFunction &cgf, CIRGenBuilderTy &builder, mlir::Value in, mlir::Location loc)
static mlir::Value emitX86CompressExpand(CIRGenBuilderTy &builder, mlir::Location loc, mlir::Value source, mlir::Value mask, mlir::Value inputVector, const std::string &id)
static void computeFullLaneShuffleMask(CIRGenFunction &cgf, const mlir::Value vec, uint32_t imm, const bool isShufP, llvm::SmallVectorImpl< int64_t > &outIndices)
static mlir::Value emitX86VPerm2f128(CIRGenBuilderTy &builder, mlir::Location loc, llvm::SmallVector< mlir::Value > ops)
static std::optional< mlir::Value > emitX86SExtMask(CIRGenBuilderTy &builder, mlir::Value op, mlir::Type dstTy, mlir::Location loc)
static mlir::Value emitX86PackedByteShift(CIRGenBuilderTy &builder, unsigned builtinID, mlir::Location loc, llvm::ArrayRef< mlir::Value > ops, llvm::Boolean isLeftShift)
static std::optional< mlir::Value > emitX86MaskedCompare(CIRGenBuilderTy &builder, unsigned cc, bool isSigned, ArrayRef< mlir::Value > ops, mlir::Location loc)
static mlir::Value emitPrefetch(CIRGenFunction &cgf, unsigned builtinID, const CallExpr *e, const SmallVector< mlir::Value > &ops)
static mlir::Value getMaskZeroBitAsBool(CIRGenBuilderTy &builder, mlir::Location loc, mlir::Value mask)
static mlir::Value emitX86Aeswide(CIRGenBuilderTy &builder, mlir::Location loc, llvm::StringRef intrinsicName, mlir::Type retType, llvm::ArrayRef< mlir::Value > ops)
static mlir::Value emitX86MaskTest(CIRGenBuilderTy &builder, mlir::Location loc, const std::string &intrinsicName, SmallVectorImpl< mlir::Value > &ops)
static mlir::Value emitEncodeKey(mlir::MLIRContext *context, CIRGenBuilderTy &builder, const mlir::Location &location, mlir::ValueRange inputOperands, mlir::Value outputOperand, std::uint8_t vecOutputCount, const std::string &intrinsicName, std::uint8_t numResults)
static mlir::Value emitVecInsert(CIRGenBuilderTy &builder, mlir::Location loc, mlir::Value vec, mlir::Value value, mlir::Value indexOp)
static mlir::Value emitX86Fpclass(CIRGenBuilderTy &builder, mlir::Location loc, unsigned builtinID, SmallVectorImpl< mlir::Value > &ops)
static mlir::Value emitX86MaskedLoad(CIRGenBuilderTy &builder, ArrayRef< mlir::Value > ops, llvm::Align alignment, mlir::Location loc)
static mlir::Value emitX86MaskUnpack(CIRGenBuilderTy &builder, mlir::Location loc, const std::string &intrinsicName, SmallVectorImpl< mlir::Value > &ops)
static mlir::Value emitVectorFCmp(CIRGenFunction &cgf, const CallExpr &expr, llvm::SmallVector< mlir::Value > &ops, cir::CmpOpKind pred, bool shouldInvert)
static cir::VecShuffleOp emitPshufWord(CIRGenBuilderTy &builder, const mlir::Value vec, const mlir::Value immediate, const mlir::Location loc, const bool isLow)
static mlir::Value emitX86MaskedCompareResult(CIRGenBuilderTy &builder, mlir::Value cmp, unsigned numElts, mlir::Value maskIn, mlir::Location loc)
static mlir::Value emitX86Select(CIRGenBuilderTy &builder, mlir::Location loc, mlir::Value mask, mlir::Value op0, mlir::Value op1)
static mlir::Value emitX86Aes(CIRGenBuilderTy &builder, mlir::Location loc, llvm::StringRef intrinsicName, mlir::Type retType, llvm::ArrayRef< mlir::Value > ops)
static mlir::Value emitX86CvtF16ToFloatExpr(CIRGenBuilderTy &builder, mlir::Location loc, llvm::ArrayRef< mlir::Value > ops, mlir::Type dstTy)
static mlir::Value emitX86FunnelShift(CIRGenBuilderTy &builder, mlir::Location location, mlir::Value &op0, mlir::Value &op1, mlir::Value &amt, bool isRight)
static mlir::Value emitX86Muldq(CIRGenBuilderTy &builder, mlir::Location loc, bool isSigned, SmallVectorImpl< mlir::Value > &ops, unsigned opTypePrimitiveSizeInBits)
static mlir::Value getMaskVecValue(CIRGenBuilderTy &builder, mlir::Location loc, mlir::Value mask, unsigned numElems)
static mlir::Value emitX86MaskAddLogic(CIRGenBuilderTy &builder, mlir::Location loc, const std::string &intrinsicName, SmallVectorImpl< mlir::Value > &ops)
static mlir::Value emitX86CompressStore(CIRGenBuilderTy &builder, mlir::Location loc, ArrayRef< mlir::Value > ops)
static mlir::Value emitX86ScalarSelect(CIRGenBuilderTy &builder, mlir::Location loc, mlir::Value mask, mlir::Value op0, mlir::Value op1)
TokenType getType() const
Returns the token's type, e.g.
Enumerates target-specific builtins in their own namespaces within namespace clang.
mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ, const llvm::APInt &val)
mlir::Value createShift(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, bool isShiftLeft)
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
mlir::Value createCast(mlir::Location loc, cir::CastKind kind, mlir::Value src, mlir::Type newTy)
cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base, mlir::Value stride)
mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy)
mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createExtractElement(mlir::Location loc, mlir::Value vec, uint64_t idx)
cir::VecCmpOp createVecCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
mlir::Value createIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
mlir::Value createNot(mlir::Location loc, mlir::Value value)
mlir::Value createSelect(mlir::Location loc, mlir::Value condition, mlir::Value trueValue, mlir::Value falseValue)
mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value={})
Create a yield operation.
cir::BoolType getBoolTy()
llvm::TypeSize getTypeSizeInBits(mlir::Type ty) const
C++ view class that accepts both !cir.struct and !cir.union types.
Definition CIRTypes.h:103
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error, unsigned *IntegerConstantArgs=nullptr) const
Return the type for the specified builtin.
@ GE_None
No error.
mlir::Value getPointer() const
Definition Address.h:98
cir::ConstantOp getUInt64(uint64_t c, mlir::Location loc)
mlir::Value emitIntrinsicCallOp(mlir::Location loc, const llvm::StringRef str, const mlir::Type &resTy, Operands &&...op)
cir::IntType getSIntNTy(int n)
cir::ConstantOp getUInt32(uint32_t c, mlir::Location loc)
cir::VecShuffleOp createVecShuffle(mlir::Location loc, mlir::Value vec1, mlir::Value vec2, llvm::ArrayRef< mlir::Attribute > maskAttrs)
mlir::Value createMaskedLoad(mlir::Location loc, mlir::Type ty, mlir::Value ptr, llvm::Align alignment, mlir::Value mask, mlir::Value passThru)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, bool isNontemporal=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
cir::LoadOp createAlignedLoad(mlir::Location loc, mlir::Type ty, mlir::Value ptr, llvm::MaybeAlign align)
cir::ConstantOp getZero(mlir::Location loc, mlir::Type ty)
cir::StructType getAnonRecordTy(llvm::ArrayRef< mlir::Type > members, bool packed=false, bool padded=false)
Get a CIR anonymous struct type.
cir::ConstantOp getSInt32(int32_t c, mlir::Location loc)
cir::IntType getUIntNTy(int n)
mlir::Value getArrayElement(mlir::Location arrayLocBegin, mlir::Location arrayLocEnd, mlir::Value arrayPtr, mlir::Type eltTy, mlir::Value idx, bool shouldDecay)
Create a cir.ptr_stride operation to get access to an array element.
mlir::Type convertType(clang::QualType t)
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
static int64_t getZExtIntValueFromConstOp(mlir::Value val)
Get zero-extended integer from a mlir::Value that is an int constant or a constant op.
static int64_t getSExtIntValueFromConstOp(mlir::Value val)
Get integer from a mlir::Value that is an int constant or a constant op.
std::optional< mlir::Value > emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr)
CIRGenBuilderTy & getBuilder()
mlir::MLIRContext & getMLIRContext()
clang::ASTContext & getContext() const
Address createMemTemp(QualType t, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr, mlir::OpBuilder::InsertPoint ip={})
Create a temporary memory object of the given type, with appropriate alignmen and cast it to the defa...
mlir::Value emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned idx, const Expr *argExpr)
const cir::CIRDataLayout getDataLayout() const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2949
static CharUnits One()
One - Construct a CharUnits quantity of one.
Definition CharUnits.h:58
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
The JSON file list parser is used to communicate input to InstallAPI.
U cast(CodeGen::Address addr)
Definition Address.h:327
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 uint8_t
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
static bool msvcBuiltins()
static bool handleBuiltinICEArguments()
static bool emitConstrainedFPCall()
static bool fastMathFlags()
cir::PointerType allocaInt8PtrTy
void* in alloca address space
cir::PointerType voidPtrTy
void* in address space 0