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 bool isNoundef, AtomicOrdering ordering,
932 StringRef syncscope) {
933 build(builder, state, type, addr,
935 isNonTemporal, isInvariant, isInvariantGroup, ordering,
936 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
937 nullptr, isNoundef,
nullptr,
947void StoreOp::getEffects(
956 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
957 getOrdering() != AtomicOrdering::unordered)) {
963LogicalResult StoreOp::verify() {
964 Type valueType = getValue().getType();
966 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
970 Value addr,
unsigned alignment,
bool isVolatile,
971 bool isNonTemporal,
bool isInvariantGroup,
972 AtomicOrdering ordering, StringRef syncscope) {
973 build(builder, state, value, addr,
975 isNonTemporal, isInvariantGroup, ordering,
976 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
978 nullptr,
nullptr,
nullptr);
988 Type resultType = calleeType.getReturnType();
989 if (!isa<LLVM::LLVMVoidType>(resultType))
990 results.push_back(resultType);
996 return calleeType.isVarArg() ? TypeAttr::get(calleeType) :
nullptr;
1003 if (results.empty())
1004 resultType = LLVMVoidType::get(context);
1006 resultType = results.front();
1007 return LLVMFunctionType::get(resultType, llvm::to_vector(args.
getTypes()),
1013 build(builder, state, results, builder.
getStringAttr(callee), args);
1018 build(builder, state, results, SymbolRefAttr::get(callee), args);
1023 assert(callee &&
"expected non-null callee in direct call builder");
1024 build(builder, state, results,
1025 nullptr, callee, args,
nullptr,
1028 nullptr,
nullptr,
nullptr,
1029 nullptr,
nullptr,
nullptr,
1033 nullptr,
nullptr,
nullptr,
1048 LLVMFunctionType calleeType, StringRef callee,
1050 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
1054 LLVMFunctionType calleeType, StringAttr callee,
1056 build(builder, state, calleeType, SymbolRefAttr::get(callee), args);
1074 nullptr,
nullptr,
nullptr,
1083 nullptr,
nullptr,
nullptr,
1089 LLVMFunctionType calleeType,
ValueRange args) {
1094 nullptr,
nullptr,
nullptr,
1095 nullptr,
nullptr,
nullptr,
1101 nullptr,
nullptr,
nullptr,
1117 auto calleeType =
func.getFunctionType();
1121 nullptr,
nullptr,
nullptr,
1122 nullptr,
nullptr,
nullptr,
1128 nullptr,
nullptr,
nullptr,
1147 return getOperand(0);
1153 auto symRef = cast<SymbolRefAttr>(callee);
1154 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1157 return setOperand(0, cast<Value>(callee));
1162template <
typename OpTy>
1165 if (callOp.getCallee().has_value())
1172template <
typename OpTy>
1174 return callOp.getCalleeOperands().drop_front(
1186template <
typename OpTy>
1189 if (std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType())
1190 return operands.take_front(varCalleeType->getNumParams());
1208template <
typename OpTy>
1210 if (callee.isExternal())
1212 auto parentFunc = callOp->template getParentOfType<FunctionOpInterface>();
1216 auto hasSubprogram = [](
Operation *op) {
1221 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1223 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1225 return callOp.emitError()
1226 <<
"inlinable function call in a function with a DISubprogram "
1227 "location must have a debug location";
1233template <
typename OpTy>
1236 if (!callOp.getCallee().has_value() && callOp.getCalleeOperands().empty())
1237 return callOp.emitOpError(
1238 "must have either a `callee` attribute or at least an operand");
1240 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1245 if (!varCalleeType->isVarArg())
1246 return callOp.emitOpError(
1247 "expected var_callee_type to be a variadic function type");
1255 if (varCalleeType->getNumParams() > passedOperands.size())
1256 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1257 << passedOperands.size() <<
" parameters";
1260 for (
auto [paramType, operand] :
1261 llvm::zip(varCalleeType->getParams(), passedOperands))
1262 if (paramType != operand.getType())
1263 return callOp.emitOpError()
1264 <<
"var_callee_type parameter type mismatch: " << paramType
1265 <<
" != " << operand.getType();
1268 if (!callOp.getNumResults()) {
1269 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1270 return callOp.emitOpError(
"expected var_callee_type to return void");
1272 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1273 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1274 << varCalleeType->getReturnType()
1275 <<
" != " << callOp.getResult().getType();
1280template <
typename OpType>
1283 std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1285 auto isStringAttr = [](
Attribute tagAttr) {
1286 return isa<StringAttr>(tagAttr);
1288 if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1289 return op.emitError(
"operand bundle tag must be a StringAttr");
1291 size_t numOpBundles = opBundleOperands.size();
1292 size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1293 if (numOpBundles != numOpBundleTags)
1294 return op.emitError(
"expected ")
1295 << numOpBundles <<
" operand bundle tags, but actually got "
1303template <
typename OpTy>
1318 llvm::dyn_cast<LLVMPointerType>(callOp.getOperand(0).getType());
1320 return callOp.emitOpError(
"indirect call expects a pointer as callee: ")
1321 << callOp.getOperand(0).getType();
1329 return callOp.emitOpError()
1331 <<
"' does not reference a symbol in the current scope";
1332 if (
auto fn = dyn_cast<LLVMFuncOp>(callee)) {
1335 fnType = fn.getFunctionType();
1336 }
else if (
auto ifunc = dyn_cast<IFuncOp>(callee)) {
1337 fnType = ifunc.getIFuncType();
1338 }
else if (isa<AliasOp>(callee)) {
1342 fnType = callOp.getCalleeFunctionType();
1344 return callOp.emitOpError()
1346 <<
"' does not reference a valid LLVM function, IFunc, or alias";
1350 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1352 return callOp.emitOpError(
"callee does not have a functional type: ")
1355 if (funcType.isVarArg() && !callOp.getVarCalleeType())
1356 return callOp.emitOpError()
1357 <<
"missing var_callee_type attribute for vararg call";
1361 if (callOp.getNumResults() == 0 &&
1362 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1363 return callOp.emitOpError() <<
"expected function call to produce a value";
1365 if (callOp.getNumResults() != 0 &&
1366 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1367 return callOp.emitOpError()
1368 <<
"calling function with void result must not produce values";
1370 if (callOp.getNumResults() > 1)
1371 return callOp.emitOpError()
1372 <<
"expected LLVM function call to produce 0 or 1 result";
1374 if (callOp.getNumResults() &&
1375 callOp.getResult().getType() != funcType.getReturnType())
1376 return callOp.emitOpError()
1377 <<
"result type mismatch: " << callOp.getResult().getType()
1378 <<
" != " << funcType.getReturnType();
1384 if (!llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1385 calleeResultTypes.push_back(funcType.getReturnType());
1387 callOp, funcType.getParams(), calleeResultTypes);
1395 auto callee = getCallee();
1396 bool isDirect = callee.has_value();
1401 if (getCConv() != LLVM::CConv::C)
1402 p << stringifyCConv(getCConv()) <<
' ';
1404 if (getTailCallKind() != LLVM::TailCallKind::None)
1405 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1414 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1415 p <<
'(' << args <<
')';
1418 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1419 p <<
" vararg(" << *varCalleeType <<
")";
1421 if (!getOpBundleOperands().empty()) {
1424 getOpBundleOperands().getTypes(), getOpBundleTags());
1428 {getCalleeAttrName(), getTailCallKindAttrName(),
1429 getVarCalleeTypeAttrName(), getCConvAttrName(),
1430 getOperandSegmentSizesAttrName(),
1431 getOpBundleSizesAttrName(),
1432 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1433 getResAttrsAttrName()});
1437 p << getOperand(0).getType() <<
", ";
1441 p, args.getTypes(), getArgAttrsAttr(),
1442 false, getResultTypes(), getResAttrsAttr());
1457 types.emplace_back();
1462 trailingTypesLoc,
"expected indirect call to have 2 trailing types");
1467 resTypes, resultAttrs)) {
1469 return parser.
emitError(trailingTypesLoc,
1470 "expected direct call to have 1 trailing types");
1471 return parser.
emitError(trailingTypesLoc,
1472 "expected trailing function type");
1475 if (resTypes.size() > 1)
1476 return parser.
emitError(trailingTypesLoc,
1477 "expected function with 0 or 1 result");
1478 if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
1479 return parser.
emitError(trailingTypesLoc,
1480 "expected a non-void result type");
1486 llvm::append_range(types, argTypes);
1490 if (!resTypes.empty())
1491 result.addTypes(resTypes);
1504 if (failed(*parseResult))
1505 return *parseResult;
1506 operands.push_back(funcPtrOperand);
1515 StringAttr opBundleSizesAttrName) {
1516 unsigned opBundleIndex = 0;
1517 for (
const auto &[operands, types] :
1518 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1519 if (operands.size() != types.size())
1520 return parser.
emitError(loc,
"expected ")
1522 <<
" types for operand bundle operands for operand bundle #"
1523 << opBundleIndex <<
", but actually got " << types.size();
1529 opBundleSizes.reserve(opBundleOperands.size());
1530 for (
const auto &operands : opBundleOperands)
1531 opBundleSizes.push_back(operands.size());
1534 opBundleSizesAttrName,
1546 SymbolRefAttr funcAttr;
1547 TypeAttr varCalleeType;
1555 getCConvAttrName(
result.name),
1560 getTailCallKindAttrName(
result.name),
1563 parser, LLVM::TailCallKind::None)));
1568 bool isDirect = operands.empty();
1581 StringAttr varCalleeTypeAttrName =
1582 CallOp::getVarCalleeTypeAttrName(
result.name);
1594 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1597 if (opBundleTags && !opBundleTags.empty())
1598 result.addAttribute(CallOp::getOpBundleTagsAttrName(
result.name).getValue(),
1608 argAttrs, resultAttrs))
1612 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1614 opBundleOperandTypes,
1615 getOpBundleSizesAttrName(
result.name)))
1618 int32_t numOpBundleOperands = 0;
1619 for (
const auto &operands : opBundleOperands)
1620 numOpBundleOperands += operands.size();
1623 CallOp::getOperandSegmentSizeAttr(),
1625 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
1629LLVMFunctionType CallOp::getCalleeFunctionType() {
1630 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1631 return *varCalleeType;
1642 auto calleeType =
func.getFunctionType();
1645 nullptr,
nullptr, normalOps, unwindOps,
1646 nullptr,
nullptr,
nullptr,
1647 nullptr, {}, {}, normal, unwind);
1654 build(builder, state, tys,
1655 nullptr, callee, ops,
nullptr,
1656 nullptr, normalOps, unwindOps,
nullptr,
nullptr,
1658 nullptr, {}, {}, normal, unwind);
1667 nullptr,
nullptr, normalOps, unwindOps,
1668 nullptr,
nullptr,
nullptr,
1669 nullptr, {}, {}, normal, unwind);
1673 assert(
index < getNumSuccessors() &&
"invalid successor index");
1675 : getUnwindDestOperandsMutable());
1683 return getOperand(0);
1689 auto symRef = cast<SymbolRefAttr>(callee);
1690 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1693 return setOperand(0, cast<Value>(callee));
1711LogicalResult InvokeOp::verify() {
1712 Block *unwindDest = getUnwindDest();
1713 if (unwindDest->
empty())
1714 return emitError(
"must have at least one operation in unwind destination");
1717 if (!isa<LandingpadOp>(unwindDest->
front()))
1718 return emitError(
"first operation in unwind destination should be a "
1719 "llvm.landingpad operation");
1728 auto callee = getCallee();
1729 bool isDirect = callee.has_value();
1734 if (getCConv() != LLVM::CConv::C)
1735 p << stringifyCConv(getCConv()) <<
' ';
1743 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1750 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1751 p <<
" vararg(" << *varCalleeType <<
")";
1753 if (!getOpBundleOperands().empty()) {
1756 getOpBundleOperands().getTypes(), getOpBundleTags());
1760 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1761 getCConvAttrName(), getVarCalleeTypeAttrName(),
1762 getOpBundleSizesAttrName(),
1763 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1764 getResAttrsAttrName()});
1768 p << getOperand(0).getType() <<
", ";
1770 p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
1772 false, getResultTypes(), getResAttrsAttr());
1785 SymbolRefAttr funcAttr;
1786 TypeAttr varCalleeType;
1790 Block *normalDest, *unwindDest;
1796 getCConvAttrName(
result.name),
1803 bool isDirect = operands.empty();
1819 StringAttr varCalleeTypeAttrName =
1820 InvokeOp::getVarCalleeTypeAttrName(
result.name);
1832 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1835 if (opBundleTags && !opBundleTags.empty())
1837 InvokeOp::getOpBundleTagsAttrName(
result.name).getValue(),
1847 argAttrs, resultAttrs))
1851 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1853 result.addSuccessors({normalDest, unwindDest});
1854 result.addOperands(normalOperands);
1855 result.addOperands(unwindOperands);
1858 opBundleOperandTypes,
1859 getOpBundleSizesAttrName(
result.name)))
1862 int32_t numOpBundleOperands = 0;
1863 for (
const auto &operands : opBundleOperands)
1864 numOpBundleOperands += operands.size();
1867 InvokeOp::getOperandSegmentSizeAttr(),
1869 static_cast<int32_t>(normalOperands.size()),
1870 static_cast<int32_t>(unwindOperands.size()),
1871 numOpBundleOperands}));
1875LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1876 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1877 return *varCalleeType;
1885LogicalResult LandingpadOp::verify() {
1887 if (LLVMFuncOp
func = (*this)->getParentOfType<LLVMFuncOp>()) {
1888 if (!
func.getPersonality())
1890 "llvm.landingpad needs to be in a function with a personality");
1896 if (!getCleanup() && getOperands().empty())
1897 return emitError(
"landingpad instruction expects at least one clause or "
1898 "cleanup attribute");
1901 value = getOperand(idx);
1902 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1909 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1912 <<
"global addresses expected as operand to "
1913 "bitcast used in clauses for landingpad";
1921 << idx <<
" is not a known constant - null, addressof, bitcast";
1928 p << (getCleanup() ?
" cleanup " :
" ");
1931 for (
auto value : getOperands()) {
1934 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1935 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1982 Type llvmType = containerType;
1984 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1992 for (
int64_t idx : position) {
1993 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1994 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1995 emitError(
"position out of bounds: ") << idx;
1998 llvmType = arrayType.getElementType();
1999 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
2001 static_cast<unsigned>(idx) >= structType.getBody().size()) {
2002 emitError(
"position out of bounds: ") << idx;
2005 llvmType = structType.getBody()[idx];
2007 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
2018 for (
int64_t idx : position) {
2019 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
2020 llvmType = structType.getBody()[idx];
2022 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
2034 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
2035 ShapedType shapedType = elementsAttr.getShapedType();
2036 if (!shapedType.hasRank() || shapedType.getRank() != 1)
2038 if (
index <
static_cast<size_t>(elementsAttr.getNumElements()))
2042 if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
2043 if (
index < arrayAttr.getValue().size())
2044 return arrayAttr[
index];
2047 if (isa<ZeroAttr, UndefAttr, PoisonAttr>(attr))
2052OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
2053 if (
auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
2055 newPos.append(getPosition().begin(), getPosition().end());
2056 setPosition(newPos);
2057 getContainerMutable().set(extractValueOp.getContainer());
2063 for (
int64_t pos : getPosition()) {
2068 return containerAttr;
2071 Value container = getContainer();
2073 while (
auto insertValueOp = container.
getDefiningOp<InsertValueOp>()) {
2075 auto extractPosSize = extractPos.size();
2076 auto insertPosSize = insertPos.size();
2079 if (extractPos == insertPos)
2080 return insertValueOp.getValue();
2094 if (extractPosSize > insertPosSize &&
2095 extractPos.take_front(insertPosSize) == insertPos) {
2096 container = insertValueOp.getValue();
2097 extractPos = extractPos.drop_front(insertPosSize);
2113 if (insertPosSize > extractPosSize &&
2114 extractPos == insertPos.take_front(extractPosSize))
2119 container = insertValueOp.getContainer();
2125 if (container == getContainer())
2127 setPosition(extractPos);
2128 getContainerMutable().assign(container);
2132LogicalResult ExtractValueOp::verify() {
2133 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
2139 if (getRes().
getType() != valueType)
2140 return emitOpError() <<
"Type mismatch: extracting from "
2141 << getContainer().getType() <<
" should produce "
2142 << valueType <<
" but this op returns "
2143 << getRes().getType();
2149 build(builder, state,
2188 LogicalResult matchAndRewrite(InsertValueOp insertOp,
2189 PatternRewriter &rewriter)
const override {
2190 bool changed =
false;
2196 auto insertBaseIdx = insertOp.getPosition()[0];
2197 for (
auto &use : insertOp->getUses()) {
2198 if (
auto extractOp = dyn_cast<ExtractValueOp>(use.getOwner())) {
2199 auto baseIdx = extractOp.getPosition()[0];
2202 if (baseIdx == insertBaseIdx)
2204 posToExtractOps[baseIdx].push_back(extractOp);
2209 Value nextContainer = insertOp.getContainer();
2210 while (!posToExtractOps.empty()) {
2212 dyn_cast_or_null<InsertValueOp>(nextContainer.
getDefiningOp());
2215 nextContainer = curInsert.getContainer();
2218 auto curInsertBaseIdx = curInsert.getPosition()[0];
2219 auto it = posToExtractOps.find(curInsertBaseIdx);
2220 if (it == posToExtractOps.end())
2224 for (
auto &extractOp : it->second) {
2226 extractOp.getContainerMutable().assign(curInsert);
2231 assert(!it->second.empty());
2233 posToExtractOps.erase(it);
2237 for (
auto &[baseIdx, extracts] : posToExtractOps) {
2238 for (
auto &extractOp : extracts) {
2240 extractOp.getContainerMutable().assign(nextContainer);
2243 assert(!extracts.empty() &&
"Empty list in map");
2253 patterns.
add<ResolveExtractValueSource>(context);
2261 [&](StringRef msg) {
2273LogicalResult InsertValueOp::verify() {
2274 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
2280 if (getValue().
getType() != valueType)
2281 return emitOpError() <<
"Type mismatch: cannot insert "
2282 << getValue().getType() <<
" into "
2283 << getContainer().getType();
2292LogicalResult ReturnOp::verify() {
2293 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2297 Type expectedType = parent.getFunctionType().getReturnType();
2298 if (llvm::isa<LLVMVoidType>(expectedType)) {
2302 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2306 if (llvm::isa<LLVMVoidType>(expectedType))
2309 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2312 if (expectedType != getArg().
getType()) {
2314 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2325 return dyn_cast_or_null<GlobalOp>(
2330 return dyn_cast_or_null<LLVMFuncOp>(
2335 return dyn_cast_or_null<AliasOp>(
2340 return dyn_cast_or_null<IFuncOp>(
2349 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2350 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2351 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2352 auto ifunc = dyn_cast_or_null<IFuncOp>(symbol);
2354 if (!global && !function && !alias && !ifunc)
2355 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2356 "'llvm.mlir.alias' or 'llvm.func' or 'llvm.mlir.ifunc'");
2358 LLVMPointerType type =
getType();
2359 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2360 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2361 return emitOpError(
"pointer address space must match address space of the "
2362 "referenced global or alias");
2369 return getGlobalNameAttr();
2390 getFunctionNameAttr());
2391 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2392 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2394 if (!function && !alias)
2396 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2399 if (alias.getInitializer()
2400 .walk([&](AddressOfOp addrOp) {
2401 if (addrOp.getGlobal(symbolTable))
2402 return WalkResult::interrupt();
2403 return WalkResult::advance();
2406 return emitOpError(
"must reference an alias to a function");
2409 if ((function && function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2410 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2412 "target function with 'extern_weak' linkage not allowed");
2420 return DSOLocalEquivalentAttr::get(
getContext(), getFunctionNameAttr());
2428 StringRef symName) {
2431 Region *body =
result.addRegion();
2435LogicalResult ComdatOp::verifyRegions() {
2436 Region &body = getBody();
2437 for (Operation &op : body.
getOps())
2438 if (!isa<ComdatSelectorOp>(op))
2439 return op.emitError(
2440 "only comdat selector symbols can appear in a comdat region");
2450 bool isConstant, Linkage linkage, StringRef name,
2451 Attribute value, uint64_t alignment,
unsigned addrSpace,
2452 bool dsoLocal, ThreadLocalMode threadModel,
2455 result.getOrAddProperties<Properties>().sym_name =
2457 result.addAttribute(getGlobalTypeAttrName(
result.name), TypeAttr::get(type));
2459 getTlsModeAttrName(
result.name),
2460 ThreadLocalModeAttr::get(builder.
getContext(), threadModel));
2465 result.addAttribute(getValueAttrName(
result.name), value);
2470 result.addAttribute(getComdatAttrName(
result.name), comdat);
2480 LinkageAttr::get(builder.
getContext(), linkage));
2484 result.attributes.append(attrs.begin(), attrs.end());
2486 if (!dbgExprs.empty())
2488 ArrayAttr::get(builder.
getContext(), dbgExprs));
2493template <
typename OpType>
2495 p <<
' ' << stringifyLinkage(op.getLinkage()) <<
' ';
2496 StringRef visibility = stringifyVisibility(op.getVisibility_());
2497 if (!visibility.empty())
2498 p << visibility <<
' ';
2500 if (ThreadLocalMode mode = op.getTlsMode();
2501 mode != ThreadLocalMode::NotThreadLocal) {
2502 p <<
"thread_local";
2503 if (mode != ThreadLocalMode::GeneralDynamic)
2504 p <<
'(' << mode <<
')';
2508 if (
auto unnamedAddr = op.getUnnamedAddr()) {
2509 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2521 if (
auto value = getValueOrNull())
2524 if (
auto comdat = getComdat())
2525 p <<
" comdat(" << *comdat <<
')';
2532 *
this, {getDsoLocalAttrName(), getExternallyInitializedAttrName(),
2533 getAlignmentAttrName(), getAddrSpaceAttrName(),
2534 getSectionAttrName(), getAssociatedAttrName(),
2535 getAbsoluteSymbolAttrName(), getDbgExprsAttrName(),
2536 getTargetSpecificAttrsAttrName(), getSymVisibilityAttrName()})
2538 {getSymNameAttrName(), getGlobalTypeAttrName(), getConstantAttrName(),
2539 getValueAttrName(), getLinkageAttrName(), getUnnamedAddrAttrName(),
2540 getTlsModeAttrName(), getVisibility_AttrName(), getComdatAttrName()});
2543 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2547 Region &initializer = getInitializerRegion();
2548 if (!initializer.
empty()) {
2555 std::optional<SymbolRefAttr> attr,
2561 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2562 return op->
emitError() <<
"expected comdat symbol";
2572 WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2573 if (blockTags.contains(blockTagOp.getTag())) {
2574 blockTagOp.emitError()
2575 <<
"duplicate block tag '" << blockTagOp.getTag().getId()
2576 <<
"' in the same function: ";
2579 blockTags.insert(blockTagOp.getTag());
2583 return failure(res.wasInterrupted());
2588template <
typename OpType>
2595 OpType::getLinkageAttrName(
result.name),
2597 parser, LLVM::Linkage::External)));
2600 result.addAttribute(OpType::getVisibility_AttrName(
result.name),
2603 parser, LLVM::Visibility::Default)));
2606 ThreadLocalMode threadModel = ThreadLocalMode::GeneralDynamic;
2613 parser, ThreadLocalMode::NotThreadLocal);
2614 if (threadModel == ThreadLocalMode::NotThreadLocal) {
2615 parser.
emitError(kwLoc,
"invalid value for thread_local");
2621 result.addAttribute(OpType::getTlsModeAttrName(
result.name),
2622 ThreadLocalModeAttr::get(ctx, threadModel));
2626 result.addAttribute(OpType::getUnnamedAddrAttrName(
result.name),
2629 parser, LLVM::UnnamedAddr::None)));
2667 SymbolRefAttr comdat;
2672 result.addAttribute(getComdatAttrName(
result.name), comdat);
2680 if (types.size() > 1)
2684 if (types.empty()) {
2685 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2687 auto arrayType = LLVM::LLVMArrayType::get(IntegerType::get(context, 8),
2688 strAttr.getValue().size());
2689 types.push_back(arrayType);
2692 "type can only be omitted for string globals");
2702 result.addAttribute(getGlobalTypeAttrName(
result.name),
2703 TypeAttr::get(types[0]));
2708 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2709 return intValue.getValue().isZero();
2710 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2711 return fpValue.getValue().isZero();
2712 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2714 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2716 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2725LogicalResult GlobalOp::verify() {
2727 ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
2729 :
llvm::isa<PointerElementTypeInterface>(
getType());
2732 "expects type to be a valid element type for an LLVM global");
2734 return emitOpError(
"must appear at the module level");
2736 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2737 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2738 IntegerType elementType =
2739 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) :
nullptr;
2740 if (!elementType || elementType.getWidth() != 8 ||
2741 type.getNumElements() != strAttr.getValue().size())
2743 "requires an i8 array type of the length equal to that of the string "
2747 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2748 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2749 return emitOpError()
2750 <<
"this target extension type cannot be used in a global";
2753 return emitOpError() <<
"global with target extension type can only be "
2754 "initialized with zero-initializer";
2757 if (getLinkage() == Linkage::Common) {
2758 if (
Attribute value = getValueOrNull()) {
2760 return emitOpError()
2761 <<
"expected zero value for '"
2762 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2767 if (getLinkage() == Linkage::Appending) {
2768 if (!llvm::isa<LLVMArrayType>(
getType())) {
2769 return emitOpError() <<
"expected array type for '"
2770 << stringifyLinkage(Linkage::Appending)
2775 std::optional<uint64_t> alignAttr = getAlignment();
2776 if (alignAttr.has_value()) {
2777 uint64_t value = alignAttr.value();
2778 if (!llvm::isPowerOf2_64(value))
2779 return emitError() <<
"alignment attribute is not a power of 2";
2783 if (associated.getValue() == getSymName())
2784 return emitOpError(
"associated cannot refer to the global itself");
2787 if (
ArrayAttr absSym = getAbsoluteSymbolAttr()) {
2788 if (absSym.empty() || absSym.size() % 2 != 0)
2790 "absolute_symbol must contain one or more integer range pairs");
2793 auto intAttr = dyn_cast<IntegerAttr>(attr);
2795 return emitOpError(
"absolute_symbol operands must be integers");
2797 pairType = intAttr.getType();
2798 else if (intAttr.getType() != pairType)
2799 return emitOpError(
"absolute_symbol range pair types must match");
2806LogicalResult GlobalOp::verifyRegions() {
2807 if (
Block *
b = getInitializerBlock()) {
2808 ReturnOp ret = cast<ReturnOp>(
b->getTerminator());
2809 if (ret.operand_type_begin() == ret.operand_type_end())
2810 return emitOpError(
"initializer region cannot return void");
2811 if (*ret.operand_type_begin() !=
getType())
2812 return emitOpError(
"initializer region type ")
2813 << *ret.operand_type_begin() <<
" does not match global type "
2817 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2818 if (!iface || !iface.hasNoEffect())
2819 return op.emitError()
2820 <<
"ops with side effects not allowed in global initializers";
2823 if (getValueOrNull())
2824 return emitOpError(
"cannot have both initializer value and region");
2839 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2842 return op->
emitError(
"data element must be symbol or #llvm.zero");
2855LogicalResult GlobalCtorsOp::verify() {
2859 if (getCtors().size() == getPriorities().size() &&
2860 getCtors().size() == getData().size())
2863 "ctors, priorities, and data must have the same number of elements");
2880LogicalResult GlobalDtorsOp::verify() {
2884 if (getDtors().size() == getPriorities().size() &&
2885 getDtors().size() == getData().size())
2888 "dtors, priorities, and data must have the same number of elements");
2896 Linkage linkage, StringRef name,
bool dsoLocal,
2897 ThreadLocalMode threadModel,
2901 result.addAttribute(getAliasTypeAttrName(
result.name), TypeAttr::get(type));
2903 getTlsModeAttrName(
result.name),
2904 ThreadLocalModeAttr::get(builder.
getContext(), threadModel));
2910 LinkageAttr::get(builder.
getContext(), linkage));
2911 result.attributes.append(attrs.begin(), attrs.end());
2922 {getDsoLocalAttrName(), getSymVisibilityAttrName()})
2924 {getSymNameAttrName(), getAliasTypeAttrName(), getLinkageAttrName(),
2925 getUnnamedAddrAttrName(), getTlsModeAttrName(),
2926 getVisibility_AttrName()});
2929 p <<
" : " <<
getType() <<
' ';
2955 if (types.size() > 1)
2963 TypeAttr::get(types[0]));
2967LogicalResult AliasOp::verify() {
2969 ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
2971 :
llvm::isa<PointerElementTypeInterface>(
getType());
2974 "expects type to be a valid element type for an LLVM global alias");
2977 switch (getLinkage()) {
2978 case Linkage::External:
2979 case Linkage::Internal:
2980 case Linkage::Private:
2982 case Linkage::WeakODR:
2983 case Linkage::Linkonce:
2984 case Linkage::LinkonceODR:
2985 case Linkage::AvailableExternally:
2988 return emitOpError()
2989 <<
"'" << stringifyLinkage(getLinkage())
2990 <<
"' linkage not supported in aliases, available options: private, "
2991 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2992 "available_externally";
2998LogicalResult AliasOp::verifyRegions() {
2999 Block &
b = getInitializerBlock();
3000 auto ret = cast<ReturnOp>(
b.getTerminator());
3001 if (ret.getNumOperands() == 0 ||
3002 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
3003 return emitOpError(
"initializer region must always return a pointer");
3006 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
3007 if (!iface || !iface.hasNoEffect())
3008 return op.emitError()
3009 <<
"ops with side effects are not allowed in alias initializers";
3015unsigned AliasOp::getAddrSpace() {
3016 Block &initializer = getInitializerBlock();
3018 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
3019 return ptrTy.getAddressSpace();
3027 Type iFuncType, StringRef resolverName,
Type resolverType,
3028 Linkage linkage, LLVM::Visibility visibility) {
3029 return build(builder,
result, name, iFuncType, resolverName, resolverType,
3031 UnnamedAddr::None, visibility,
nullptr);
3038 auto resolver = dyn_cast<LLVMFuncOp>(symbol);
3039 auto alias = dyn_cast<AliasOp>(symbol);
3041 Block &initBlock = alias.getInitializerBlock();
3043 auto addrOp = returnOp.getArg().getDefiningOp<AddressOfOp>();
3050 resolver = addrOp.getFunction(symbolTable);
3051 alias = addrOp.getAlias(symbolTable);
3054 return emitOpError(
"must have a function resolver");
3055 Linkage linkage = resolver.getLinkage();
3056 if (resolver.isExternal() || linkage == Linkage::AvailableExternally)
3057 return emitOpError(
"resolver must be a definition");
3058 if (!isa<LLVMPointerType>(resolver.getFunctionType().getReturnType()))
3059 return emitOpError(
"resolver must return a pointer");
3060 auto resolverPtr = dyn_cast<LLVMPointerType>(getResolverType());
3061 if (!resolverPtr || resolverPtr.getAddressSpace() != getAddressSpace())
3062 return emitOpError(
"resolver has incorrect type");
3066LogicalResult IFuncOp::verify() {
3067 switch (getLinkage()) {
3068 case Linkage::External:
3069 case Linkage::Internal:
3070 case Linkage::Private:
3072 case Linkage::WeakODR:
3073 case Linkage::Linkonce:
3074 case Linkage::LinkonceODR:
3077 return emitOpError() <<
"'" << stringifyLinkage(getLinkage())
3078 <<
"' linkage not supported in ifuncs, available "
3079 "options: private, internal, linkonce, weak, "
3080 "linkonce_odr, weak_odr, or external linkage";
3092 auto containerType = v1.
getType();
3096 build(builder, state, vType, v1, v2, mask);
3111 "expected an LLVM compatible vector type");
3123LogicalResult ShuffleVectorOp::verify() {
3125 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
3126 return emitOpError(
"expected a splat operation for scalable vectors");
3132OpFoldResult ShuffleVectorOp::fold(FoldAdaptor adaptor) {
3134 auto vecType = llvm::dyn_cast<VectorType>(getV1().
getType());
3135 if (!vecType || vecType.getRank() != 1 || vecType.getNumElements() != 1)
3139 if (getMask().size() != 1 || getMask()[0] != 0)
3150 assert(empty() &&
"function already has an entry block");
3155 LLVMFunctionType type = getFunctionType();
3156 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
3157 entry->
addArgument(type.getParamType(i), getLoc());
3162 StringRef name,
Type type, LLVM::Linkage linkage,
3163 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
3166 std::optional<uint64_t> functionEntryCount) {
3170 result.addAttribute(getFunctionTypeAttrName(
result.name),
3171 TypeAttr::get(type));
3173 LinkageAttr::get(builder.
getContext(), linkage));
3175 CConvAttr::get(builder.
getContext(), cconv));
3176 result.attributes.append(attrs.begin(), attrs.end());
3181 result.addAttribute(getComdatAttrName(
result.name), comdat);
3182 if (functionEntryCount)
3183 result.addAttribute(getFunctionEntryCountAttrName(
result.name),
3184 FunctionEntryCountAttr::get(builder.
getContext(),
3185 *functionEntryCount,
3188 std::optional<NamedAttribute> duplicate =
result.attributes.findDuplicate();
3189 if (duplicate.has_value()) {
3190 llvm::report_fatal_error(
3191 Twine(
"LLVMFuncOp propagated an attribute that is meant "
3192 "to be constructed by the builder: ") +
3193 duplicate->getName().str());
3196 if (argAttrs.empty())
3199 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
3200 "expected as many argument attribute lists as arguments");
3202 builder,
result, argAttrs, {},
3203 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3214 if (outputs.size() > 1) {
3215 parser.
emitError(loc,
"failed to construct function type: expected zero or "
3216 "one function result");
3222 for (
auto t : inputs) {
3224 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3225 "type for function arguments");
3228 llvmInputs.push_back(t);
3233 outputs.empty() ? LLVMVoidType::get(
b.getContext()) : outputs.front();
3235 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3236 "type for function results")
3240 return LLVMFunctionType::get(llvmOutput, llvmInputs,
3256 parser, LLVM::Linkage::External)));
3259 result.addAttribute(getVisibility_AttrName(
result.name),
3262 parser, LLVM::Visibility::Default)));
3265 result.addAttribute(getUnnamedAddrAttrName(
result.name),
3268 parser, LLVM::UnnamedAddr::None)));
3272 getCConvAttrName(
result.name),
3276 StringAttr nameAttr;
3286 parser,
true, entryArgs, isVariadic, resultTypes,
3291 for (
auto &arg : entryArgs)
3292 argTypes.push_back(arg.type);
3298 result.addAttribute(getFunctionTypeAttrName(
result.name),
3299 TypeAttr::get(type));
3307 auto intTy = IntegerType::get(parser.
getContext(), 32);
3309 getVscaleRangeAttrName(
result.name),
3310 LLVM::VScaleRangeAttr::get(parser.
getContext(),
3311 IntegerAttr::get(intTy, minRange),
3312 IntegerAttr::get(intTy, maxRange)));
3316 SymbolRefAttr comdat;
3321 result.addAttribute(getComdatAttrName(
result.name), comdat);
3328 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3330 auto *body =
result.addRegion();
3341 if (getLinkage() != LLVM::Linkage::External)
3342 p << stringifyLinkage(getLinkage()) <<
' ';
3343 StringRef visibility = stringifyVisibility(getVisibility_());
3344 if (!visibility.empty())
3345 p << visibility <<
' ';
3346 if (
auto unnamedAddr = getUnnamedAddr()) {
3347 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
3351 if (getCConv() != LLVM::CConv::C)
3352 p << stringifyCConv(getCConv()) <<
' ';
3356 LLVMFunctionType fnType = getFunctionType();
3359 argTypes.reserve(fnType.getNumParams());
3360 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
3361 argTypes.push_back(fnType.getParamType(i));
3363 Type returnType = fnType.getReturnType();
3364 if (!llvm::isa<LLVMVoidType>(returnType))
3365 resTypes.push_back(returnType);
3368 isVarArg(), resTypes);
3371 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
3372 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
3373 << vscale->getMaxRange().getInt() <<
')';
3376 if (
auto comdat = getComdat())
3377 p <<
" comdat(" << *comdat <<
')';
3381 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
3382 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
3383 getComdatAttrName(), getUnnamedAddrAttrName(),
3384 getVscaleRangeAttrName()});
3387 Region &body = getBody();
3388 if (!body.empty()) {
3403LogicalResult LLVMFuncOp::verify() {
3404 if (getLinkage() == LLVM::Linkage::Common)
3405 return emitOpError() <<
"functions cannot have '"
3406 << stringifyLinkage(LLVM::Linkage::Common)
3410 if (getFunctionEntryCountAttr())
3411 return emitOpError() <<
"external functions cannot have "
3412 << getFunctionEntryCountAttrName() <<
" attribute";
3414 if (getLinkage() != LLVM::Linkage::External &&
3415 getLinkage() != LLVM::Linkage::ExternWeak)
3416 return emitOpError() <<
"external functions must have '"
3417 << stringifyLinkage(LLVM::Linkage::External)
3419 << stringifyLinkage(LLVM::Linkage::ExternWeak)
3425 if (isNoInline() && isAlwaysInline())
3426 return emitError(
"no_inline and always_inline attributes are incompatible");
3428 if (isOptimizeNone() && !isNoInline())
3429 return emitOpError(
"with optimize_none must also be no_inline");
3431 Type landingpadResultTy;
3432 StringRef diagnosticMessage;
3433 bool isLandingpadTypeConsistent =
3435 const auto checkType = [&](
Type type, StringRef errorMessage) {
3436 if (!landingpadResultTy) {
3437 landingpadResultTy = type;
3440 if (landingpadResultTy != type) {
3441 diagnosticMessage = errorMessage;
3447 .Case([&](LandingpadOp landingpad) {
3448 constexpr StringLiteral errorMessage =
3449 "'llvm.landingpad' should have a consistent result type "
3450 "inside a function";
3451 return checkType(landingpad.getType(), errorMessage);
3453 .Case([&](ResumeOp resume) {
3454 constexpr StringLiteral errorMessage =
3455 "'llvm.resume' should have a consistent input type inside a "
3457 return checkType(resume.getValue().getType(), errorMessage);
3460 }).wasInterrupted();
3461 if (!isLandingpadTypeConsistent) {
3462 assert(!diagnosticMessage.empty() &&
3463 "Expecting a non-empty diagnostic message");
3475LogicalResult LLVMFuncOp::verifyRegions() {
3479 unsigned numArguments = getFunctionType().getNumParams();
3480 Block &entryBlock = front();
3481 for (
unsigned i = 0; i < numArguments; ++i) {
3484 return emitOpError(
"entry block argument #")
3485 << i <<
" is not of LLVM type";
3491Region *LLVMFuncOp::getCallableRegion() {
3520OpFoldResult LLVM::MetadataAsValueOp::fold(FoldAdaptor) {
3521 return getMetadataAttr();
3528LogicalResult LLVM::ZeroOp::verify() {
3529 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3530 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3531 return emitOpError()
3532 <<
"target extension type does not support zero-initializer";
3554 if (
auto vecType = dyn_cast<VectorType>(t)) {
3555 assert(!vecType.isScalable() &&
3556 "number of elements of a scalable vector type is unknown");
3557 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3559 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3560 return arrayType.getNumElements() *
3568 while (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(type))
3569 type = arrayType.getElementType();
3570 if (
auto vecType = dyn_cast<VectorType>(type))
3571 return vecType.getElementType();
3572 if (
auto tenType = dyn_cast<TensorType>(type))
3573 return tenType.getElementType();
3580 if (
auto vecType = dyn_cast<VectorType>(t)) {
3581 if (vecType.isScalable())
3585 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3593 LLVM::LLVMArrayType arrayType,
3595 if (arrayType.getNumElements() != arrayAttr.size())
3596 return op.emitOpError()
3597 <<
"array attribute size does not match array type size in "
3599 << dim <<
": " << arrayAttr.size() <<
" vs. "
3600 << arrayType.getNumElements();
3605 if (
auto subArrayType =
3606 dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
3607 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr))
3608 if (elementsVerified.insert(elementAttr).second) {
3609 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3611 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3613 return op.emitOpError()
3614 <<
"nested attribute for sub-array in dimension " << dim
3615 <<
" at index " << idx
3616 <<
" must be a zero, or undef, or array attribute";
3630 Type elementType = arrayType.getElementType();
3631 if (isa<LLVM::LLVMPointerType>(elementType)) {
3632 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3634 LLVM::PoisonAttr>(elementAttr))
3636 return op.emitOpError()
3637 <<
"pointer array element at index " << idx
3638 <<
" must be a flat symbol reference, zero, undef, or poison";
3642 auto structType = dyn_cast<LLVM::LLVMStructType>(elementType);
3644 return op.emitOpError() <<
"for array with an array attribute must have a "
3645 "struct element type";
3649 size_t numStructElements = structType.getBody().size();
3650 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3651 if (elementsVerified.insert(elementAttr).second) {
3652 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3654 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3656 return op.emitOpError()
3657 <<
"nested attribute for struct element at index " << idx
3658 <<
" must be a zero, or undef, or array attribute";
3659 if (subArrayAttr.size() != numStructElements)
3660 return op.emitOpError()
3661 <<
"nested array attribute size for struct element at index "
3662 << idx <<
" must match struct size: " << subArrayAttr.size()
3663 <<
" vs. " << numStructElements;
3670LogicalResult LLVM::ConstantOp::verify() {
3671 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3672 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3673 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3674 !arrayType.getElementType().isInteger(8)) {
3675 return emitOpError() <<
"expected array type of "
3676 << sAttr.getValue().size()
3677 <<
" i8 elements for the string constant";
3681 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3682 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3684 return emitOpError() <<
"expected array attribute for struct type";
3687 if (arrayAttr.size() != elementTypes.size()) {
3688 return emitOpError() <<
"expected array attribute of size "
3689 << elementTypes.size();
3691 for (
auto [i, attr, type] : llvm::enumerate(arrayAttr, elementTypes)) {
3693 return emitOpError() <<
"expected struct element types to be floating "
3694 "point type or integer type";
3696 if (!isa<FloatAttr, IntegerAttr>(attr)) {
3697 return emitOpError() <<
"expected element of array attribute to be "
3698 "floating point or integer";
3700 if (cast<TypedAttr>(attr).
getType() != type)
3701 return emitOpError()
3702 <<
"struct element at index " << i <<
" is of wrong type";
3707 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3708 return emitOpError() <<
"does not support target extension type.";
3719 auto verifyFloatSemantics =
3720 [
this](
const llvm::fltSemantics &attributeFloatSemantics,
3721 Type constantElementType) -> LogicalResult {
3722 if (
auto floatType = dyn_cast<FloatType>(constantElementType)) {
3723 if (&floatType.getFloatSemantics() != &attributeFloatSemantics) {
3724 return emitOpError()
3725 <<
"attribute and type have different float semantics";
3729 unsigned floatWidth = APFloat::getSizeInBits(attributeFloatSemantics);
3730 if (isa<IntegerType>(constantElementType)) {
3731 if (!constantElementType.isInteger(floatWidth))
3732 return emitOpError() <<
"expected integer type of width " << floatWidth;
3747 auto verifyIntegerSemantics = [
this](
Type attributeIntType,
3748 Type constantElementType,
3749 StringRef description) -> LogicalResult {
3750 if (attributeIntType != constantElementType)
3751 return emitOpError() <<
"attribute and type have different integer "
3752 << description <<
"s: " << attributeIntType
3753 <<
" vs. " << constantElementType;
3758 if (
auto intAttr = dyn_cast<IntegerAttr>(getValue())) {
3759 if (!llvm::isa<IntegerType>(
getType()))
3760 return emitOpError() <<
"expected integer type";
3761 return verifyIntegerSemantics(intAttr.getType(),
getType(),
"type");
3762 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3763 return verifyFloatSemantics(floatAttr.getValue().getSemantics(),
getType());
3764 }
else if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
3768 auto verifyElementTypes = [&](ElementsAttr attr) -> LogicalResult {
3771 if (
auto floatType = dyn_cast<FloatType>(attrElmType))
3772 return verifyFloatSemantics(floatType.getFloatSemantics(),
3775 if (isa<IntegerType, IndexType>(attrElmType)) {
3776 if (!isa<IntegerType>(resultElmType))
3778 "expected integer element type for integer elements attribute");
3779 return verifyIntegerSemantics(attrElmType, resultElmType,
3788 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3789 if (!splatElementsAttr)
3790 return emitOpError()
3791 <<
"scalable vector type requires a splat attribute";
3792 return verifyElementTypes(splatElementsAttr);
3794 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3795 return emitOpError() <<
"expected vector or array type";
3798 int64_t attrNumElements = elementsAttr.getNumElements();
3800 return emitOpError()
3801 <<
"type and attribute have a different number of elements: "
3805 return verifyElementTypes(elementsAttr);
3806 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {
3809 auto arrayType = dyn_cast<LLVM::LLVMArrayType>(
getType());
3811 return emitOpError()
3812 <<
"expected array or struct type for array attribute";
3818 return emitOpError()
3819 <<
"only supports integer, float, string or elements attributes";
3823bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3825 auto typedAttr = dyn_cast<TypedAttr>(value);
3832 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3837 if (isBuildableWith(value, type))
3838 return LLVM::ConstantOp::create(builder, loc, cast<TypedAttr>(value));
3843OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3851 AtomicOrdering ordering, StringRef syncscope,
3852 unsigned alignment,
bool isVolatile,
3853 bool ignoreDenormalMode) {
3854 build(builder, state, val.
getType(), binOp,
ptr, val, ordering,
3855 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3859 nullptr,
nullptr,
nullptr);
3862LogicalResult AtomicRMWOp::verify() {
3863 auto valType = getVal().getType();
3864 if (isFloatingPointOperation()) {
3867 return emitOpError(
"expected LLVM IR fixed vector type");
3868 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3871 "expected LLVM IR floating point type for vector element");
3873 return emitOpError(
"expected LLVM IR floating point type");
3875 }
else if (getBinOp() == AtomicBinOp::xchg) {
3878 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3880 auto intType = llvm::dyn_cast<IntegerType>(valType);
3881 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3882 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3884 return emitOpError(
"expected LLVM IR integer type");
3887 if (getIgnoreDenormalMode() && !isFloatingPointOperation())
3889 "expected floating-point operation with 'ignore_denormal_mode'");
3891 if (
static_cast<unsigned>(getOrdering()) <
3892 static_cast<unsigned>(AtomicOrdering::monotonic))
3893 return emitOpError() <<
"expected at least '"
3894 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3906 auto boolType = IntegerType::get(valType.
getContext(), 1);
3907 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3912 AtomicOrdering successOrdering,
3913 AtomicOrdering failureOrdering, StringRef syncscope,
3914 unsigned alignment,
bool isWeak,
bool isVolatile) {
3916 successOrdering, failureOrdering,
3917 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3919 isVolatile,
nullptr,
3920 nullptr,
nullptr,
nullptr);
3923LogicalResult AtomicCmpXchgOp::verify() {
3924 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3926 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3927 auto valType = getVal().getType();
3930 return emitOpError(
"unexpected LLVM IR type");
3931 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3932 getFailureOrdering() < AtomicOrdering::monotonic)
3933 return emitOpError(
"ordering must be at least 'monotonic'");
3934 if (getFailureOrdering() == AtomicOrdering::release ||
3935 getFailureOrdering() == AtomicOrdering::acq_rel)
3936 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3945 AtomicOrdering ordering, StringRef syncscope) {
3946 build(builder, state, ordering,
3947 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3950LogicalResult FenceOp::verify() {
3951 if (getOrdering() == AtomicOrdering::not_atomic ||
3952 getOrdering() == AtomicOrdering::unordered ||
3953 getOrdering() == AtomicOrdering::monotonic)
3954 return emitOpError(
"can be given only acquire, release, acq_rel, "
3955 "and seq_cst orderings");
3965template <
class ExtOp>
3967 IntegerType inputType, outputType;
3970 return op.emitError(
3971 "input type is a vector but output type is an integer");
3974 return op.emitError(
"input and output vectors are of incompatible shape");
3977 inputType = cast<IntegerType>(
3978 cast<VectorType>(op.getArg().getType()).getElementType());
3979 outputType = cast<IntegerType>(
3980 cast<VectorType>(op.getResult().getType()).getElementType());
3984 inputType = cast<IntegerType>(op.getArg().getType());
3985 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3987 return op.emitError(
3988 "input type is an integer but output type is a vector");
3991 if (outputType.getWidth() <= inputType.getWidth())
3992 return op.emitError(
"integer width of the output type is smaller or "
3993 "equal to the integer width of the input type");
4004 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
4008 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
4009 return IntegerAttr::get(
getType(), arg.getValue().zext(targetSize));
4023template <
typename T>
4025 typename T::FoldAdaptor adaptor) {
4027 if (castOp.getArg().getType() == castOp.getType())
4028 return castOp.getArg();
4029 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
4031 if (prev.getArg().getType() == castOp.getType())
4032 return prev.getArg();
4034 castOp.getArgMutable().set(prev.getArg());
4035 return Value{castOp};
4040OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
4044LogicalResult LLVM::BitcastOp::verify() {
4050 if (isa<LLVMByteType>(srcElemType) || isa<LLVMByteType>(dstElemType))
4053 auto resultType = llvm::dyn_cast<LLVMPointerType>(dstElemType);
4054 auto sourceType = llvm::dyn_cast<LLVMPointerType>(srcElemType);
4058 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
4059 return emitOpError(
"can only cast pointers from and to pointers");
4064 auto isVector = llvm::IsaPred<VectorType>;
4068 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
4069 return emitOpError(
"cannot cast pointer to vector of pointers");
4071 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
4072 return emitOpError(
"cannot cast vector of pointers to pointer");
4076 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
4077 return emitOpError(
"cannot cast pointers of different address spaces, "
4078 "use 'llvm.addrspacecast' instead");
4083LogicalResult LLVM::PtrToAddrOp::verify() {
4090 assert(width &&
"pointers always return an index bitwidth");
4091 if (width != integerType.getWidth())
4092 return emitOpError(
"bit-width of integer result type ")
4093 << integerType <<
" must match the pointer bitwidth (" << *width
4094 <<
") specified in the datalayout";
4103OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
4107Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
4115 adaptor.getDynamicIndices());
4118 if (getInrangeAttr())
4123 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(
indices[0]))
4124 if (integer.getValue().isZero())
4128 bool changed =
false;
4130 for (
auto iter : llvm::enumerate(
indices)) {
4131 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
4134 if (!
indices.isDynamicIndex(iter.index()) || !integer ||
4138 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
4139 gepArgs.emplace_back(val);
4141 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
4147 gepArgs.emplace_back(integer.getInt());
4155 getDynamicIndicesMutable().assign(dynamicIndices);
4156 setRawConstantIndices(rawConstantIndices);
4157 return Value{*
this};
4163Value LLVM::GEPOp::getViewSource() {
return getBase(); }
4170 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
4174 if (rhs.getValue().uge(getLhs().
getType().getIntOrFloatBitWidth()))
4177 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
4181 return IntegerAttr::get(
getType(), lhs.getValue().shl(rhs.getValue()));
4189 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
4193 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
4197 return IntegerAttr::get(
getType(), lhs.getValue() | rhs.getValue());
4204LogicalResult CallIntrinsicOp::verify() {
4205 if (!getIntrin().starts_with(
"llvm."))
4206 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
4214 build(builder, state,
TypeRange{}, intrin, args,
4215 FastmathFlagsAttr{},
4222 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4223 build(builder, state,
TypeRange{}, intrin, args,
4230 mlir::Type resultType, mlir::StringAttr intrin,
4232 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
4240 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4241 build(builder, state, resultTypes, intrin, args, fastMathFlags,
4246ParseResult CallIntrinsicOp::parse(
OpAsmParser &parser,
4248 StringAttr intrinAttr;
4258 result.addAttribute(CallIntrinsicOp::getIntrinAttrName(
result.name),
4266 return mlir::failure();
4269 return mlir::failure();
4274 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
4277 if (opBundleTags && !opBundleTags.empty())
4279 CallIntrinsicOp::getOpBundleTagsAttrName(
result.name).getValue(),
4283 return mlir::failure();
4288 operands, argAttrs, resultAttrs))
4292 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
4295 opBundleOperandTypes,
4296 getOpBundleSizesAttrName(
result.name)))
4299 int32_t numOpBundleOperands = 0;
4300 for (
const auto &operands : opBundleOperands)
4301 numOpBundleOperands += operands.size();
4304 CallIntrinsicOp::getOperandSegmentSizeAttr(),
4306 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
4308 return mlir::success();
4316 p <<
"(" << args <<
")";
4319 if (!getOpBundleOperands().empty()) {
4322 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
4326 {getOperandSegmentSizesAttrName(),
4327 getOpBundleSizesAttrName(), getIntrinAttrName(),
4328 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
4329 getResAttrsAttrName()});
4335 p, args.
getTypes(), getArgAttrsAttr(),
4336 false, getResultTypes(), getResAttrsAttr());
4343LogicalResult LinkerOptionsOp::verify() {
4346 return emitOpError(
"must appear at the module level");
4354LogicalResult ModuleFlagsOp::verify() {
4357 return emitOpError(
"must appear at the module level");
4361 auto moduleFlag = dyn_cast<ModuleFlagAttrInterface>(flag);
4363 return emitOpError(
"expected a module flag attribute");
4365 moduleFlag.getModuleFlagKey(), moduleFlag.getModuleFlagValue(),
4366 [&] { return emitOpError(); })))
4368 if (moduleFlag.getModuleFlagBehavior() == ModFlagBehavior::Require)
4370 StringAttr key = moduleFlag.getModuleFlagKey();
4371 if (!seenNonRequireKeys.insert(key).second)
4372 return emitOpError(
"expected module flag key '")
4373 << key.getValue() <<
"' to be unique for non-require flags";
4382void InlineAsmOp::getEffects(
4385 if (getHasSideEffects()) {
4398 getBlockAddr().getFunction());
4399 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
4402 return emitOpError(
"must reference a function defined by 'llvm.func'");
4412BlockTagOp BlockAddressOp::getBlockTagOp() {
4417 auto funcOp = dyn_cast<LLVMFuncOp>(sym);
4420 BlockTagOp blockTagOp =
nullptr;
4421 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
4422 if (labelOp.getTag() == getBlockAddr().getTag()) {
4423 blockTagOp = labelOp;
4431LogicalResult BlockAddressOp::verify() {
4432 if (!getBlockTagOp())
4434 "expects an existing block label target in the referenced function");
4441OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
4448 assert(
index < getNumSuccessors() &&
"invalid successor index");
4460 rangeSegments.push_back(range.size());
4474 Block *destination = nullptr;
4475 SmallVector<OpAsmParser::UnresolvedOperand> operands;
4476 SmallVector<Type> operandTypes;
4478 if (parser.parseSuccessor(destination).failed())
4481 if (succeeded(parser.parseOptionalLParen())) {
4482 if (failed(parser.parseOperandList(
4483 operands, OpAsmParser::Delimiter::None)) ||
4484 failed(parser.parseColonTypeList(operandTypes)) ||
4485 failed(parser.parseRParen()))
4488 succOperandBlocks.push_back(destination);
4489 succOperands.emplace_back(operands);
4490 succOperandsTypes.emplace_back(operandTypes);
4493 "successor blocks")))
4503 llvm::zip(succs, succOperands),
4509 if (!succOperands.empty())
4521 auto resultStructType =
4522 mlir::dyn_cast<mlir::LLVM::LLVMStructType>(resultType);
4523 if (!resultStructType || resultStructType.getBody().size() != 2 ||
4524 resultStructType.getBody()[0] != operandType ||
4525 resultStructType.getBody()[1] != operandType) {
4527 "expected result type to be a homogeneous struct with "
4528 "two elements matching the operand type, but got ")
4534LogicalResult LLVM::SincosOp::verify() {
4539LogicalResult LLVM::ModfOp::verify() {
4550 return build(builder, state, cond, {},
4562 return build(builder, state, cond,
"align",
ValueRange{
ptr, align});
4568 return build(builder, state, cond,
"separate_storage",
4578LogicalResult LLVM::masked_gather::verify() {
4579 auto ptrsVectorType = getPtrs().getType();
4580 Type expectedPtrsVectorType =
4585 if (ptrsVectorType != expectedPtrsVectorType)
4586 return emitOpError(
"expected operand #1 type to be ")
4587 << expectedPtrsVectorType;
4595LogicalResult LLVM::masked_scatter::verify() {
4596 auto ptrsVectorType = getPtrs().getType();
4597 Type expectedPtrsVectorType =
4602 if (ptrsVectorType != expectedPtrsVectorType)
4603 return emitOpError(
"expected operand #2 type to be ")
4604 << expectedPtrsVectorType;
4617 build(builder, state, resTys,
ptr, mask, passthru, argAttrs,
4625void LLVM::masked_compressstore::build(
OpBuilder &builder,
4630 build(builder, state, value,
ptr, mask, argAttrs,
4638LogicalResult InlineAsmOp::verify() {
4639 if (!getTailCallKindAttr())
4642 if (getTailCallKindAttr().getTailCallKind() == TailCallKind::MustTail)
4644 "tail call kind 'musttail' is not supported by this operation");
4654 Value divisor = getRhs();
4669 Value divisor = getRhs();
4681void LLVMDialect::initialize() {
4682 registerAttributes();
4685 addTypes<LLVMVoidType,
4687 LLVMMetadataType>();
4691 registerLLVMDialectOperations(
this);
4694 allowUnknownOperations();
4695 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4699LogicalResult LLVMDialect::verifyDataLayoutString(
4702 llvm::DataLayout::parse(descr);
4703 if (maybeDataLayout)
4706 std::string message;
4707 llvm::raw_string_ostream messageStream(message);
4708 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4709 reportError(
"invalid data layout descriptor: " + message);
4714LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
4720 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4722 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
4723 return verifyDataLayoutString(
4724 stringAttr.getValue(),
4725 [op](
const Twine &message) { op->emitOpError() << message.str(); });
4728 << LLVM::LLVMDialect::getDataLayoutAttrName()
4729 <<
"' to be a string attributes";
4732LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
4740 StringAttr name = paramAttr.
getName();
4742 auto checkUnitAttrType = [&]() -> LogicalResult {
4743 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
4744 return op->
emitError() << name <<
" should be a unit attribute";
4747 auto checkTypeAttrType = [&]() -> LogicalResult {
4748 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
4749 return op->
emitError() << name <<
" should be a type attribute";
4752 auto checkIntegerAttrType = [&]() -> LogicalResult {
4753 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
4754 return op->
emitError() << name <<
" should be an integer attribute";
4757 auto checkPointerType = [&]() -> LogicalResult {
4758 if (!llvm::isa<LLVMPointerType>(paramType))
4760 << name <<
" attribute attached to non-pointer LLVM type";
4763 auto checkIntegerType = [&]() -> LogicalResult {
4764 if (!llvm::isa<IntegerType>(paramType))
4766 << name <<
" attribute attached to non-integer LLVM type";
4769 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4770 if (
failed(checkPointerType()))
4777 if (name == LLVMDialect::getNoAliasAttrName() ||
4778 name == LLVMDialect::getReadonlyAttrName() ||
4779 name == LLVMDialect::getReadnoneAttrName() ||
4780 name == LLVMDialect::getWriteOnlyAttrName() ||
4781 name == LLVMDialect::getNestAttrName() ||
4782 name == LLVMDialect::getNoCaptureAttrName() ||
4783 name == LLVMDialect::getNoFreeAttrName() ||
4784 name == LLVMDialect::getNoFreeObjAttrName() ||
4785 name == LLVMDialect::getNonNullAttrName()) {
4786 if (
failed(checkUnitAttrType()))
4788 if (verifyValueType &&
failed(checkPointerType()))
4794 if (name == LLVMDialect::getStructRetAttrName() ||
4795 name == LLVMDialect::getByValAttrName() ||
4796 name == LLVMDialect::getByRefAttrName() ||
4797 name == LLVMDialect::getElementTypeAttrName() ||
4798 name == LLVMDialect::getInAllocaAttrName() ||
4799 name == LLVMDialect::getPreallocatedAttrName()) {
4800 if (
failed(checkTypeAttrType()))
4802 if (verifyValueType &&
failed(checkPointerTypeMatches()))
4808 if (name == LLVMDialect::getSExtAttrName() ||
4809 name == LLVMDialect::getZExtAttrName()) {
4810 if (
failed(checkUnitAttrType()))
4812 if (verifyValueType &&
failed(checkIntegerType()))
4818 if (name == LLVMDialect::getAlignAttrName() ||
4819 name == LLVMDialect::getDereferenceableAttrName() ||
4820 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4821 if (
failed(checkIntegerAttrType()))
4823 if (verifyValueType &&
failed(checkPointerType()))
4829 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4830 if (
failed(checkIntegerAttrType()))
4836 if (name == LLVMDialect::getNoUndefAttrName() ||
4837 name == LLVMDialect::getInRegAttrName() ||
4838 name == LLVMDialect::getReturnedAttrName())
4839 return checkUnitAttrType();
4845LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4849 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4852 Type argType = funcOp.getArgumentTypes()[argIdx];
4854 return verifyParameterAttribute(op, argType, argAttr);
4857LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4861 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4864 Type resType = funcOp.getResultTypes()[resIdx];
4868 if (llvm::isa<LLVMVoidType>(resType))
4869 return op->
emitError() <<
"cannot attach result attributes to functions "
4870 "with a void return";
4874 auto name = resAttr.
getName();
4875 if (name == LLVMDialect::getAllocAlignAttrName() ||
4876 name == LLVMDialect::getAllocatedPointerAttrName() ||
4877 name == LLVMDialect::getByValAttrName() ||
4878 name == LLVMDialect::getByRefAttrName() ||
4879 name == LLVMDialect::getInAllocaAttrName() ||
4880 name == LLVMDialect::getNestAttrName() ||
4881 name == LLVMDialect::getNoCaptureAttrName() ||
4882 name == LLVMDialect::getNoFreeAttrName() ||
4883 name == LLVMDialect::getPreallocatedAttrName() ||
4884 name == LLVMDialect::getReadnoneAttrName() ||
4885 name == LLVMDialect::getReadonlyAttrName() ||
4886 name == LLVMDialect::getReturnedAttrName() ||
4887 name == LLVMDialect::getStackAlignmentAttrName() ||
4888 name == LLVMDialect::getStructRetAttrName() ||
4889 name == LLVMDialect::getWriteOnlyAttrName())
4890 return op->
emitError() << name <<
" is not a valid result attribute";
4891 return verifyParameterAttribute(op, resType, resAttr);
4899 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4900 if (isa<LLVM::LLVMPointerType>(type))
4901 return LLVM::AddressOfOp::create(builder, loc, type, symbol);
4902 if (isa<LLVM::UndefAttr>(value))
4903 return LLVM::UndefOp::create(builder, loc, type);
4904 if (isa<LLVM::PoisonAttr>(value))
4905 return LLVM::PoisonOp::create(builder, loc, type);
4906 if (isa<LLVM::ZeroAttr>(value))
4907 return LLVM::ZeroOp::create(builder, loc, type);
4908 if (isa<LLVM::MDStringAttr, LLVM::MDConstantAttr, LLVM::MDGlobalValueAttr,
4909 LLVM::MDNodeAttr>(value))
4910 if (isa<LLVM::LLVMMetadataType>(type))
4911 return LLVM::MetadataAsValueOp::create(builder, loc, type, value);
4913 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4921 StringRef name, StringRef value,
4922 LLVM::Linkage linkage) {
4925 "expected builder to point to a block constrained in an op");
4927 builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
4928 assert(module &&
"builder points to an op outside of a module");
4933 auto type = LLVM::LLVMArrayType::get(IntegerType::get(ctx, 8), value.size());
4934 auto global = LLVM::GlobalOp::create(
4935 moduleBuilder, loc, type,
true, linkage, name,
4938 LLVMPointerType ptrType = LLVMPointerType::get(ctx);
4941 LLVM::AddressOfOp::create(builder, loc, ptrType, global.getSymNameAttr());
4942 return LLVM::GEPOp::create(builder, loc, ptrType, type, globalPtr,
4954 module = module->getParentOp();
4955 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...
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.