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