29#include "llvm/ADT/APFloat.h"
30#include "llvm/ADT/DenseSet.h"
31#include "llvm/ADT/STLExtras.h"
32#include "llvm/ADT/TypeSwitch.h"
33#include "llvm/IR/DataLayout.h"
34#include "llvm/Support/Error.h"
43using mlir::LLVM::cconv::getMaxEnumValForCConv;
44using mlir::LLVM::linkage::getMaxEnumValForLinkage;
45using mlir::LLVM::tailcallkind::getMaxEnumValForTailCallKind;
47#include "mlir/Dialect/LLVMIR/LLVMOpsDialect.cpp.inc"
58 op, [&](StringRef name,
Attribute &attr) { attrs.
set(name, attr); });
68 for (StringAttr name : inherentAttrNames)
71 attrs.
set(name, *attr);
78 if (attr.
getName() ==
"fastmathFlags") {
98 << name <<
"' does not reference a valid LLVM function";
99 if (
func.isExternal())
100 return op->
emitOpError(
"'") << name <<
"' does not have a definition";
118 for (
const auto &en : llvm::enumerate(keywords)) {
126template <
typename Ty>
129#define REGISTER_ENUM_TYPE(Ty) \
131 struct EnumTraits<Ty> { \
132 static StringRef stringify(Ty value) { return stringify##Ty(value); } \
133 static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
147template <
typename EnumTy,
typename RetTy = EnumTy>
149 EnumTy defaultValue) {
151 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
152 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
156 return static_cast<RetTy
>(defaultValue);
157 return static_cast<RetTy
>(
index);
162 p << stringifyLinkage(val.getLinkage());
166 val = LinkageAttr::get(
174 uint64_t alignment = 1) {
180 if (alignment == 1) {
187 builder.
getNamedAttr(LLVMDialect::getAlignAttrName(), alignmentAttr);
197 int pos = isExpandLoad ? 0 : 1;
199 {alignDictAttr, emptyDictAttr, emptyDictAttr})
201 {emptyDictAttr, alignDictAttr, emptyDictAttr});
213 if (!operands.empty()) {
216 llvm::interleaveComma(operandTypes, p);
225 std::optional<ArrayAttr> opBundleTags) {
226 if (opBundleOperands.empty())
228 assert(opBundleTags &&
"expect operand bundle tags");
231 llvm::interleaveComma(
232 llvm::zip(opBundleOperands, opBundleOperandTypes, *opBundleTags), p,
234 auto bundleTag = cast<StringAttr>(std::get<2>(bundle)).getValue();
252 return p.
emitError(currentParserLoc,
"expect operand bundle tag");
263 opBundleOperands.push_back(std::move(operands));
264 opBundleOperandTypes.push_back(std::move(types));
265 opBundleTags.push_back(StringAttr::get(p.
getContext(), tag));
282 auto bundleParser = [&] {
292 opBundleTags = ArrayAttr::get(p.
getContext(), opBundleTagAttrs);
301template <
typename PredicateAttr,
typename Predicate>
304 function_ref<std::optional<Predicate>(StringRef)> symbolize) {
305 std::string spelling;
309 std::optional<Predicate> value = symbolize(spelling);
313 <<
"' is an incorrect value of the 'predicate' attribute";
314 predicate = PredicateAttr::get(parser.
getContext(), *value);
319 ICmpPredicateAttr &predicate) {
322 [](StringRef spelling) {
return symbolizeICmpPredicate(spelling); });
326 FCmpPredicateAttr &predicate) {
329 [](StringRef spelling) {
return symbolizeFCmpPredicate(spelling); });
333 ICmpPredicateAttr predicate) {
334 printer <<
'"' << stringifyICmpPredicate(predicate.getValue()) <<
'"';
338 FCmpPredicateAttr predicate) {
339 printer <<
'"' << stringifyFCmpPredicate(predicate.getValue()) <<
'"';
345 ShapedType shapedType = dyn_cast<ShapedType>(type);
352 if (getPredicate() != ICmpPredicate::eq &&
353 getPredicate() != ICmpPredicate::ne)
357 if (getLhs() == getRhs())
359 getPredicate() == ICmpPredicate::eq);
362 if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
364 getPredicate() == ICmpPredicate::ne);
367 if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
368 Value lhs = getLhs();
369 Value rhs = getRhs();
370 getLhsMutable().assign(rhs);
371 getRhsMutable().assign(lhs);
389 p <<
' ' << getArraySize() <<
" x " << getElemType();
390 NamedAttrList attrs((*this)->getDiscardableAttrDictionary().getValue());
391 if (getAlignment() && *getAlignment() != 0)
392 attrs.append(getAlignmentAttrName(), getAlignmentAttr());
394 p <<
" : " << funcTy;
402 SMLoc trailingTypeLoc;
414 std::optional<NamedAttribute> alignmentAttr =
415 result.attributes.getNamed(
"alignment");
416 if (alignmentAttr.has_value()) {
417 auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
420 "expected integer alignment");
421 if (alignmentInt.getValue().isZero())
422 result.attributes.erase(
"alignment");
426 auto funcType = llvm::dyn_cast<FunctionType>(type);
427 if (!funcType || funcType.getNumInputs() != 1 ||
428 funcType.getNumResults() != 1)
431 "expected trailing function type with one argument and one result");
436 Type resultType = funcType.getResult(0);
437 if (
auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
440 result.addTypes({funcType.getResult(0)});
444LogicalResult AllocaOp::verify() {
446 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
447 targetExtType && !targetExtType.supportsMemOps())
449 <<
"this target extension type cannot be used in alloca";
454LogicalResult AllocaOp::canonicalize(AllocaOp op,
PatternRewriter &rewriter) {
458 numElements.isOne() || numElements.getActiveBits() > 64)
462 LLVMArrayType::get(op.getElemType(), numElements.getZExtValue());
463 Value one = ConstantOp::create(rewriter, op.getLoc(), rewriter.
getI32Type(),
466 AllocaOp::create(rewriter, op.getLoc(), op.getType(), one,
467 op.getAlignmentAttr(), arrayType, op.getInalloca());
468 newAlloca->setDiscardableAttrs(op->getDiscardableAttrDictionary());
478 assert(
index == 0 &&
"invalid successor index");
487 assert(
index < getNumSuccessors() &&
"invalid successor index");
489 : getFalseDestOperandsMutable());
495 std::optional<std::pair<uint32_t, uint32_t>> weights) {
500 static_cast<int32_t
>(weights->second)});
502 build(builder,
result, condition, trueOperands, falseOperands, weightsAttr,
503 {}, trueDest, falseDest);
517 if (!branchWeights.empty())
520 build(builder,
result, value, defaultOperands, caseOperands, caseValues,
521 weightsAttr, defaultDestination, caseDestinations);
530 if (!caseValues.empty()) {
531 ShapedType caseValueType = VectorType::get(
536 build(builder,
result, value, defaultDestination, defaultOperands,
537 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
546 if (!caseValues.empty()) {
547 ShapedType caseValueType = VectorType::get(
552 build(builder,
result, value, defaultDestination, defaultOperands,
553 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
569 auto parseCase = [&]() {
573 values.push_back(APInt(bitWidth, value,
true));
585 caseDestinations.push_back(destination);
586 caseOperands.emplace_back(operands);
587 caseOperandTypes.emplace_back(operandTypes);
593 ShapedType caseValueType =
594 VectorType::get(
static_cast<int64_t>(values.size()), flagType);
613 llvm::zip(caseValues, caseDestinations),
628LogicalResult SwitchOp::verify() {
629 if ((!getCaseValues() && !getCaseDestinations().empty()) ||
631 getCaseValues()->size() !=
632 static_cast<int64_t>(getCaseDestinations().size())))
633 return emitOpError(
"expects number of case values to match number of "
634 "case destinations");
635 if (getCaseValues() &&
637 return emitError(
"expects case value type to match condition value type");
642 assert(
index < getNumSuccessors() &&
"invalid successor index");
644 : getCaseOperandsMutable(
index - 1));
653 getDynamicIndices());
658 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
659 return vectorType.getElementType();
676 bool requiresConst = !rawConstantIndices.empty() &&
677 isa_and_nonnull<LLVMStructType>(currType);
678 if (
Value val = llvm::dyn_cast_if_present<Value>(iter)) {
682 rawConstantIndices.push_back(intC.getSExtValue());
684 rawConstantIndices.push_back(GEPOp::kDynamicIndex);
685 dynamicIndices.push_back(val);
688 rawConstantIndices.push_back(cast<GEPConstantIndex>(iter));
693 if (rawConstantIndices.size() == 1 || !currType)
697 .Case<VectorType, LLVMArrayType>([](
auto containerType) {
698 return containerType.getElementType();
700 .Case([&](LLVMStructType structType) ->
Type {
701 int64_t memberIndex = rawConstantIndices.back();
702 if (memberIndex >= 0 &&
static_cast<size_t>(memberIndex) <
703 structType.getBody().size())
704 return structType.getBody()[memberIndex];
713 GEPNoWrapFlags noWrapFlags, ConstantRangeAttr inrange,
719 result.addTypes(resultType);
720 result.addAttributes(attributes);
721 result.getOrAddProperties<Properties>().rawConstantIndices =
723 result.getOrAddProperties<Properties>().noWrapFlags = noWrapFlags;
724 result.getOrAddProperties<Properties>().elem_type =
725 TypeAttr::get(elementType);
726 result.getOrAddProperties<Properties>().inrange = inrange;
727 result.addOperands(basePtr);
728 result.addOperands(dynamicIndices);
733 GEPNoWrapFlags noWrapFlags, ConstantRangeAttr inrange,
735 build(builder,
result, resultType, elementType, basePtr,
745 auto idxParser = [&]() -> ParseResult {
746 int32_t constantIndex;
750 if (failed(parsedInteger.
value()))
752 constantIndices.push_back(constantIndex);
756 constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
770 llvm::interleaveComma(
773 if (
Value val = llvm::dyn_cast_if_present<Value>(cst))
776 printer << cast<IntegerAttr>(cst).getInt();
786 if (indexPos >=
indices.size())
791 .Case([&](LLVMStructType structType) -> LogicalResult {
792 auto attr = dyn_cast<IntegerAttr>(
indices[indexPos]);
794 return emitOpError() <<
"expected index " << indexPos
795 <<
" indexing a struct to be constant";
797 int32_t gepIndex = attr.getInt();
800 static_cast<size_t>(gepIndex) >= elementTypes.size())
801 return emitOpError() <<
"index " << indexPos
802 <<
" indexing a struct is out of bounds";
809 .Case<VectorType, LLVMArrayType>(
810 [&](
auto containerType) -> LogicalResult {
812 indexPos + 1,
indices, emitOpError);
814 .Default([&](
auto otherType) -> LogicalResult {
816 <<
"type " << otherType <<
" cannot be indexed (index #"
828LogicalResult LLVM::GEPOp::verify() {
829 if (
static_cast<size_t>(
830 llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
831 getDynamicIndices().size())
832 return emitOpError(
"expected as many dynamic indices as specified in '")
833 << getRawConstantIndicesAttrName().getValue() <<
"'";
835 if (getNoWrapFlags() == GEPNoWrapFlags::inboundsFlag)
836 return emitOpError(
"'inbounds_flag' cannot be used directly.");
843 if (
auto inrange = getInrangeAttr()) {
847 std::optional<uint64_t> indexWidth =
849 assert(indexWidth &&
"pointers always return an index bitwidth");
850 if (inrange.getLower().getBitWidth() != *indexWidth)
851 return emitOpError(
"'inrange' bitwidth ")
852 << inrange.getLower().getBitWidth()
853 <<
" must match the pointer index bitwidth (" << *indexWidth
854 <<
") specified in the datalayout";
855 if (inrange.getLower().sge(inrange.getUpper()))
856 return emitOpError(
"expected 'inrange' end to be larger than start");
860 [&] {
return emitOpError(); });
867void LoadOp::getEffects(
876 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
877 getOrdering() != AtomicOrdering::unordered)) {
888 if (!isa<IntegerType, LLVMPointerType>(type))
893 if (bitWidth.isScalable())
896 return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
900template <
typename OpTy>
904 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
907 return memOp.emitOpError(
"unsupported type ")
908 << valueType <<
" for atomic access";
909 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
910 return memOp.emitOpError(
"unsupported ordering '")
911 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
912 if (!memOp.getAlignment())
913 return memOp.emitOpError(
"expected alignment for atomic access");
916 if (memOp.getSyncscope())
917 return memOp.emitOpError(
918 "expected syncscope to be null for non-atomic access");
922LogicalResult LoadOp::verify() {
923 Type valueType = getResult().getType();
925 {AtomicOrdering::release, AtomicOrdering::acq_rel});
929 Value addr,
unsigned alignment,
bool isVolatile,
930 bool isNonTemporal,
bool isInvariant,
bool isInvariantGroup,
931 AtomicOrdering ordering, StringRef syncscope) {
932 build(builder, state, type, addr,
934 isNonTemporal, isInvariant, isInvariantGroup, ordering,
935 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
946void StoreOp::getEffects(
955 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
956 getOrdering() != AtomicOrdering::unordered)) {
962LogicalResult StoreOp::verify() {
963 Type valueType = getValue().getType();
965 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
969 Value addr,
unsigned alignment,
bool isVolatile,
970 bool isNonTemporal,
bool isInvariantGroup,
971 AtomicOrdering ordering, StringRef syncscope) {
972 build(builder, state, value, addr,
974 isNonTemporal, isInvariantGroup, ordering,
975 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
977 nullptr,
nullptr,
nullptr);
987 Type resultType = calleeType.getReturnType();
988 if (!isa<LLVM::LLVMVoidType>(resultType))
989 results.push_back(resultType);
995 return calleeType.isVarArg() ? TypeAttr::get(calleeType) :
nullptr;
1002 if (results.empty())
1003 resultType = LLVMVoidType::get(context);
1005 resultType = results.front();
1006 return LLVMFunctionType::get(resultType, llvm::to_vector(args.
getTypes()),
1012 build(builder, state, results, builder.
getStringAttr(callee), args);
1017 build(builder, state, results, SymbolRefAttr::get(callee), args);
1022 assert(callee &&
"expected non-null callee in direct call builder");
1023 build(builder, state, results,
1024 nullptr, callee, args,
nullptr,
1027 nullptr,
nullptr,
nullptr,
1028 nullptr,
nullptr,
nullptr,
1032 nullptr,
nullptr,
nullptr,
1047 LLVMFunctionType calleeType, StringRef callee,
1049 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
1053 LLVMFunctionType calleeType, StringAttr callee,
1055 build(builder, state, calleeType, SymbolRefAttr::get(callee), args);
1073 nullptr,
nullptr,
nullptr,
1082 nullptr,
nullptr,
nullptr,
1088 LLVMFunctionType calleeType,
ValueRange args) {
1093 nullptr,
nullptr,
nullptr,
1094 nullptr,
nullptr,
nullptr,
1100 nullptr,
nullptr,
nullptr,
1116 auto calleeType =
func.getFunctionType();
1120 nullptr,
nullptr,
nullptr,
1121 nullptr,
nullptr,
nullptr,
1127 nullptr,
nullptr,
nullptr,
1146 return getOperand(0);
1152 auto symRef = cast<SymbolRefAttr>(callee);
1153 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1156 return setOperand(0, cast<Value>(callee));
1161template <
typename OpTy>
1164 if (callOp.getCallee().has_value())
1171template <
typename OpTy>
1173 return callOp.getCalleeOperands().drop_front(
1185template <
typename OpTy>
1188 if (std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType())
1189 return operands.take_front(varCalleeType->getNumParams());
1207template <
typename OpTy>
1209 if (callee.isExternal())
1211 auto parentFunc = callOp->template getParentOfType<FunctionOpInterface>();
1215 auto hasSubprogram = [](
Operation *op) {
1220 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1222 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1224 return callOp.emitError()
1225 <<
"inlinable function call in a function with a DISubprogram "
1226 "location must have a debug location";
1232template <
typename OpTy>
1235 if (!callOp.getCallee().has_value() && callOp.getCalleeOperands().empty())
1236 return callOp.emitOpError(
1237 "must have either a `callee` attribute or at least an operand");
1239 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1244 if (!varCalleeType->isVarArg())
1245 return callOp.emitOpError(
1246 "expected var_callee_type to be a variadic function type");
1254 if (varCalleeType->getNumParams() > passedOperands.size())
1255 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1256 << passedOperands.size() <<
" parameters";
1259 for (
auto [paramType, operand] :
1260 llvm::zip(varCalleeType->getParams(), passedOperands))
1261 if (paramType != operand.getType())
1262 return callOp.emitOpError()
1263 <<
"var_callee_type parameter type mismatch: " << paramType
1264 <<
" != " << operand.getType();
1267 if (!callOp.getNumResults()) {
1268 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1269 return callOp.emitOpError(
"expected var_callee_type to return void");
1271 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1272 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1273 << varCalleeType->getReturnType()
1274 <<
" != " << callOp.getResult().getType();
1279template <
typename OpType>
1282 std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1284 auto isStringAttr = [](
Attribute tagAttr) {
1285 return isa<StringAttr>(tagAttr);
1287 if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1288 return op.emitError(
"operand bundle tag must be a StringAttr");
1290 size_t numOpBundles = opBundleOperands.size();
1291 size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1292 if (numOpBundles != numOpBundleTags)
1293 return op.emitError(
"expected ")
1294 << numOpBundles <<
" operand bundle tags, but actually got "
1302template <
typename OpTy>
1317 llvm::dyn_cast<LLVMPointerType>(callOp.getOperand(0).getType());
1319 return callOp.emitOpError(
"indirect call expects a pointer as callee: ")
1320 << callOp.getOperand(0).getType();
1328 return callOp.emitOpError()
1330 <<
"' does not reference a symbol in the current scope";
1331 if (
auto fn = dyn_cast<LLVMFuncOp>(callee)) {
1334 fnType = fn.getFunctionType();
1335 }
else if (
auto ifunc = dyn_cast<IFuncOp>(callee)) {
1336 fnType = ifunc.getIFuncType();
1337 }
else if (isa<AliasOp>(callee)) {
1341 fnType = callOp.getCalleeFunctionType();
1343 return callOp.emitOpError()
1345 <<
"' does not reference a valid LLVM function, IFunc, or alias";
1349 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1351 return callOp.emitOpError(
"callee does not have a functional type: ")
1354 if (funcType.isVarArg() && !callOp.getVarCalleeType())
1355 return callOp.emitOpError()
1356 <<
"missing var_callee_type attribute for vararg call";
1360 if (callOp.getNumResults() == 0 &&
1361 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1362 return callOp.emitOpError() <<
"expected function call to produce a value";
1364 if (callOp.getNumResults() != 0 &&
1365 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1366 return callOp.emitOpError()
1367 <<
"calling function with void result must not produce values";
1369 if (callOp.getNumResults() > 1)
1370 return callOp.emitOpError()
1371 <<
"expected LLVM function call to produce 0 or 1 result";
1373 if (callOp.getNumResults() &&
1374 callOp.getResult().getType() != funcType.getReturnType())
1375 return callOp.emitOpError()
1376 <<
"result type mismatch: " << callOp.getResult().getType()
1377 <<
" != " << funcType.getReturnType();
1383 if (!llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1384 calleeResultTypes.push_back(funcType.getReturnType());
1386 callOp, funcType.getParams(), calleeResultTypes);
1394 auto callee = getCallee();
1395 bool isDirect = callee.has_value();
1400 if (getCConv() != LLVM::CConv::C)
1401 p << stringifyCConv(getCConv()) <<
' ';
1403 if (getTailCallKind() != LLVM::TailCallKind::None)
1404 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1413 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1414 p <<
'(' << args <<
')';
1417 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1418 p <<
" vararg(" << *varCalleeType <<
")";
1420 if (!getOpBundleOperands().empty()) {
1423 getOpBundleOperands().getTypes(), getOpBundleTags());
1427 {getCalleeAttrName(), getTailCallKindAttrName(),
1428 getVarCalleeTypeAttrName(), getCConvAttrName(),
1429 getOperandSegmentSizesAttrName(),
1430 getOpBundleSizesAttrName(),
1431 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1432 getResAttrsAttrName()});
1436 p << getOperand(0).getType() <<
", ";
1440 p, args.getTypes(), getArgAttrsAttr(),
1441 false, getResultTypes(), getResAttrsAttr());
1456 types.emplace_back();
1461 trailingTypesLoc,
"expected indirect call to have 2 trailing types");
1466 resTypes, resultAttrs)) {
1468 return parser.
emitError(trailingTypesLoc,
1469 "expected direct call to have 1 trailing types");
1470 return parser.
emitError(trailingTypesLoc,
1471 "expected trailing function type");
1474 if (resTypes.size() > 1)
1475 return parser.
emitError(trailingTypesLoc,
1476 "expected function with 0 or 1 result");
1477 if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
1478 return parser.
emitError(trailingTypesLoc,
1479 "expected a non-void result type");
1485 llvm::append_range(types, argTypes);
1489 if (!resTypes.empty())
1490 result.addTypes(resTypes);
1503 if (failed(*parseResult))
1504 return *parseResult;
1505 operands.push_back(funcPtrOperand);
1514 StringAttr opBundleSizesAttrName) {
1515 unsigned opBundleIndex = 0;
1516 for (
const auto &[operands, types] :
1517 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1518 if (operands.size() != types.size())
1519 return parser.
emitError(loc,
"expected ")
1521 <<
" types for operand bundle operands for operand bundle #"
1522 << opBundleIndex <<
", but actually got " << types.size();
1528 opBundleSizes.reserve(opBundleOperands.size());
1529 for (
const auto &operands : opBundleOperands)
1530 opBundleSizes.push_back(operands.size());
1533 opBundleSizesAttrName,
1545 SymbolRefAttr funcAttr;
1546 TypeAttr varCalleeType;
1554 getCConvAttrName(
result.name),
1559 getTailCallKindAttrName(
result.name),
1562 parser, LLVM::TailCallKind::None)));
1567 bool isDirect = operands.empty();
1580 StringAttr varCalleeTypeAttrName =
1581 CallOp::getVarCalleeTypeAttrName(
result.name);
1593 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1596 if (opBundleTags && !opBundleTags.empty())
1597 result.addAttribute(CallOp::getOpBundleTagsAttrName(
result.name).getValue(),
1607 argAttrs, resultAttrs))
1611 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1613 opBundleOperandTypes,
1614 getOpBundleSizesAttrName(
result.name)))
1617 int32_t numOpBundleOperands = 0;
1618 for (
const auto &operands : opBundleOperands)
1619 numOpBundleOperands += operands.size();
1622 CallOp::getOperandSegmentSizeAttr(),
1624 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
1628LLVMFunctionType CallOp::getCalleeFunctionType() {
1629 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1630 return *varCalleeType;
1641 auto calleeType =
func.getFunctionType();
1644 nullptr,
nullptr, normalOps, unwindOps,
1645 nullptr,
nullptr,
nullptr,
1646 nullptr, {}, {}, normal, unwind);
1653 build(builder, state, tys,
1654 nullptr, callee, ops,
nullptr,
1655 nullptr, normalOps, unwindOps,
nullptr,
nullptr,
1657 nullptr, {}, {}, normal, unwind);
1666 nullptr,
nullptr, normalOps, unwindOps,
1667 nullptr,
nullptr,
nullptr,
1668 nullptr, {}, {}, normal, unwind);
1672 assert(
index < getNumSuccessors() &&
"invalid successor index");
1674 : getUnwindDestOperandsMutable());
1682 return getOperand(0);
1688 auto symRef = cast<SymbolRefAttr>(callee);
1689 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1692 return setOperand(0, cast<Value>(callee));
1710LogicalResult InvokeOp::verify() {
1711 Block *unwindDest = getUnwindDest();
1712 if (unwindDest->
empty())
1713 return emitError(
"must have at least one operation in unwind destination");
1716 if (!isa<LandingpadOp>(unwindDest->
front()))
1717 return emitError(
"first operation in unwind destination should be a "
1718 "llvm.landingpad operation");
1727 auto callee = getCallee();
1728 bool isDirect = callee.has_value();
1733 if (getCConv() != LLVM::CConv::C)
1734 p << stringifyCConv(getCConv()) <<
' ';
1742 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1749 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1750 p <<
" vararg(" << *varCalleeType <<
")";
1752 if (!getOpBundleOperands().empty()) {
1755 getOpBundleOperands().getTypes(), getOpBundleTags());
1759 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1760 getCConvAttrName(), getVarCalleeTypeAttrName(),
1761 getOpBundleSizesAttrName(),
1762 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1763 getResAttrsAttrName()});
1767 p << getOperand(0).getType() <<
", ";
1769 p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
1771 false, getResultTypes(), getResAttrsAttr());
1784 SymbolRefAttr funcAttr;
1785 TypeAttr varCalleeType;
1789 Block *normalDest, *unwindDest;
1795 getCConvAttrName(
result.name),
1802 bool isDirect = operands.empty();
1818 StringAttr varCalleeTypeAttrName =
1819 InvokeOp::getVarCalleeTypeAttrName(
result.name);
1831 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1834 if (opBundleTags && !opBundleTags.empty())
1836 InvokeOp::getOpBundleTagsAttrName(
result.name).getValue(),
1846 argAttrs, resultAttrs))
1850 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1852 result.addSuccessors({normalDest, unwindDest});
1853 result.addOperands(normalOperands);
1854 result.addOperands(unwindOperands);
1857 opBundleOperandTypes,
1858 getOpBundleSizesAttrName(
result.name)))
1861 int32_t numOpBundleOperands = 0;
1862 for (
const auto &operands : opBundleOperands)
1863 numOpBundleOperands += operands.size();
1866 InvokeOp::getOperandSegmentSizeAttr(),
1868 static_cast<int32_t>(normalOperands.size()),
1869 static_cast<int32_t>(unwindOperands.size()),
1870 numOpBundleOperands}));
1874LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1875 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1876 return *varCalleeType;
1884LogicalResult LandingpadOp::verify() {
1886 if (LLVMFuncOp
func = (*this)->getParentOfType<LLVMFuncOp>()) {
1887 if (!
func.getPersonality())
1889 "llvm.landingpad needs to be in a function with a personality");
1895 if (!getCleanup() && getOperands().empty())
1896 return emitError(
"landingpad instruction expects at least one clause or "
1897 "cleanup attribute");
1900 value = getOperand(idx);
1901 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1908 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1911 <<
"global addresses expected as operand to "
1912 "bitcast used in clauses for landingpad";
1920 << idx <<
" is not a known constant - null, addressof, bitcast";
1927 p << (getCleanup() ?
" cleanup " :
" ");
1930 for (
auto value : getOperands()) {
1933 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1934 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1981 Type llvmType = containerType;
1983 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1991 for (
int64_t idx : position) {
1992 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1993 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1994 emitError(
"position out of bounds: ") << idx;
1997 llvmType = arrayType.getElementType();
1998 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
2000 static_cast<unsigned>(idx) >= structType.getBody().size()) {
2001 emitError(
"position out of bounds: ") << idx;
2004 llvmType = structType.getBody()[idx];
2006 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
2017 for (
int64_t idx : position) {
2018 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
2019 llvmType = structType.getBody()[idx];
2021 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
2033 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
2034 ShapedType shapedType = elementsAttr.getShapedType();
2035 if (!shapedType.hasRank() || shapedType.getRank() != 1)
2037 if (
index <
static_cast<size_t>(elementsAttr.getNumElements()))
2041 if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
2042 if (
index < arrayAttr.getValue().size())
2043 return arrayAttr[
index];
2046 if (isa<ZeroAttr, UndefAttr, PoisonAttr>(attr))
2051OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
2052 if (
auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
2054 newPos.append(getPosition().begin(), getPosition().end());
2055 setPosition(newPos);
2056 getContainerMutable().set(extractValueOp.getContainer());
2062 for (
int64_t pos : getPosition()) {
2067 return containerAttr;
2070 Value container = getContainer();
2072 while (
auto insertValueOp = container.
getDefiningOp<InsertValueOp>()) {
2074 auto extractPosSize = extractPos.size();
2075 auto insertPosSize = insertPos.size();
2078 if (extractPos == insertPos)
2079 return insertValueOp.getValue();
2093 if (extractPosSize > insertPosSize &&
2094 extractPos.take_front(insertPosSize) == insertPos) {
2095 container = insertValueOp.getValue();
2096 extractPos = extractPos.drop_front(insertPosSize);
2112 if (insertPosSize > extractPosSize &&
2113 extractPos == insertPos.take_front(extractPosSize))
2118 container = insertValueOp.getContainer();
2124 if (container == getContainer())
2126 setPosition(extractPos);
2127 getContainerMutable().assign(container);
2131LogicalResult ExtractValueOp::verify() {
2132 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
2138 if (getRes().
getType() != valueType)
2139 return emitOpError() <<
"Type mismatch: extracting from "
2140 << getContainer().getType() <<
" should produce "
2141 << valueType <<
" but this op returns "
2142 << getRes().getType();
2148 build(builder, state,
2187 LogicalResult matchAndRewrite(InsertValueOp insertOp,
2188 PatternRewriter &rewriter)
const override {
2189 bool changed =
false;
2195 auto insertBaseIdx = insertOp.getPosition()[0];
2196 for (
auto &use : insertOp->getUses()) {
2197 if (
auto extractOp = dyn_cast<ExtractValueOp>(use.getOwner())) {
2198 auto baseIdx = extractOp.getPosition()[0];
2201 if (baseIdx == insertBaseIdx)
2203 posToExtractOps[baseIdx].push_back(extractOp);
2208 Value nextContainer = insertOp.getContainer();
2209 while (!posToExtractOps.empty()) {
2211 dyn_cast_or_null<InsertValueOp>(nextContainer.
getDefiningOp());
2214 nextContainer = curInsert.getContainer();
2217 auto curInsertBaseIdx = curInsert.getPosition()[0];
2218 auto it = posToExtractOps.find(curInsertBaseIdx);
2219 if (it == posToExtractOps.end())
2223 for (
auto &extractOp : it->second) {
2225 extractOp.getContainerMutable().assign(curInsert);
2230 assert(!it->second.empty());
2232 posToExtractOps.erase(it);
2236 for (
auto &[baseIdx, extracts] : posToExtractOps) {
2237 for (
auto &extractOp : extracts) {
2239 extractOp.getContainerMutable().assign(nextContainer);
2242 assert(!extracts.empty() &&
"Empty list in map");
2252 patterns.
add<ResolveExtractValueSource>(context);
2260 [&](StringRef msg) {
2272LogicalResult InsertValueOp::verify() {
2273 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
2279 if (getValue().
getType() != valueType)
2280 return emitOpError() <<
"Type mismatch: cannot insert "
2281 << getValue().getType() <<
" into "
2282 << getContainer().getType();
2291LogicalResult ReturnOp::verify() {
2292 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2296 Type expectedType = parent.getFunctionType().getReturnType();
2297 if (llvm::isa<LLVMVoidType>(expectedType)) {
2301 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2305 if (llvm::isa<LLVMVoidType>(expectedType))
2308 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2311 if (expectedType != getArg().
getType()) {
2313 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2324 return dyn_cast_or_null<GlobalOp>(
2329 return dyn_cast_or_null<LLVMFuncOp>(
2334 return dyn_cast_or_null<AliasOp>(
2339 return dyn_cast_or_null<IFuncOp>(
2348 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2349 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2350 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2351 auto ifunc = dyn_cast_or_null<IFuncOp>(symbol);
2353 if (!global && !function && !alias && !ifunc)
2354 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2355 "'llvm.mlir.alias' or 'llvm.func' or 'llvm.mlir.ifunc'");
2357 LLVMPointerType type =
getType();
2358 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2359 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2360 return emitOpError(
"pointer address space must match address space of the "
2361 "referenced global or alias");
2368 return getGlobalNameAttr();
2389 getFunctionNameAttr());
2390 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2391 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2393 if (!function && !alias)
2395 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2398 if (alias.getInitializer()
2399 .walk([&](AddressOfOp addrOp) {
2400 if (addrOp.getGlobal(symbolTable))
2401 return WalkResult::interrupt();
2402 return WalkResult::advance();
2405 return emitOpError(
"must reference an alias to a function");
2408 if ((function && function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2409 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2411 "target function with 'extern_weak' linkage not allowed");
2419 return DSOLocalEquivalentAttr::get(
getContext(), getFunctionNameAttr());
2427 StringRef symName) {
2430 Region *body =
result.addRegion();
2434LogicalResult ComdatOp::verifyRegions() {
2435 Region &body = getBody();
2436 for (Operation &op : body.
getOps())
2437 if (!isa<ComdatSelectorOp>(op))
2438 return op.emitError(
2439 "only comdat selector symbols can appear in a comdat region");
2449 bool isConstant, Linkage linkage, StringRef name,
2450 Attribute value, uint64_t alignment,
unsigned addrSpace,
2451 bool dsoLocal, ThreadLocalMode threadModel,
2454 result.getOrAddProperties<Properties>().sym_name =
2456 result.addAttribute(getGlobalTypeAttrName(
result.name), TypeAttr::get(type));
2458 getTlsModeAttrName(
result.name),
2459 ThreadLocalModeAttr::get(builder.
getContext(), threadModel));
2464 result.addAttribute(getValueAttrName(
result.name), value);
2469 result.addAttribute(getComdatAttrName(
result.name), comdat);
2479 LinkageAttr::get(builder.
getContext(), linkage));
2483 result.attributes.append(attrs.begin(), attrs.end());
2485 if (!dbgExprs.empty())
2487 ArrayAttr::get(builder.
getContext(), dbgExprs));
2492template <
typename OpType>
2494 p <<
' ' << stringifyLinkage(op.getLinkage()) <<
' ';
2495 StringRef visibility = stringifyVisibility(op.getVisibility_());
2496 if (!visibility.empty())
2497 p << visibility <<
' ';
2499 if (ThreadLocalMode mode = op.getTlsMode();
2500 mode != ThreadLocalMode::NotThreadLocal) {
2501 p <<
"thread_local";
2502 if (mode != ThreadLocalMode::GeneralDynamic)
2503 p <<
'(' << mode <<
')';
2507 if (
auto unnamedAddr = op.getUnnamedAddr()) {
2508 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2520 if (
auto value = getValueOrNull())
2523 if (
auto comdat = getComdat())
2524 p <<
" comdat(" << *comdat <<
')';
2531 *
this, {getDsoLocalAttrName(), getExternallyInitializedAttrName(),
2532 getAlignmentAttrName(), getAddrSpaceAttrName(),
2533 getSectionAttrName(), getAssociatedAttrName(),
2534 getAbsoluteSymbolAttrName(), getDbgExprsAttrName(),
2535 getTargetSpecificAttrsAttrName(), getSymVisibilityAttrName()})
2537 {getSymNameAttrName(), getGlobalTypeAttrName(), getConstantAttrName(),
2538 getValueAttrName(), getLinkageAttrName(), getUnnamedAddrAttrName(),
2539 getTlsModeAttrName(), getVisibility_AttrName(), getComdatAttrName()});
2542 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2546 Region &initializer = getInitializerRegion();
2547 if (!initializer.
empty()) {
2554 std::optional<SymbolRefAttr> attr,
2560 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2561 return op->
emitError() <<
"expected comdat symbol";
2571 WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2572 if (blockTags.contains(blockTagOp.getTag())) {
2573 blockTagOp.emitError()
2574 <<
"duplicate block tag '" << blockTagOp.getTag().getId()
2575 <<
"' in the same function: ";
2578 blockTags.insert(blockTagOp.getTag());
2582 return failure(res.wasInterrupted());
2587template <
typename OpType>
2594 OpType::getLinkageAttrName(
result.name),
2596 parser, LLVM::Linkage::External)));
2599 result.addAttribute(OpType::getVisibility_AttrName(
result.name),
2602 parser, LLVM::Visibility::Default)));
2605 ThreadLocalMode threadModel = ThreadLocalMode::GeneralDynamic;
2612 parser, ThreadLocalMode::NotThreadLocal);
2613 if (threadModel == ThreadLocalMode::NotThreadLocal) {
2614 parser.
emitError(kwLoc,
"invalid value for thread_local");
2620 result.addAttribute(OpType::getTlsModeAttrName(
result.name),
2621 ThreadLocalModeAttr::get(ctx, threadModel));
2625 result.addAttribute(OpType::getUnnamedAddrAttrName(
result.name),
2628 parser, LLVM::UnnamedAddr::None)));
2666 SymbolRefAttr comdat;
2671 result.addAttribute(getComdatAttrName(
result.name), comdat);
2679 if (types.size() > 1)
2683 if (types.empty()) {
2684 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2686 auto arrayType = LLVM::LLVMArrayType::get(IntegerType::get(context, 8),
2687 strAttr.getValue().size());
2688 types.push_back(arrayType);
2691 "type can only be omitted for string globals");
2701 result.addAttribute(getGlobalTypeAttrName(
result.name),
2702 TypeAttr::get(types[0]));
2707 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2708 return intValue.getValue().isZero();
2709 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2710 return fpValue.getValue().isZero();
2711 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2713 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2715 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2724LogicalResult GlobalOp::verify() {
2726 ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
2728 :
llvm::isa<PointerElementTypeInterface>(
getType());
2731 "expects type to be a valid element type for an LLVM global");
2733 return emitOpError(
"must appear at the module level");
2735 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2736 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2737 IntegerType elementType =
2738 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) :
nullptr;
2739 if (!elementType || elementType.getWidth() != 8 ||
2740 type.getNumElements() != strAttr.getValue().size())
2742 "requires an i8 array type of the length equal to that of the string "
2746 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2747 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2748 return emitOpError()
2749 <<
"this target extension type cannot be used in a global";
2752 return emitOpError() <<
"global with target extension type can only be "
2753 "initialized with zero-initializer";
2756 if (getLinkage() == Linkage::Common) {
2757 if (
Attribute value = getValueOrNull()) {
2759 return emitOpError()
2760 <<
"expected zero value for '"
2761 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2766 if (getLinkage() == Linkage::Appending) {
2767 if (!llvm::isa<LLVMArrayType>(
getType())) {
2768 return emitOpError() <<
"expected array type for '"
2769 << stringifyLinkage(Linkage::Appending)
2774 std::optional<uint64_t> alignAttr = getAlignment();
2775 if (alignAttr.has_value()) {
2776 uint64_t value = alignAttr.value();
2777 if (!llvm::isPowerOf2_64(value))
2778 return emitError() <<
"alignment attribute is not a power of 2";
2782 if (associated.getValue() == getSymName())
2783 return emitOpError(
"associated cannot refer to the global itself");
2786 if (
ArrayAttr absSym = getAbsoluteSymbolAttr()) {
2787 if (absSym.empty() || absSym.size() % 2 != 0)
2789 "absolute_symbol must contain one or more integer range pairs");
2792 auto intAttr = dyn_cast<IntegerAttr>(attr);
2794 return emitOpError(
"absolute_symbol operands must be integers");
2796 pairType = intAttr.getType();
2797 else if (intAttr.getType() != pairType)
2798 return emitOpError(
"absolute_symbol range pair types must match");
2805LogicalResult GlobalOp::verifyRegions() {
2806 if (
Block *
b = getInitializerBlock()) {
2807 ReturnOp ret = cast<ReturnOp>(
b->getTerminator());
2808 if (ret.operand_type_begin() == ret.operand_type_end())
2809 return emitOpError(
"initializer region cannot return void");
2810 if (*ret.operand_type_begin() !=
getType())
2811 return emitOpError(
"initializer region type ")
2812 << *ret.operand_type_begin() <<
" does not match global type "
2816 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2817 if (!iface || !iface.hasNoEffect())
2818 return op.emitError()
2819 <<
"ops with side effects not allowed in global initializers";
2822 if (getValueOrNull())
2823 return emitOpError(
"cannot have both initializer value and region");
2838 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2841 return op->
emitError(
"data element must be symbol or #llvm.zero");
2854LogicalResult GlobalCtorsOp::verify() {
2858 if (getCtors().size() == getPriorities().size() &&
2859 getCtors().size() == getData().size())
2862 "ctors, priorities, and data must have the same number of elements");
2879LogicalResult GlobalDtorsOp::verify() {
2883 if (getDtors().size() == getPriorities().size() &&
2884 getDtors().size() == getData().size())
2887 "dtors, priorities, and data must have the same number of elements");
2895 Linkage linkage, StringRef name,
bool dsoLocal,
2896 ThreadLocalMode threadModel,
2900 result.addAttribute(getAliasTypeAttrName(
result.name), TypeAttr::get(type));
2902 getTlsModeAttrName(
result.name),
2903 ThreadLocalModeAttr::get(builder.
getContext(), threadModel));
2909 LinkageAttr::get(builder.
getContext(), linkage));
2910 result.attributes.append(attrs.begin(), attrs.end());
2921 {getDsoLocalAttrName(), getSymVisibilityAttrName()})
2923 {getSymNameAttrName(), getAliasTypeAttrName(), getLinkageAttrName(),
2924 getUnnamedAddrAttrName(), getTlsModeAttrName(),
2925 getVisibility_AttrName()});
2928 p <<
" : " <<
getType() <<
' ';
2954 if (types.size() > 1)
2962 TypeAttr::get(types[0]));
2966LogicalResult AliasOp::verify() {
2968 ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
2970 :
llvm::isa<PointerElementTypeInterface>(
getType());
2973 "expects type to be a valid element type for an LLVM global alias");
2976 switch (getLinkage()) {
2977 case Linkage::External:
2978 case Linkage::Internal:
2979 case Linkage::Private:
2981 case Linkage::WeakODR:
2982 case Linkage::Linkonce:
2983 case Linkage::LinkonceODR:
2984 case Linkage::AvailableExternally:
2987 return emitOpError()
2988 <<
"'" << stringifyLinkage(getLinkage())
2989 <<
"' linkage not supported in aliases, available options: private, "
2990 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2991 "available_externally";
2997LogicalResult AliasOp::verifyRegions() {
2998 Block &
b = getInitializerBlock();
2999 auto ret = cast<ReturnOp>(
b.getTerminator());
3000 if (ret.getNumOperands() == 0 ||
3001 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
3002 return emitOpError(
"initializer region must always return a pointer");
3005 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
3006 if (!iface || !iface.hasNoEffect())
3007 return op.emitError()
3008 <<
"ops with side effects are not allowed in alias initializers";
3014unsigned AliasOp::getAddrSpace() {
3015 Block &initializer = getInitializerBlock();
3017 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
3018 return ptrTy.getAddressSpace();
3026 Type iFuncType, StringRef resolverName,
Type resolverType,
3027 Linkage linkage, LLVM::Visibility visibility) {
3028 return build(builder,
result, name, iFuncType, resolverName, resolverType,
3030 UnnamedAddr::None, visibility,
nullptr);
3037 auto resolver = dyn_cast<LLVMFuncOp>(symbol);
3038 auto alias = dyn_cast<AliasOp>(symbol);
3040 Block &initBlock = alias.getInitializerBlock();
3042 auto addrOp = returnOp.getArg().getDefiningOp<AddressOfOp>();
3049 resolver = addrOp.getFunction(symbolTable);
3050 alias = addrOp.getAlias(symbolTable);
3053 return emitOpError(
"must have a function resolver");
3054 Linkage linkage = resolver.getLinkage();
3055 if (resolver.isExternal() || linkage == Linkage::AvailableExternally)
3056 return emitOpError(
"resolver must be a definition");
3057 if (!isa<LLVMPointerType>(resolver.getFunctionType().getReturnType()))
3058 return emitOpError(
"resolver must return a pointer");
3059 auto resolverPtr = dyn_cast<LLVMPointerType>(getResolverType());
3060 if (!resolverPtr || resolverPtr.getAddressSpace() != getAddressSpace())
3061 return emitOpError(
"resolver has incorrect type");
3065LogicalResult IFuncOp::verify() {
3066 switch (getLinkage()) {
3067 case Linkage::External:
3068 case Linkage::Internal:
3069 case Linkage::Private:
3071 case Linkage::WeakODR:
3072 case Linkage::Linkonce:
3073 case Linkage::LinkonceODR:
3076 return emitOpError() <<
"'" << stringifyLinkage(getLinkage())
3077 <<
"' linkage not supported in ifuncs, available "
3078 "options: private, internal, linkonce, weak, "
3079 "linkonce_odr, weak_odr, or external linkage";
3091 auto containerType = v1.
getType();
3095 build(builder, state, vType, v1, v2, mask);
3110 "expected an LLVM compatible vector type");
3122LogicalResult ShuffleVectorOp::verify() {
3124 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
3125 return emitOpError(
"expected a splat operation for scalable vectors");
3131OpFoldResult ShuffleVectorOp::fold(FoldAdaptor adaptor) {
3133 auto vecType = llvm::dyn_cast<VectorType>(getV1().
getType());
3134 if (!vecType || vecType.getRank() != 1 || vecType.getNumElements() != 1)
3138 if (getMask().size() != 1 || getMask()[0] != 0)
3149 assert(empty() &&
"function already has an entry block");
3154 LLVMFunctionType type = getFunctionType();
3155 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
3156 entry->
addArgument(type.getParamType(i), getLoc());
3161 StringRef name,
Type type, LLVM::Linkage linkage,
3162 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
3165 std::optional<uint64_t> functionEntryCount) {
3169 result.addAttribute(getFunctionTypeAttrName(
result.name),
3170 TypeAttr::get(type));
3172 LinkageAttr::get(builder.
getContext(), linkage));
3174 CConvAttr::get(builder.
getContext(), cconv));
3175 result.attributes.append(attrs.begin(), attrs.end());
3180 result.addAttribute(getComdatAttrName(
result.name), comdat);
3181 if (functionEntryCount)
3182 result.addAttribute(getFunctionEntryCountAttrName(
result.name),
3183 FunctionEntryCountAttr::get(
3187 std::optional<NamedAttribute> duplicate =
result.attributes.findDuplicate();
3188 if (duplicate.has_value()) {
3189 llvm::report_fatal_error(
3190 Twine(
"LLVMFuncOp propagated an attribute that is meant "
3191 "to be constructed by the builder: ") +
3192 duplicate->getName().str());
3195 if (argAttrs.empty())
3198 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
3199 "expected as many argument attribute lists as arguments");
3201 builder,
result, argAttrs, {},
3202 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3213 if (outputs.size() > 1) {
3214 parser.
emitError(loc,
"failed to construct function type: expected zero or "
3215 "one function result");
3221 for (
auto t : inputs) {
3223 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3224 "type for function arguments");
3227 llvmInputs.push_back(t);
3232 outputs.empty() ? LLVMVoidType::get(
b.getContext()) : outputs.front();
3234 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3235 "type for function results")
3239 return LLVMFunctionType::get(llvmOutput, llvmInputs,
3255 parser, LLVM::Linkage::External)));
3258 result.addAttribute(getVisibility_AttrName(
result.name),
3261 parser, LLVM::Visibility::Default)));
3264 result.addAttribute(getUnnamedAddrAttrName(
result.name),
3267 parser, LLVM::UnnamedAddr::None)));
3271 getCConvAttrName(
result.name),
3275 StringAttr nameAttr;
3285 parser,
true, entryArgs, isVariadic, resultTypes,
3290 for (
auto &arg : entryArgs)
3291 argTypes.push_back(arg.type);
3297 result.addAttribute(getFunctionTypeAttrName(
result.name),
3298 TypeAttr::get(type));
3306 auto intTy = IntegerType::get(parser.
getContext(), 32);
3308 getVscaleRangeAttrName(
result.name),
3309 LLVM::VScaleRangeAttr::get(parser.
getContext(),
3310 IntegerAttr::get(intTy, minRange),
3311 IntegerAttr::get(intTy, maxRange)));
3315 SymbolRefAttr comdat;
3320 result.addAttribute(getComdatAttrName(
result.name), comdat);
3327 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3329 auto *body =
result.addRegion();
3340 if (getLinkage() != LLVM::Linkage::External)
3341 p << stringifyLinkage(getLinkage()) <<
' ';
3342 StringRef visibility = stringifyVisibility(getVisibility_());
3343 if (!visibility.empty())
3344 p << visibility <<
' ';
3345 if (
auto unnamedAddr = getUnnamedAddr()) {
3346 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
3350 if (getCConv() != LLVM::CConv::C)
3351 p << stringifyCConv(getCConv()) <<
' ';
3355 LLVMFunctionType fnType = getFunctionType();
3358 argTypes.reserve(fnType.getNumParams());
3359 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
3360 argTypes.push_back(fnType.getParamType(i));
3362 Type returnType = fnType.getReturnType();
3363 if (!llvm::isa<LLVMVoidType>(returnType))
3364 resTypes.push_back(returnType);
3367 isVarArg(), resTypes);
3370 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
3371 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
3372 << vscale->getMaxRange().getInt() <<
')';
3375 if (
auto comdat = getComdat())
3376 p <<
" comdat(" << *comdat <<
')';
3380 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
3381 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
3382 getComdatAttrName(), getUnnamedAddrAttrName(),
3383 getVscaleRangeAttrName()});
3386 Region &body = getBody();
3387 if (!body.empty()) {
3402LogicalResult LLVMFuncOp::verify() {
3403 if (getLinkage() == LLVM::Linkage::Common)
3404 return emitOpError() <<
"functions cannot have '"
3405 << stringifyLinkage(LLVM::Linkage::Common)
3409 if (getFunctionEntryCountAttr())
3410 return emitOpError() <<
"external functions cannot have "
3411 << getFunctionEntryCountAttrName() <<
" attribute";
3413 if (getLinkage() != LLVM::Linkage::External &&
3414 getLinkage() != LLVM::Linkage::ExternWeak)
3415 return emitOpError() <<
"external functions must have '"
3416 << stringifyLinkage(LLVM::Linkage::External)
3418 << stringifyLinkage(LLVM::Linkage::ExternWeak)
3424 if (isNoInline() && isAlwaysInline())
3425 return emitError(
"no_inline and always_inline attributes are incompatible");
3427 if (isOptimizeNone() && !isNoInline())
3428 return emitOpError(
"with optimize_none must also be no_inline");
3430 Type landingpadResultTy;
3431 StringRef diagnosticMessage;
3432 bool isLandingpadTypeConsistent =
3434 const auto checkType = [&](
Type type, StringRef errorMessage) {
3435 if (!landingpadResultTy) {
3436 landingpadResultTy = type;
3439 if (landingpadResultTy != type) {
3440 diagnosticMessage = errorMessage;
3446 .Case([&](LandingpadOp landingpad) {
3447 constexpr StringLiteral errorMessage =
3448 "'llvm.landingpad' should have a consistent result type "
3449 "inside a function";
3450 return checkType(landingpad.getType(), errorMessage);
3452 .Case([&](ResumeOp resume) {
3453 constexpr StringLiteral errorMessage =
3454 "'llvm.resume' should have a consistent input type inside a "
3456 return checkType(resume.getValue().getType(), errorMessage);
3459 }).wasInterrupted();
3460 if (!isLandingpadTypeConsistent) {
3461 assert(!diagnosticMessage.empty() &&
3462 "Expecting a non-empty diagnostic message");
3474LogicalResult LLVMFuncOp::verifyRegions() {
3478 unsigned numArguments = getFunctionType().getNumParams();
3479 Block &entryBlock = front();
3480 for (
unsigned i = 0; i < numArguments; ++i) {
3483 return emitOpError(
"entry block argument #")
3484 << i <<
" is not of LLVM type";
3490Region *LLVMFuncOp::getCallableRegion() {
3519OpFoldResult LLVM::MetadataAsValueOp::fold(FoldAdaptor) {
3520 return getMetadataAttr();
3527LogicalResult LLVM::ZeroOp::verify() {
3528 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3529 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3530 return emitOpError()
3531 <<
"target extension type does not support zero-initializer";
3553 if (
auto vecType = dyn_cast<VectorType>(t)) {
3554 assert(!vecType.isScalable() &&
3555 "number of elements of a scalable vector type is unknown");
3556 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3558 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3559 return arrayType.getNumElements() *
3567 while (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(type))
3568 type = arrayType.getElementType();
3569 if (
auto vecType = dyn_cast<VectorType>(type))
3570 return vecType.getElementType();
3571 if (
auto tenType = dyn_cast<TensorType>(type))
3572 return tenType.getElementType();
3579 if (
auto vecType = dyn_cast<VectorType>(t)) {
3580 if (vecType.isScalable())
3584 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3592 LLVM::LLVMArrayType arrayType,
3594 if (arrayType.getNumElements() != arrayAttr.size())
3595 return op.emitOpError()
3596 <<
"array attribute size does not match array type size in "
3598 << dim <<
": " << arrayAttr.size() <<
" vs. "
3599 << arrayType.getNumElements();
3604 if (
auto subArrayType =
3605 dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
3606 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr))
3607 if (elementsVerified.insert(elementAttr).second) {
3608 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3610 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3612 return op.emitOpError()
3613 <<
"nested attribute for sub-array in dimension " << dim
3614 <<
" at index " << idx
3615 <<
" must be a zero, or undef, or array attribute";
3629 Type elementType = arrayType.getElementType();
3630 if (isa<LLVM::LLVMPointerType>(elementType)) {
3631 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3633 LLVM::PoisonAttr>(elementAttr))
3635 return op.emitOpError()
3636 <<
"pointer array element at index " << idx
3637 <<
" must be a flat symbol reference, zero, undef, or poison";
3641 auto structType = dyn_cast<LLVM::LLVMStructType>(elementType);
3643 return op.emitOpError() <<
"for array with an array attribute must have a "
3644 "struct element type";
3648 size_t numStructElements = structType.getBody().size();
3649 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3650 if (elementsVerified.insert(elementAttr).second) {
3651 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3653 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3655 return op.emitOpError()
3656 <<
"nested attribute for struct element at index " << idx
3657 <<
" must be a zero, or undef, or array attribute";
3658 if (subArrayAttr.size() != numStructElements)
3659 return op.emitOpError()
3660 <<
"nested array attribute size for struct element at index "
3661 << idx <<
" must match struct size: " << subArrayAttr.size()
3662 <<
" vs. " << numStructElements;
3669LogicalResult LLVM::ConstantOp::verify() {
3670 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3671 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3672 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3673 !arrayType.getElementType().isInteger(8)) {
3674 return emitOpError() <<
"expected array type of "
3675 << sAttr.getValue().size()
3676 <<
" i8 elements for the string constant";
3680 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3681 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3683 return emitOpError() <<
"expected array attribute for struct type";
3686 if (arrayAttr.size() != elementTypes.size()) {
3687 return emitOpError() <<
"expected array attribute of size "
3688 << elementTypes.size();
3690 for (
auto [i, attr, type] : llvm::enumerate(arrayAttr, elementTypes)) {
3692 return emitOpError() <<
"expected struct element types to be floating "
3693 "point type or integer type";
3695 if (!isa<FloatAttr, IntegerAttr>(attr)) {
3696 return emitOpError() <<
"expected element of array attribute to be "
3697 "floating point or integer";
3699 if (cast<TypedAttr>(attr).
getType() != type)
3700 return emitOpError()
3701 <<
"struct element at index " << i <<
" is of wrong type";
3706 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3707 return emitOpError() <<
"does not support target extension type.";
3718 auto verifyFloatSemantics =
3719 [
this](
const llvm::fltSemantics &attributeFloatSemantics,
3720 Type constantElementType) -> LogicalResult {
3721 if (
auto floatType = dyn_cast<FloatType>(constantElementType)) {
3722 if (&floatType.getFloatSemantics() != &attributeFloatSemantics) {
3723 return emitOpError()
3724 <<
"attribute and type have different float semantics";
3728 unsigned floatWidth = APFloat::getSizeInBits(attributeFloatSemantics);
3729 if (isa<IntegerType>(constantElementType)) {
3730 if (!constantElementType.isInteger(floatWidth))
3731 return emitOpError() <<
"expected integer type of width " << floatWidth;
3746 auto verifyIntegerSemantics = [
this](
Type attributeIntType,
3747 Type constantElementType,
3748 StringRef description) -> LogicalResult {
3749 if (attributeIntType != constantElementType)
3750 return emitOpError() <<
"attribute and type have different integer "
3751 << description <<
"s: " << attributeIntType
3752 <<
" vs. " << constantElementType;
3757 if (
auto intAttr = dyn_cast<IntegerAttr>(getValue())) {
3758 if (!llvm::isa<IntegerType>(
getType()))
3759 return emitOpError() <<
"expected integer type";
3760 return verifyIntegerSemantics(intAttr.getType(),
getType(),
"type");
3761 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3762 return verifyFloatSemantics(floatAttr.getValue().getSemantics(),
getType());
3763 }
else if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
3767 auto verifyElementTypes = [&](ElementsAttr attr) -> LogicalResult {
3770 if (
auto floatType = dyn_cast<FloatType>(attrElmType))
3771 return verifyFloatSemantics(floatType.getFloatSemantics(),
3774 if (isa<IntegerType, IndexType>(attrElmType)) {
3775 if (!isa<IntegerType>(resultElmType))
3777 "expected integer element type for integer elements attribute");
3778 return verifyIntegerSemantics(attrElmType, resultElmType,
3787 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3788 if (!splatElementsAttr)
3789 return emitOpError()
3790 <<
"scalable vector type requires a splat attribute";
3791 return verifyElementTypes(splatElementsAttr);
3793 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3794 return emitOpError() <<
"expected vector or array type";
3797 int64_t attrNumElements = elementsAttr.getNumElements();
3799 return emitOpError()
3800 <<
"type and attribute have a different number of elements: "
3804 return verifyElementTypes(elementsAttr);
3805 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {
3808 auto arrayType = dyn_cast<LLVM::LLVMArrayType>(
getType());
3810 return emitOpError()
3811 <<
"expected array or struct type for array attribute";
3817 return emitOpError()
3818 <<
"only supports integer, float, string or elements attributes";
3822bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3824 auto typedAttr = dyn_cast<TypedAttr>(value);
3831 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3836 if (isBuildableWith(value, type))
3837 return LLVM::ConstantOp::create(builder, loc, cast<TypedAttr>(value));
3842OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3850 AtomicOrdering ordering, StringRef syncscope,
3851 unsigned alignment,
bool isVolatile) {
3852 build(builder, state, val.
getType(), binOp,
ptr, val, ordering,
3853 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3856 nullptr,
nullptr,
nullptr);
3859LogicalResult AtomicRMWOp::verify() {
3860 auto valType = getVal().getType();
3861 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3862 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax ||
3863 getBinOp() == AtomicBinOp::fminimum ||
3864 getBinOp() == AtomicBinOp::fmaximum ||
3865 getBinOp() == AtomicBinOp::fminimumnum ||
3866 getBinOp() == AtomicBinOp::fmaximumnum) {
3869 return emitOpError(
"expected LLVM IR fixed vector type");
3870 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3873 "expected LLVM IR floating point type for vector element");
3875 return emitOpError(
"expected LLVM IR floating point type");
3877 }
else if (getBinOp() == AtomicBinOp::xchg) {
3880 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3882 auto intType = llvm::dyn_cast<IntegerType>(valType);
3883 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3884 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3886 return emitOpError(
"expected LLVM IR integer type");
3889 if (
static_cast<unsigned>(getOrdering()) <
3890 static_cast<unsigned>(AtomicOrdering::monotonic))
3891 return emitOpError() <<
"expected at least '"
3892 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3904 auto boolType = IntegerType::get(valType.
getContext(), 1);
3905 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3910 AtomicOrdering successOrdering,
3911 AtomicOrdering failureOrdering, StringRef syncscope,
3912 unsigned alignment,
bool isWeak,
bool isVolatile) {
3914 successOrdering, failureOrdering,
3915 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3917 isVolatile,
nullptr,
3918 nullptr,
nullptr,
nullptr);
3921LogicalResult AtomicCmpXchgOp::verify() {
3922 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3924 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3925 auto valType = getVal().getType();
3928 return emitOpError(
"unexpected LLVM IR type");
3929 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3930 getFailureOrdering() < AtomicOrdering::monotonic)
3931 return emitOpError(
"ordering must be at least 'monotonic'");
3932 if (getFailureOrdering() == AtomicOrdering::release ||
3933 getFailureOrdering() == AtomicOrdering::acq_rel)
3934 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3943 AtomicOrdering ordering, StringRef syncscope) {
3944 build(builder, state, ordering,
3945 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3948LogicalResult FenceOp::verify() {
3949 if (getOrdering() == AtomicOrdering::not_atomic ||
3950 getOrdering() == AtomicOrdering::unordered ||
3951 getOrdering() == AtomicOrdering::monotonic)
3952 return emitOpError(
"can be given only acquire, release, acq_rel, "
3953 "and seq_cst orderings");
3963template <
class ExtOp>
3965 IntegerType inputType, outputType;
3968 return op.emitError(
3969 "input type is a vector but output type is an integer");
3972 return op.emitError(
"input and output vectors are of incompatible shape");
3975 inputType = cast<IntegerType>(
3976 cast<VectorType>(op.getArg().getType()).getElementType());
3977 outputType = cast<IntegerType>(
3978 cast<VectorType>(op.getResult().getType()).getElementType());
3982 inputType = cast<IntegerType>(op.getArg().getType());
3983 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3985 return op.emitError(
3986 "input type is an integer but output type is a vector");
3989 if (outputType.getWidth() <= inputType.getWidth())
3990 return op.emitError(
"integer width of the output type is smaller or "
3991 "equal to the integer width of the input type");
4002 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
4006 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
4007 return IntegerAttr::get(
getType(), arg.getValue().zext(targetSize));
4021template <
typename T>
4023 typename T::FoldAdaptor adaptor) {
4025 if (castOp.getArg().getType() == castOp.getType())
4026 return castOp.getArg();
4027 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
4029 if (prev.getArg().getType() == castOp.getType())
4030 return prev.getArg();
4032 castOp.getArgMutable().set(prev.getArg());
4033 return Value{castOp};
4038OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
4042LogicalResult LLVM::BitcastOp::verify() {
4048 if (isa<LLVMByteType>(srcElemType) || isa<LLVMByteType>(dstElemType))
4051 auto resultType = llvm::dyn_cast<LLVMPointerType>(dstElemType);
4052 auto sourceType = llvm::dyn_cast<LLVMPointerType>(srcElemType);
4056 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
4057 return emitOpError(
"can only cast pointers from and to pointers");
4062 auto isVector = llvm::IsaPred<VectorType>;
4066 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
4067 return emitOpError(
"cannot cast pointer to vector of pointers");
4069 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
4070 return emitOpError(
"cannot cast vector of pointers to pointer");
4074 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
4075 return emitOpError(
"cannot cast pointers of different address spaces, "
4076 "use 'llvm.addrspacecast' instead");
4081LogicalResult LLVM::PtrToAddrOp::verify() {
4088 assert(width &&
"pointers always return an index bitwidth");
4089 if (width != integerType.getWidth())
4090 return emitOpError(
"bit-width of integer result type ")
4091 << integerType <<
" must match the pointer bitwidth (" << *width
4092 <<
") specified in the datalayout";
4101OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
4105Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
4113 adaptor.getDynamicIndices());
4116 if (getInrangeAttr())
4121 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(
indices[0]))
4122 if (integer.getValue().isZero())
4126 bool changed =
false;
4128 for (
auto iter : llvm::enumerate(
indices)) {
4129 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
4132 if (!
indices.isDynamicIndex(iter.index()) || !integer ||
4136 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
4137 gepArgs.emplace_back(val);
4139 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
4145 gepArgs.emplace_back(integer.getInt());
4153 getDynamicIndicesMutable().assign(dynamicIndices);
4154 setRawConstantIndices(rawConstantIndices);
4155 return Value{*
this};
4161Value LLVM::GEPOp::getViewSource() {
return getBase(); }
4168 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
4172 if (rhs.getValue().uge(getLhs().
getType().getIntOrFloatBitWidth()))
4175 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
4179 return IntegerAttr::get(
getType(), lhs.getValue().shl(rhs.getValue()));
4187 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
4191 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
4195 return IntegerAttr::get(
getType(), lhs.getValue() | rhs.getValue());
4202LogicalResult CallIntrinsicOp::verify() {
4203 if (!getIntrin().starts_with(
"llvm."))
4204 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
4212 build(builder, state,
TypeRange{}, intrin, args,
4213 FastmathFlagsAttr{},
4220 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4221 build(builder, state,
TypeRange{}, intrin, args,
4228 mlir::Type resultType, mlir::StringAttr intrin,
4230 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
4238 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4239 build(builder, state, resultTypes, intrin, args, fastMathFlags,
4244ParseResult CallIntrinsicOp::parse(
OpAsmParser &parser,
4246 StringAttr intrinAttr;
4256 result.addAttribute(CallIntrinsicOp::getIntrinAttrName(
result.name),
4264 return mlir::failure();
4267 return mlir::failure();
4272 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
4275 if (opBundleTags && !opBundleTags.empty())
4277 CallIntrinsicOp::getOpBundleTagsAttrName(
result.name).getValue(),
4281 return mlir::failure();
4286 operands, argAttrs, resultAttrs))
4290 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
4293 opBundleOperandTypes,
4294 getOpBundleSizesAttrName(
result.name)))
4297 int32_t numOpBundleOperands = 0;
4298 for (
const auto &operands : opBundleOperands)
4299 numOpBundleOperands += operands.size();
4302 CallIntrinsicOp::getOperandSegmentSizeAttr(),
4304 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
4306 return mlir::success();
4314 p <<
"(" << args <<
")";
4317 if (!getOpBundleOperands().empty()) {
4320 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
4324 {getOperandSegmentSizesAttrName(),
4325 getOpBundleSizesAttrName(), getIntrinAttrName(),
4326 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
4327 getResAttrsAttrName()});
4333 p, args.
getTypes(), getArgAttrsAttr(),
4334 false, getResultTypes(), getResAttrsAttr());
4341LogicalResult LinkerOptionsOp::verify() {
4344 return emitOpError(
"must appear at the module level");
4352LogicalResult ModuleFlagsOp::verify() {
4355 return emitOpError(
"must appear at the module level");
4359 auto moduleFlag = dyn_cast<ModuleFlagAttrInterface>(flag);
4361 return emitOpError(
"expected a module flag attribute");
4363 moduleFlag.getModuleFlagKey(), moduleFlag.getModuleFlagValue(),
4364 [&] { return emitOpError(); })))
4366 if (moduleFlag.getModuleFlagBehavior() == ModFlagBehavior::Require)
4368 StringAttr key = moduleFlag.getModuleFlagKey();
4369 if (!seenNonRequireKeys.insert(key).second)
4370 return emitOpError(
"expected module flag key '")
4371 << key.getValue() <<
"' to be unique for non-require flags";
4380void InlineAsmOp::getEffects(
4383 if (getHasSideEffects()) {
4396 getBlockAddr().getFunction());
4397 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
4400 return emitOpError(
"must reference a function defined by 'llvm.func'");
4410BlockTagOp BlockAddressOp::getBlockTagOp() {
4415 auto funcOp = dyn_cast<LLVMFuncOp>(sym);
4418 BlockTagOp blockTagOp =
nullptr;
4419 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
4420 if (labelOp.getTag() == getBlockAddr().getTag()) {
4421 blockTagOp = labelOp;
4429LogicalResult BlockAddressOp::verify() {
4430 if (!getBlockTagOp())
4432 "expects an existing block label target in the referenced function");
4439OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
4446 assert(
index < getNumSuccessors() &&
"invalid successor index");
4458 rangeSegments.push_back(range.size());
4472 Block *destination = nullptr;
4473 SmallVector<OpAsmParser::UnresolvedOperand> operands;
4474 SmallVector<Type> operandTypes;
4476 if (parser.parseSuccessor(destination).failed())
4479 if (succeeded(parser.parseOptionalLParen())) {
4480 if (failed(parser.parseOperandList(
4481 operands, OpAsmParser::Delimiter::None)) ||
4482 failed(parser.parseColonTypeList(operandTypes)) ||
4483 failed(parser.parseRParen()))
4486 succOperandBlocks.push_back(destination);
4487 succOperands.emplace_back(operands);
4488 succOperandsTypes.emplace_back(operandTypes);
4491 "successor blocks")))
4501 llvm::zip(succs, succOperands),
4507 if (!succOperands.empty())
4519 auto resultStructType =
4520 mlir::dyn_cast<mlir::LLVM::LLVMStructType>(resultType);
4521 if (!resultStructType || resultStructType.getBody().size() != 2 ||
4522 resultStructType.getBody()[0] != operandType ||
4523 resultStructType.getBody()[1] != operandType) {
4525 "expected result type to be a homogeneous struct with "
4526 "two elements matching the operand type, but got ")
4532LogicalResult LLVM::SincosOp::verify() {
4537LogicalResult LLVM::ModfOp::verify() {
4548 return build(builder, state, cond, {},
4560 return build(builder, state, cond,
"align",
ValueRange{
ptr, align});
4566 return build(builder, state, cond,
"separate_storage",
4576LogicalResult LLVM::masked_gather::verify() {
4577 auto ptrsVectorType = getPtrs().getType();
4578 Type expectedPtrsVectorType =
4583 if (ptrsVectorType != expectedPtrsVectorType)
4584 return emitOpError(
"expected operand #1 type to be ")
4585 << expectedPtrsVectorType;
4593LogicalResult LLVM::masked_scatter::verify() {
4594 auto ptrsVectorType = getPtrs().getType();
4595 Type expectedPtrsVectorType =
4600 if (ptrsVectorType != expectedPtrsVectorType)
4601 return emitOpError(
"expected operand #2 type to be ")
4602 << expectedPtrsVectorType;
4615 build(builder, state, resTys,
ptr, mask, passthru, argAttrs,
4623void LLVM::masked_compressstore::build(
OpBuilder &builder,
4628 build(builder, state, value,
ptr, mask, argAttrs,
4636LogicalResult InlineAsmOp::verify() {
4637 if (!getTailCallKindAttr())
4640 if (getTailCallKindAttr().getTailCallKind() == TailCallKind::MustTail)
4642 "tail call kind 'musttail' is not supported by this operation");
4652 Value divisor = getRhs();
4667 Value divisor = getRhs();
4679void LLVMDialect::initialize() {
4680 registerAttributes();
4683 addTypes<LLVMVoidType,
4685 LLVMMetadataType>();
4689 registerLLVMDialectOperations(
this);
4692 allowUnknownOperations();
4693 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4697LogicalResult LLVMDialect::verifyDataLayoutString(
4700 llvm::DataLayout::parse(descr);
4701 if (maybeDataLayout)
4704 std::string message;
4705 llvm::raw_string_ostream messageStream(message);
4706 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4707 reportError(
"invalid data layout descriptor: " + message);
4712LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
4718 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4720 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
4721 return verifyDataLayoutString(
4722 stringAttr.getValue(),
4723 [op](
const Twine &message) { op->emitOpError() << message.str(); });
4726 << LLVM::LLVMDialect::getDataLayoutAttrName()
4727 <<
"' to be a string attributes";
4730LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
4738 StringAttr name = paramAttr.
getName();
4740 auto checkUnitAttrType = [&]() -> LogicalResult {
4741 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
4742 return op->
emitError() << name <<
" should be a unit attribute";
4745 auto checkTypeAttrType = [&]() -> LogicalResult {
4746 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
4747 return op->
emitError() << name <<
" should be a type attribute";
4750 auto checkIntegerAttrType = [&]() -> LogicalResult {
4751 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
4752 return op->
emitError() << name <<
" should be an integer attribute";
4755 auto checkPointerType = [&]() -> LogicalResult {
4756 if (!llvm::isa<LLVMPointerType>(paramType))
4758 << name <<
" attribute attached to non-pointer LLVM type";
4761 auto checkIntegerType = [&]() -> LogicalResult {
4762 if (!llvm::isa<IntegerType>(paramType))
4764 << name <<
" attribute attached to non-integer LLVM type";
4767 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4768 if (
failed(checkPointerType()))
4775 if (name == LLVMDialect::getNoAliasAttrName() ||
4776 name == LLVMDialect::getReadonlyAttrName() ||
4777 name == LLVMDialect::getReadnoneAttrName() ||
4778 name == LLVMDialect::getWriteOnlyAttrName() ||
4779 name == LLVMDialect::getNestAttrName() ||
4780 name == LLVMDialect::getNoCaptureAttrName() ||
4781 name == LLVMDialect::getNoFreeAttrName() ||
4782 name == LLVMDialect::getNoFreeObjAttrName() ||
4783 name == LLVMDialect::getNonNullAttrName()) {
4784 if (
failed(checkUnitAttrType()))
4786 if (verifyValueType &&
failed(checkPointerType()))
4792 if (name == LLVMDialect::getStructRetAttrName() ||
4793 name == LLVMDialect::getByValAttrName() ||
4794 name == LLVMDialect::getByRefAttrName() ||
4795 name == LLVMDialect::getElementTypeAttrName() ||
4796 name == LLVMDialect::getInAllocaAttrName() ||
4797 name == LLVMDialect::getPreallocatedAttrName()) {
4798 if (
failed(checkTypeAttrType()))
4800 if (verifyValueType &&
failed(checkPointerTypeMatches()))
4806 if (name == LLVMDialect::getSExtAttrName() ||
4807 name == LLVMDialect::getZExtAttrName()) {
4808 if (
failed(checkUnitAttrType()))
4810 if (verifyValueType &&
failed(checkIntegerType()))
4816 if (name == LLVMDialect::getAlignAttrName() ||
4817 name == LLVMDialect::getDereferenceableAttrName() ||
4818 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4819 if (
failed(checkIntegerAttrType()))
4821 if (verifyValueType &&
failed(checkPointerType()))
4827 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4828 if (
failed(checkIntegerAttrType()))
4834 if (name == LLVMDialect::getNoUndefAttrName() ||
4835 name == LLVMDialect::getInRegAttrName() ||
4836 name == LLVMDialect::getReturnedAttrName())
4837 return checkUnitAttrType();
4843LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4847 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4850 Type argType = funcOp.getArgumentTypes()[argIdx];
4852 return verifyParameterAttribute(op, argType, argAttr);
4855LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4859 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4862 Type resType = funcOp.getResultTypes()[resIdx];
4866 if (llvm::isa<LLVMVoidType>(resType))
4867 return op->
emitError() <<
"cannot attach result attributes to functions "
4868 "with a void return";
4872 auto name = resAttr.
getName();
4873 if (name == LLVMDialect::getAllocAlignAttrName() ||
4874 name == LLVMDialect::getAllocatedPointerAttrName() ||
4875 name == LLVMDialect::getByValAttrName() ||
4876 name == LLVMDialect::getByRefAttrName() ||
4877 name == LLVMDialect::getInAllocaAttrName() ||
4878 name == LLVMDialect::getNestAttrName() ||
4879 name == LLVMDialect::getNoCaptureAttrName() ||
4880 name == LLVMDialect::getNoFreeAttrName() ||
4881 name == LLVMDialect::getPreallocatedAttrName() ||
4882 name == LLVMDialect::getReadnoneAttrName() ||
4883 name == LLVMDialect::getReadonlyAttrName() ||
4884 name == LLVMDialect::getReturnedAttrName() ||
4885 name == LLVMDialect::getStackAlignmentAttrName() ||
4886 name == LLVMDialect::getStructRetAttrName() ||
4887 name == LLVMDialect::getWriteOnlyAttrName())
4888 return op->
emitError() << name <<
" is not a valid result attribute";
4889 return verifyParameterAttribute(op, resType, resAttr);
4897 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4898 if (isa<LLVM::LLVMPointerType>(type))
4899 return LLVM::AddressOfOp::create(builder, loc, type, symbol);
4900 if (isa<LLVM::UndefAttr>(value))
4901 return LLVM::UndefOp::create(builder, loc, type);
4902 if (isa<LLVM::PoisonAttr>(value))
4903 return LLVM::PoisonOp::create(builder, loc, type);
4904 if (isa<LLVM::ZeroAttr>(value))
4905 return LLVM::ZeroOp::create(builder, loc, type);
4906 if (isa<LLVM::MDStringAttr, LLVM::MDConstantAttr, LLVM::MDGlobalValueAttr,
4907 LLVM::MDNodeAttr>(value))
4908 if (isa<LLVM::LLVMMetadataType>(type))
4909 return LLVM::MetadataAsValueOp::create(builder, loc, type, value);
4911 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4919 StringRef name, StringRef value,
4920 LLVM::Linkage linkage) {
4923 "expected builder to point to a block constrained in an op");
4925 builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
4926 assert(module &&
"builder points to an op outside of a module");
4931 auto type = LLVM::LLVMArrayType::get(IntegerType::get(ctx, 8), value.size());
4932 auto global = LLVM::GlobalOp::create(
4933 moduleBuilder, loc, type,
true, linkage, name,
4936 LLVMPointerType ptrType = LLVMPointerType::get(ctx);
4939 LLVM::AddressOfOp::create(builder, loc, ptrType, global.getSymNameAttr());
4940 return LLVM::GEPOp::create(builder, loc, ptrType, type, globalPtr,
4952 module = module->getParentOp();
4953 assert(module &&
"unexpected operation outside of a module");
getNumOperands() - 1))) return failure()
Given a list of lists of parsed operands, populates uniqueOperands with unique operands.
static Value getBase(Value v)
Looks through known "view-like" ops to find the base memref.
static int parseOptionalKeywordAlternative(OpAsmParser &parser, ArrayRef< StringRef > keywords)
static ArrayAttr getLLVMAlignParamForCompressExpand(OpBuilder &builder, bool isExpandLoad, uint64_t alignment=1)
static LogicalResult verifyAtomicMemOp(OpTy memOp, Type valueType, ArrayRef< AtomicOrdering > unsupportedOrderings)
Verifies the attributes and the type of atomic memory access operations.
static RetTy parseOptionalLLVMKeyword(OpAsmParser &parser, EnumTy defaultValue)
Parse an enum from the keyword, or default to the provided default value.
static LogicalResult checkGlobalXtorData(Operation *op, ArrayAttr data)
static LogicalResult verifyOperandBundles(OpType &op)
static LogicalResult verifyCallOpSymbolUses(OpTy callOp, SymbolTableCollection &symbolTable)
static void printOneOpBundle(OpAsmPrinter &p, OperandRange operands, TypeRange operandTypes, StringRef tag)
static unsigned getNumConsumedCalleeOperands(OpTy callOp)
Return the number of leading callee operands of callOp that the operation consumes instead of passing...
static LLVMFunctionType getLLVMFuncType(MLIRContext *context, TypeRange results, ValueRange args)
Constructs a LLVMFunctionType from MLIR results and args.
static LogicalResult verifyCallOpVarCalleeType(OpTy callOp)
Verify that the parameter and return types of the variadic callee type match the callOp argument and ...
static ParseResult parseOptionalCallFuncPtr(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &operands)
Parses an optional function pointer operand before the call argument list for indirect calls,...
static bool isZeroAttribute(Attribute value)
static Operation::operand_range getOperandsPassedToCallee(OpTy callOp)
Return the operands of callOp that are passed to the callee, including the variadic arguments in case...
static LogicalResult verifyComdat(Operation *op, std::optional< SymbolRefAttr > attr, SymbolTableCollection &symbolTable)
static LogicalResult verifyCallOpDebugInfo(OpTy callOp, LLVMFuncOp callee)
Verify that an inlinable callsite of a debug-info-bearing function in a debug-info-bearing function h...
static LogicalResult verifyBlockTags(LLVMFuncOp funcOp)
static Type buildLLVMFunctionType(OpAsmParser &parser, SMLoc loc, ArrayRef< Type > inputs, ArrayRef< Type > outputs, function_interface_impl::VariadicFlag variadicFlag)
static auto processFMFAttr(ArrayRef< NamedAttribute > attrs)
static TypeAttr getCallOpVarCalleeType(LLVMFunctionType calleeType)
Gets the variadic callee type for a LLVMFunctionType.
static Type getInsertExtractValueElementType(function_ref< InFlightDiagnostic(StringRef)> emitError, Type containerType, ArrayRef< int64_t > position)
Extract the type at position in the LLVM IR aggregate type containerType.
static ParseResult parseOneOpBundle(OpAsmParser &p, SmallVector< SmallVector< OpAsmParser::UnresolvedOperand > > &opBundleOperands, SmallVector< SmallVector< Type > > &opBundleOperandTypes, SmallVector< Attribute > &opBundleTags)
static ParseResult resolveOpBundleOperands(OpAsmParser &parser, SMLoc loc, OperationState &state, ArrayRef< SmallVector< OpAsmParser::UnresolvedOperand > > opBundleOperands, ArrayRef< SmallVector< Type > > opBundleOperandTypes, StringAttr opBundleSizesAttrName)
static LogicalResult verifyStructArrayConstant(LLVM::ConstantOp op, LLVM::LLVMArrayType arrayType, ArrayAttr arrayAttr, int dim)
Verifies the constant array represented by arrayAttr matches the provided arrayType.
static ParseResult parseCallTypeAndResolveOperands(OpAsmParser &parser, OperationState &result, bool isDirect, ArrayRef< OpAsmParser::UnresolvedOperand > operands, SmallVectorImpl< DictionaryAttr > &argAttrs, SmallVectorImpl< DictionaryAttr > &resultAttrs)
Parses the type of a call operation and resolves the operands if the parsing succeeds.
static LogicalResult verifySymbolAttrUse(FlatSymbolRefAttr symbol, Operation *op, SymbolTableCollection &symbolTable)
Verifies symbol's use in op to ensure the symbol is a valid and fully defined llvm....
static Type extractVectorElementType(Type type)
Returns the elemental type of any LLVM-compatible vector type or self.
static bool hasScalableVectorType(Type t)
Check if the given type is a scalable vector type or a vector/array type that contains a nested scala...
static SmallVector< Type, 1 > getCallOpResultTypes(LLVMFunctionType calleeType)
Gets the MLIR Op-like result types of a LLVMFunctionType.
static LogicalResult verifyHomogeneousStructResult(Operation *op, Type operandType, Type resultType)
static OpFoldResult foldChainableCast(T castOp, typename T::FoldAdaptor adaptor)
Folds a cast op that can be chained.
static void destructureIndices(Type currType, ArrayRef< GEPArg > indices, SmallVectorImpl< int32_t > &rawConstantIndices, SmallVectorImpl< Value > &dynamicIndices)
Destructures the 'indices' parameter into 'rawConstantIndices' and 'dynamicIndices',...
static ParseResult parseCommonGlobalAndAlias(OpAsmParser &parser, OperationState &result)
Parse common attributes that might show up in the same order in both GlobalOp and AliasOp.
static NamedAttrList getAttrsForPrinting(Operation *op)
static ParseResult parseCmpPredicateImpl(OpAsmParser &parser, PredicateAttr &predicate, function_ref< std::optional< Predicate >(StringRef)> symbolize)
static void printCommonGlobalAndAlias(OpAsmPrinter &p, OpType op)
static Attribute getBoolAttribute(Type type, MLIRContext *ctx, bool value)
Returns a scalar or vector boolean attribute of the given type.
static LogicalResult verifyExtOp(ExtOp op)
Verifies that the given extension operation operates on consistent scalars or vectors,...
static constexpr const char kElemTypeAttrName[]
static LogicalResult verifyStructIndices(Type baseGEPType, unsigned indexPos, GEPIndicesAdaptor< ValueRange > indices, function_ref< InFlightDiagnostic()> emitOpError)
For the given indices, check if they comply with baseGEPType, especially check against LLVMStructType...
static Attribute extractElementAt(Attribute attr, size_t index)
Extracts the element at the given index from an attribute.
static int64_t getNumElements(Type t)
Compute the total number of elements in the given type, also taking into account nested types.
#define REGISTER_ENUM_TYPE(Ty)
static Operation::operand_range getArgOperandsImpl(OpTy callOp)
Return the operands of callOp that correspond to the declared parameters of the callee,...
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity,...
This base class exposes generic asm parser hooks, usable across the various derived parsers.
ParseResult parseSymbolName(StringAttr &result)
Parse an -identifier and store it (without the '@' symbol) in a string attribute.
@ Paren
Parens surrounding zero or more operands.
@ None
Zero or more operands with no delimiters.
@ Square
Square brackets surrounding zero or more operands.
virtual OptionalParseResult parseOptionalInteger(APInt &result)=0
Parse an optional integer value from the stream.
virtual ParseResult parseColonTypeList(SmallVectorImpl< Type > &result)=0
Parse a colon followed by a type list, which must have at least one type.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual ParseResult parseOptionalAttrDict(NamedAttrList &result)=0
Parse a named dictionary into 'result' if it is present.
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
MLIRContext * getContext() const
virtual ParseResult parseRParen()=0
Parse a ) token.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseLSquare()=0
Parse a [ token.
virtual ParseResult parseRSquare()=0
Parse a ] token.
virtual ParseResult parseOptionalColonTypeList(SmallVectorImpl< Type > &result)=0
Parse an optional colon followed by a type list, which if present must have at least one type.
ParseResult parseInteger(IntT &result)
Parse an integer value from the stream.
virtual ParseResult parseOptionalRParen()=0
Parse a ) token if present.
virtual ParseResult parseCustomAttributeWithFallback(Attribute &result, Type type, function_ref< ParseResult(Attribute &result, Type type)> parseAttribute)=0
Parse a custom attribute with the provided callback, unless the next token is #, in which case the ge...
ParseResult parseString(std::string *string)
Parse a quoted string token.
virtual ParseResult parseOptionalAttrDictWithKeyword(NamedAttrList &result)=0
Parse a named dictionary into 'result' if the attributes keyword is present.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseOptionalComma()=0
Parse a , token if present.
virtual ParseResult parseColon()=0
Parse a : token.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseOptionalRSquare()=0
Parse a ] token if present.
virtual ParseResult parseLParen()=0
Parse a ( token.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual ParseResult parseComma()=0
Parse a , token.
virtual ParseResult parseOptionalLParen()=0
Parse a ( token if present.
ParseResult parseTypeList(SmallVectorImpl< Type > &result)
Parse a type list.
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
virtual ParseResult parseOptionalLSquare()=0
Parse a [ token if present.
virtual ParseResult parseAttribute(Attribute &result, Type type={})=0
Parse an arbitrary attribute of a given type and return it in result.
This base class exposes generic asm printer hooks, usable across the various derived printers.
virtual void printAttributeWithoutType(Attribute attr)
Print the given attribute without its type.
virtual void printSymbolName(StringRef symbolRef)
Print the given string as a symbol reference, i.e.
virtual void printString(StringRef string)
Print the given string as a quoted string, escaping any special or non-printable characters in it.
virtual void printAttribute(Attribute attr)
virtual void printNewline()
Print a newline and indent the printer to the start of the current operation/attribute/type.
Attributes are known-constant values of operations.
MLIRContext * getContext() const
Return the context this attribute belongs to.
This class provides an abstraction over the different types of ranges over Blocks.
Block represents an ordered list of Operations.
BlockArgument getArgument(unsigned i)
Operation * getTerminator()
Get the terminator operation of this block.
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
static BoolAttr get(MLIRContext *context, bool value)
This class is a general helper class for creating context-global objects like types,...
IntegerAttr getI32IntegerAttr(int32_t value)
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
IntegerAttr getI64IntegerAttr(int64_t value)
Ty getType(Args &&...args)
Get or construct an instance of the type Ty with provided arguments.
StringAttr getStringAttr(const Twine &bytes)
TypedAttr getZeroAttr(Type type)
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
MLIRContext * getContext() const
DictionaryAttr getDictionaryAttr(ArrayRef< NamedAttribute > value)
NamedAttribute getNamedAttr(StringRef name, Attribute val)
ArrayAttr getStrArrayAttr(ArrayRef< StringRef > values)
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
The main mechanism for performing data layout queries.
static DataLayout closest(Operation *op)
Returns the layout of the closest parent operation carrying layout info.
std::optional< uint64_t > getTypeIndexBitwidth(Type t) const
Returns the bitwidth that should be used when performing index computations for the given pointer-lik...
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
An attribute that represents a reference to a dense integer vector or tensor object.
static DenseIntElementsAttr get(const ShapedType &type, Arg &&arg)
Get an instance of a DenseIntElementsAttr with the given arguments.
A symbol reference with a reference path containing a single element.
StringRef getValue() const
Returns the name of the held symbol reference.
StringAttr getAttr() const
Returns the name of the held symbol reference as a StringAttr.
This class represents a fused location whose metadata is known to be an instance of the given type.
This class represents a diagnostic that is inflight and set to be reported.
Diagnostic & attachNote(std::optional< Location > noteLoc=std::nullopt)
Attaches a note to this diagnostic.
Class used for building a 'llvm.getelementptr'.
Class used for convenient access and iteration over GEP indices.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
This class provides a mutable adaptor for a range of operands.
MutableOperandRange slice(unsigned subStart, unsigned subLen, std::optional< OperandSegment > segment=std::nullopt) const
Slice this range into a sub range, with the additional operand segment.
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
ArrayRef< NamedAttribute > getAttrs() const
Return all of the attributes on this operation.
Attribute set(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
NamedAttribute represents a combination of a name and an Attribute value.
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual ParseResult parseRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region.
virtual ParseResult parseSuccessor(Block *&dest)=0
Parse a single operation successor.
virtual ParseResult resolveOperand(const UnresolvedOperand &operand, Type type, SmallVectorImpl< Value > &result)=0
Resolve an operand to an SSA value, emitting an error on failure.
virtual OptionalParseResult parseOptionalOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single operand if present.
virtual ParseResult parseSuccessorAndUseList(Block *&dest, SmallVectorImpl< Value > &operands)=0
Parse a single operation successor and its operand list.
virtual OptionalParseResult parseOptionalRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region if present.
ParseResult resolveOperands(Operands &&operands, Type type, SmallVectorImpl< Value > &result)
Resolve a list of operands to SSA values, emitting an error on failure, or appending the results to t...
virtual ParseResult parseOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single SSA value operand name along with a result number if allowResultNumber is true.
virtual ParseResult parseOperandList(SmallVectorImpl< UnresolvedOperand > &result, Delimiter delimiter=Delimiter::None, bool allowResultNumber=true, int requiredOperandCount=-1)=0
Parse zero or more SSA comma-separated operand references with a specified surrounding delimiter,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual void printSuccessorAndUseList(Block *successor, ValueRange succOperands)=0
Print the successor and its operands.
void printOperands(OperandRange operands)
Print a comma separated range of operation operands out of line to avoid instantiating the range iter...
virtual void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary with their values.
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
virtual void printOperand(Value value)=0
Print implementations for various things an operation contains.
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Listener * getListener() const
Returns the current listener of this builder, or nullptr if this builder doesn't have a listener.
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
This class represents a single result from folding an operation.
This class provides the API for ops that are known to be isolated from above.
A trait used to provide symbol table functionalities to a region operation.
This class represents a contiguous range of operand ranges, e.g.
This class implements the operand iterators for the Operation class.
type_range getTypes() const
void walkInherentAttrs(Operation *op, InherentAttrVisitor visitor) const
Visit the inherent attributes stored in the properties of op.
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
std::optional< Attribute > getInherentAttr(StringRef name)
Access an inherent attribute by name: returns an empty optional if there is no inherent attribute wit...
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
DictionaryAttr getRawDictionaryAttrs()
Return all attributes that are not stored as properties.
OperandRange operand_range
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
OperationName getName()
The name of an operation is the key identifier for it.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
This class implements Optional functionality for ParseResult.
ParseResult value() const
Access the internal ParseResult value.
bool has_value() const
Returns true if we contain a valid ParseResult value.
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
This class contains a list of basic blocks and a link to the parent operation it is attached to.
iterator_range< OpIterator > getOps()
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
void modifyOpInPlace(Operation *root, CallableT &&callable)
This method is a utility wrapper around an in-place modification of an operation.
This class represents a specific instance of an effect.
static DerivedEffect * get()
This class models how operands are forwarded to block arguments in control flow.
This class implements the successor iterators for Block.
This class represents a collection of SymbolTables.
virtual Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
virtual Operation * lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol)
Look up a symbol with the specified name within the specified symbol table operation,...
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
This class provides an abstraction for a range of TypeRange.
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
bool isSignlessIntOrIndexOrFloat() const
Return true if this is a signless integer, index, or float type.
This class provides an abstraction over the different types of ranges over Values.
type_range getTypes() const
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
A utility result that is used to signal how to proceed with an ongoing walk:
static WalkResult advance()
static WalkResult interrupt()
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int32_t > content)
ArrayRef< T > asArrayRef() const
A named class for passing around the variadic flag.
The OpAsmOpInterface, see OpAsmInterface.td for more details.
LogicalResult verifyModuleFlagValue(StringAttr key, Attribute value, function_ref< InFlightDiagnostic()> emitError)
Verifies that a module flag value can be exported to LLVM IR.
void addBytecodeInterface(LLVMDialect *dialect)
Add the interfaces necessary for encoding the LLVM dialect components in bytecode.
Value createGlobalString(Location loc, OpBuilder &builder, StringRef name, StringRef value, Linkage linkage)
Create an LLVM global containing the string "value" at the module containing surrounding the insertio...
Operation * parentLLVMModule(Operation *op)
Lookup parent Module satisfying LLVM conditions on the Module Operation.
Type getVectorType(Type elementType, unsigned numElements, bool isScalable=false)
Creates an LLVM dialect-compatible vector type with the given element type and length.
mlir::ParseResult parseCmpPredicate(mlir::OpAsmParser &parser, mlir::LLVM::ICmpPredicateAttr &predicate)
bool isScalableVectorType(Type vectorType)
Returns whether a vector type is scalable or not.
void printCmpPredicate(mlir::OpAsmPrinter &printer, mlir::Operation *, mlir::LLVM::ICmpPredicateAttr predicate)
mlir::ParseResult parseInsertExtractValueElementType(mlir::AsmParser &parser, mlir::Type &valueType, mlir::Type containerType, mlir::DenseI64ArrayAttr position)
Infer the value type from the container type and position.
void printLLVMLinkage(mlir::OpAsmPrinter &p, mlir::Operation *, mlir::LLVM::LinkageAttr val)
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
bool isCompatibleOuterType(Type type)
Returns true if the given outer type is compatible with the LLVM dialect without checking its potenti...
void printOpBundles(mlir::OpAsmPrinter &p, mlir::Operation *op, mlir::OperandRangeRange opBundleOperands, mlir::TypeRangeRange opBundleOperandTypes, std::optional< mlir::ArrayAttr > opBundleTags)
bool satisfiesLLVMModule(Operation *op)
LLVM requires some operations to be inside of a Module operation.
mlir::ParseResult parseShuffleType(mlir::AsmParser &parser, mlir::Type v1Type, mlir::Type &resType, mlir::DenseI32ArrayAttr mask)
Build the result type of a shuffle vector operation.
constexpr int kGEPConstantBitWidth
Bit-width of a 'GEPConstantIndex' within GEPArg.
void printShuffleType(mlir::AsmPrinter &printer, mlir::Operation *op, mlir::Type v1Type, mlir::Type resType, mlir::DenseI32ArrayAttr mask)
Nothing to do when the result type is inferred.
mlir::Type getI1SameShape(mlir::Type type)
Returns a boolean type that has the same shape as type.
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
bool isTypeCompatibleWithAtomicOp(Type type, const DataLayout &dataLayout)
Returns true if the given type is supported by atomic operations.
void printSwitchOpCases(mlir::OpAsmPrinter &p, mlir::LLVM::SwitchOp op, mlir::Type flagType, mlir::DenseIntElementsAttr caseValues, mlir::SuccessorRange caseDestinations, mlir::OperandRangeRange caseOperands, const mlir::TypeRangeRange &caseOperandTypes)
void printIndirectBrOpSucessors(mlir::OpAsmPrinter &p, mlir::LLVM::IndirectBrOp op, mlir::Type flagType, mlir::SuccessorRange succs, mlir::OperandRangeRange succOperands, const mlir::TypeRangeRange &succOperandsTypes)
mlir::ParseResult parseIndirectBrOpSucessors(mlir::OpAsmParser &parser, mlir::Type &flagType, mlir::SmallVectorImpl< mlir::Block * > &succOperandBlocks, mlir::SmallVectorImpl< mlir::SmallVector< mlir::OpAsmParser::UnresolvedOperand > > &succOperands, mlir::SmallVectorImpl< mlir::SmallVector< mlir::Type > > &succOperandsTypes)
mlir::ParseResult parseLLVMLinkage(mlir::OpAsmParser &p, mlir::LLVM::LinkageAttr &val)
mlir::LLVM::LLVMStructType getValAndBoolStructType(mlir::Type valType)
Returns an LLVM struct type that contains a value type and a boolean type.
bool isCompatibleFloatingPointType(Type type)
Returns true if the given type is a floating-point type compatible with the LLVM dialect.
std::optional< mlir::ParseResult > parseOpBundles(mlir::OpAsmParser &p, mlir::SmallVector< mlir::SmallVector< mlir::OpAsmParser::UnresolvedOperand > > &opBundleOperands, mlir::SmallVector< mlir::SmallVector< mlir::Type > > &opBundleOperandTypes, mlir::ArrayAttr &opBundleTags)
Type getConstantElementType(Type type)
Determines the element type of type the way the llvm.mlir.constant verifier does, i....
mlir::ParseResult parseGEPIndices(mlir::OpAsmParser &parser, mlir::SmallVectorImpl< mlir::OpAsmParser::UnresolvedOperand > &indices, mlir::DenseI32ArrayAttr &rawConstantIndices)
void printGEPIndices(mlir::OpAsmPrinter &printer, mlir::LLVM::GEPOp gepOp, mlir::OperandRange indices, mlir::DenseI32ArrayAttr rawConstantIndices)
void printInsertExtractValueElementType(mlir::AsmPrinter &printer, mlir::Operation *op, mlir::Type valueType, mlir::Type containerType, mlir::DenseI64ArrayAttr position)
Nothing to print for an inferred type.
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
mlir::ParseResult parseSwitchOpCases(mlir::OpAsmParser &parser, mlir::Type flagType, mlir::DenseIntElementsAttr &caseValues, mlir::SmallVectorImpl< mlir::Block * > &caseDestinations, mlir::SmallVectorImpl< mlir::SmallVector< mlir::OpAsmParser::UnresolvedOperand > > &caseOperands, mlir::SmallVectorImpl< mlir::SmallVector< mlir::Type > > &caseOperandTypes)
<cases> ::= [ (case (, case )* )?
Speculatability
This enum is returned from the getSpeculatability method in the ConditionallySpeculatable op interfac...
constexpr auto Speculatable
constexpr auto NotSpeculatable
void printFunctionSignature(OpAsmPrinter &p, TypeRange argTypes, ArrayAttr argAttrs, bool isVariadic, TypeRange resultTypes, ArrayAttr resultAttrs, Region *body=nullptr, bool printEmptyResult=true)
Print a function signature for a call or callable operation.
ParseResult parseFunctionSignature(OpAsmParser &parser, SmallVectorImpl< Type > &argTypes, SmallVectorImpl< DictionaryAttr > &argAttrs, SmallVectorImpl< Type > &resultTypes, SmallVectorImpl< DictionaryAttr > &resultAttrs, bool mustParseEmptyResult=true)
Parses a function signature using parser.
LogicalResult verifyCallOpInterface(CallOpInterface call, TypeRange argumentTypes, TypeRange resultTypes)
Verify that the forwarded operands and results of call are in a 1:1 relationship with the given argum...
void addArgAndResultAttrs(Builder &builder, OperationState &result, ArrayRef< DictionaryAttr > argAttrs, ArrayRef< DictionaryAttr > resultAttrs, StringAttr argAttrsName, StringAttr resAttrsName)
Adds argument and result attributes, provided as argAttrs and resultAttrs arguments,...
void walk(Operation *op, function_ref< void(Region *)> callback, WalkOrder order)
Walk all of the regions, blocks, or operations nested under (and including) the given operation.
ParseResult parseFunctionSignatureWithArguments(OpAsmParser &parser, bool allowVariadic, SmallVectorImpl< OpAsmParser::Argument > &arguments, bool &isVariadic, SmallVectorImpl< Type > &resultTypes, SmallVectorImpl< DictionaryAttr > &resultAttrs)
Parses a function signature using parser.
void printFunctionAttributes(OpAsmPrinter &p, Operation *op, ArrayRef< StringRef > elided={})
Prints the list of function prefixed with the "attributes" keyword.
void printFunctionSignature(OpAsmPrinter &p, FunctionOpInterface op, ArrayRef< Type > argTypes, bool isVariadic, ArrayRef< Type > resultTypes)
Prints the signature of the function-like operation op.
Operation::operand_range getIndices(Operation *op)
Get the indices that the given load/store operation is operating on.
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
detail::constant_int_value_binder m_ConstantInt(IntegerAttr::ValueType *bind_value)
Matches a constant holding a scalar/vector/tensor integer (splat) and writes the integer value to bin...
detail::DenseArrayAttrImpl< int64_t > DenseI64ArrayAttr
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
detail::constant_int_range_predicate_matcher m_IntRangeWithoutNegOneS()
Matches a constant scalar / vector splat / tensor splat integer or a signed integer range that does n...
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
detail::DenseArrayAttrImpl< int32_t > DenseI32ArrayAttr
llvm::TypeSwitch< T, ResultT > TypeSwitch
detail::constant_int_range_predicate_matcher m_IntRangeWithoutZeroS()
Matches a constant scalar / vector splat / tensor splat integer or a signed integer range that does n...
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
llvm::function_ref< Fn > function_ref
detail::constant_int_range_predicate_matcher m_IntRangeWithoutZeroU()
Matches a constant scalar / vector splat / tensor splat integer or a unsigned integer range that does...
A callable is either a symbol, or an SSA value, that is referenced by a call-like operation.
This is the representation of an operand reference.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
OpRewritePattern(MLIRContext *context, PatternBenefit benefit=1, ArrayRef< StringRef > generatedNames={})
Patterns must specify the root operation name they match against, and can also specify the benefit of...
This represents an operation in an abstracted form, suitable for use with the builder APIs.
T & getOrAddProperties()
Get (or create) the properties of the provided type to be set on the operation on creation.
SmallVector< Value, 4 > operands
void addOperands(ValueRange newOperands)
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
void addSuccessors(Block *successor)
Adds a successor to the operation sate. successor must not be null.