29#include "llvm/ADT/APFloat.h"
30#include "llvm/ADT/DenseSet.h"
31#include "llvm/ADT/STLExtras.h"
32#include "llvm/ADT/TypeSwitch.h"
33#include "llvm/IR/DataLayout.h"
34#include "llvm/Support/Error.h"
43using mlir::LLVM::cconv::getMaxEnumValForCConv;
44using mlir::LLVM::linkage::getMaxEnumValForLinkage;
45using mlir::LLVM::tailcallkind::getMaxEnumValForTailCallKind;
47#include "mlir/Dialect/LLVMIR/LLVMOpsDialect.cpp.inc"
58 op, [&](StringRef name,
Attribute &attr) { attrs.
set(name, attr); });
68 for (StringAttr name : inherentAttrNames)
71 attrs.
set(name, *attr);
78 if (attr.
getName() ==
"fastmathFlags") {
98 << name <<
"' does not reference a valid LLVM function";
99 if (
func.isExternal())
100 return op->
emitOpError(
"'") << name <<
"' does not have a definition";
118 for (
const auto &en : llvm::enumerate(keywords)) {
126template <
typename Ty>
129#define REGISTER_ENUM_TYPE(Ty) \
131 struct EnumTraits<Ty> { \
132 static StringRef stringify(Ty value) { return stringify##Ty(value); } \
133 static unsigned getMaxEnumVal() { return getMaxEnumValFor##Ty(); } \
147template <
typename EnumTy,
typename RetTy = EnumTy>
149 EnumTy defaultValue) {
151 for (
unsigned i = 0, e = EnumTraits<EnumTy>::getMaxEnumVal(); i <= e; ++i)
152 names.push_back(EnumTraits<EnumTy>::stringify(
static_cast<EnumTy
>(i)));
156 return static_cast<RetTy
>(defaultValue);
157 return static_cast<RetTy
>(
index);
162 p << stringifyLinkage(val.getLinkage());
166 val = LinkageAttr::get(
174 uint64_t alignment = 1) {
180 if (alignment == 1) {
187 builder.
getNamedAttr(LLVMDialect::getAlignAttrName(), alignmentAttr);
197 int pos = isExpandLoad ? 0 : 1;
199 {alignDictAttr, emptyDictAttr, emptyDictAttr})
201 {emptyDictAttr, alignDictAttr, emptyDictAttr});
213 if (!operands.empty()) {
216 llvm::interleaveComma(operandTypes, p);
225 std::optional<ArrayAttr> opBundleTags) {
226 if (opBundleOperands.empty())
228 assert(opBundleTags &&
"expect operand bundle tags");
231 llvm::interleaveComma(
232 llvm::zip(opBundleOperands, opBundleOperandTypes, *opBundleTags), p,
234 auto bundleTag = cast<StringAttr>(std::get<2>(bundle)).getValue();
252 return p.
emitError(currentParserLoc,
"expect operand bundle tag");
263 opBundleOperands.push_back(std::move(operands));
264 opBundleOperandTypes.push_back(std::move(types));
265 opBundleTags.push_back(StringAttr::get(p.
getContext(), tag));
282 auto bundleParser = [&] {
292 opBundleTags = ArrayAttr::get(p.
getContext(), opBundleTagAttrs);
301template <
typename PredicateAttr,
typename Predicate>
304 function_ref<std::optional<Predicate>(StringRef)> symbolize) {
305 std::string spelling;
309 std::optional<Predicate> value = symbolize(spelling);
313 <<
"' is an incorrect value of the 'predicate' attribute";
314 predicate = PredicateAttr::get(parser.
getContext(), *value);
319 ICmpPredicateAttr &predicate) {
322 [](StringRef spelling) {
return symbolizeICmpPredicate(spelling); });
326 FCmpPredicateAttr &predicate) {
329 [](StringRef spelling) {
return symbolizeFCmpPredicate(spelling); });
333 ICmpPredicateAttr predicate) {
334 printer <<
'"' << stringifyICmpPredicate(predicate.getValue()) <<
'"';
338 FCmpPredicateAttr predicate) {
339 printer <<
'"' << stringifyFCmpPredicate(predicate.getValue()) <<
'"';
345 ShapedType shapedType = dyn_cast<ShapedType>(type);
352 if (getPredicate() != ICmpPredicate::eq &&
353 getPredicate() != ICmpPredicate::ne)
357 if (getLhs() == getRhs())
359 getPredicate() == ICmpPredicate::eq);
362 if (getLhs().getDefiningOp<AllocaOp>() && getRhs().getDefiningOp<ZeroOp>())
364 getPredicate() == ICmpPredicate::ne);
367 if (getLhs().getDefiningOp<ZeroOp>() && getRhs().getDefiningOp<AllocaOp>()) {
368 Value lhs = getLhs();
369 Value rhs = getRhs();
370 getLhsMutable().assign(rhs);
371 getRhsMutable().assign(lhs);
389 p <<
' ' << getArraySize() <<
" x " << getElemType();
390 NamedAttrList attrs((*this)->getDiscardableAttrDictionary().getValue());
391 if (getAlignment() && *getAlignment() != 0)
392 attrs.append(getAlignmentAttrName(), getAlignmentAttr());
394 p <<
" : " << funcTy;
402 SMLoc trailingTypeLoc;
414 std::optional<NamedAttribute> alignmentAttr =
415 result.attributes.getNamed(
"alignment");
416 if (alignmentAttr.has_value()) {
417 auto alignmentInt = llvm::dyn_cast<IntegerAttr>(alignmentAttr->getValue());
420 "expected integer alignment");
421 if (alignmentInt.getValue().isZero())
422 result.attributes.erase(
"alignment");
426 auto funcType = llvm::dyn_cast<FunctionType>(type);
427 if (!funcType || funcType.getNumInputs() != 1 ||
428 funcType.getNumResults() != 1)
431 "expected trailing function type with one argument and one result");
436 Type resultType = funcType.getResult(0);
437 if (
auto ptrResultType = llvm::dyn_cast<LLVMPointerType>(resultType))
440 result.addTypes({funcType.getResult(0)});
444LogicalResult AllocaOp::verify() {
446 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(getElemType());
447 targetExtType && !targetExtType.supportsMemOps())
449 <<
"this target extension type cannot be used in alloca";
454LogicalResult AllocaOp::canonicalize(AllocaOp op,
PatternRewriter &rewriter) {
458 numElements.isOne() || numElements.getActiveBits() > 64)
462 LLVMArrayType::get(op.getElemType(), numElements.getZExtValue());
463 Value one = ConstantOp::create(rewriter, op.getLoc(), rewriter.
getI32Type(),
466 AllocaOp::create(rewriter, op.getLoc(), op.getType(), one,
467 op.getAlignmentAttr(), arrayType, op.getInalloca());
468 newAlloca->setDiscardableAttrs(op->getDiscardableAttrDictionary());
478 assert(
index == 0 &&
"invalid successor index");
487 assert(
index < getNumSuccessors() &&
"invalid successor index");
489 : getFalseDestOperandsMutable());
495 std::optional<std::pair<uint32_t, uint32_t>> weights) {
500 static_cast<int32_t
>(weights->second)});
502 build(builder,
result, condition, trueOperands, falseOperands, weightsAttr,
503 {}, trueDest, falseDest);
517 if (!branchWeights.empty())
520 build(builder,
result, value, defaultOperands, caseOperands, caseValues,
521 weightsAttr, defaultDestination, caseDestinations);
530 if (!caseValues.empty()) {
531 ShapedType caseValueType = VectorType::get(
536 build(builder,
result, value, defaultDestination, defaultOperands,
537 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
546 if (!caseValues.empty()) {
547 ShapedType caseValueType = VectorType::get(
552 build(builder,
result, value, defaultDestination, defaultOperands,
553 caseValuesAttr, caseDestinations, caseOperands, branchWeights);
569 auto parseCase = [&]() {
573 values.push_back(APInt(bitWidth, value,
true));
585 caseDestinations.push_back(destination);
586 caseOperands.emplace_back(operands);
587 caseOperandTypes.emplace_back(operandTypes);
593 ShapedType caseValueType =
594 VectorType::get(
static_cast<int64_t>(values.size()), flagType);
613 llvm::zip(caseValues, caseDestinations),
628LogicalResult SwitchOp::verify() {
629 if ((!getCaseValues() && !getCaseDestinations().empty()) ||
631 getCaseValues()->size() !=
632 static_cast<int64_t>(getCaseDestinations().size())))
633 return emitOpError(
"expects number of case values to match number of "
634 "case destinations");
635 if (getCaseValues() &&
637 return emitError(
"expects case value type to match condition value type");
642 assert(
index < getNumSuccessors() &&
"invalid successor index");
644 : getCaseOperandsMutable(
index - 1));
653 getDynamicIndices());
658 if (
auto vectorType = llvm::dyn_cast<VectorType>(type))
659 return vectorType.getElementType();
676 bool requiresConst = !rawConstantIndices.empty() &&
677 isa_and_nonnull<LLVMStructType>(currType);
678 if (
Value val = llvm::dyn_cast_if_present<Value>(iter)) {
682 rawConstantIndices.push_back(intC.getSExtValue());
684 rawConstantIndices.push_back(GEPOp::kDynamicIndex);
685 dynamicIndices.push_back(val);
688 rawConstantIndices.push_back(cast<GEPConstantIndex>(iter));
693 if (rawConstantIndices.size() == 1 || !currType)
697 .Case<VectorType, LLVMArrayType>([](
auto containerType) {
698 return containerType.getElementType();
700 .Case([&](LLVMStructType structType) ->
Type {
701 int64_t memberIndex = rawConstantIndices.back();
702 if (memberIndex >= 0 &&
static_cast<size_t>(memberIndex) <
703 structType.getBody().size())
704 return structType.getBody()[memberIndex];
713 GEPNoWrapFlags noWrapFlags, ConstantRangeAttr inrange,
719 result.addTypes(resultType);
720 result.addAttributes(attributes);
721 result.getOrAddProperties<Properties>().rawConstantIndices =
723 result.getOrAddProperties<Properties>().noWrapFlags = noWrapFlags;
724 result.getOrAddProperties<Properties>().elem_type =
725 TypeAttr::get(elementType);
726 result.getOrAddProperties<Properties>().inrange = inrange;
727 result.addOperands(basePtr);
728 result.addOperands(dynamicIndices);
733 GEPNoWrapFlags noWrapFlags, ConstantRangeAttr inrange,
735 build(builder,
result, resultType, elementType, basePtr,
745 auto idxParser = [&]() -> ParseResult {
746 int32_t constantIndex;
750 if (failed(parsedInteger.
value()))
752 constantIndices.push_back(constantIndex);
756 constantIndices.push_back(LLVM::GEPOp::kDynamicIndex);
770 llvm::interleaveComma(
773 if (
Value val = llvm::dyn_cast_if_present<Value>(cst))
776 printer << cast<IntegerAttr>(cst).getInt();
786 if (indexPos >=
indices.size())
791 .Case([&](LLVMStructType structType) -> LogicalResult {
792 auto attr = dyn_cast<IntegerAttr>(
indices[indexPos]);
794 return emitOpError() <<
"expected index " << indexPos
795 <<
" indexing a struct to be constant";
797 int32_t gepIndex = attr.getInt();
800 static_cast<size_t>(gepIndex) >= elementTypes.size())
801 return emitOpError() <<
"index " << indexPos
802 <<
" indexing a struct is out of bounds";
809 .Case<VectorType, LLVMArrayType>(
810 [&](
auto containerType) -> LogicalResult {
812 indexPos + 1,
indices, emitOpError);
814 .Default([&](
auto otherType) -> LogicalResult {
816 <<
"type " << otherType <<
" cannot be indexed (index #"
828LogicalResult LLVM::GEPOp::verify() {
829 if (
static_cast<size_t>(
830 llvm::count(getRawConstantIndices(), kDynamicIndex)) !=
831 getDynamicIndices().size())
832 return emitOpError(
"expected as many dynamic indices as specified in '")
833 << getRawConstantIndicesAttrName().getValue() <<
"'";
835 if (getNoWrapFlags() == GEPNoWrapFlags::inboundsFlag)
836 return emitOpError(
"'inbounds_flag' cannot be used directly.");
843 if (
auto inrange = getInrangeAttr()) {
847 std::optional<uint64_t> indexWidth =
849 assert(indexWidth &&
"pointers always return an index bitwidth");
850 if (inrange.getLower().getBitWidth() != *indexWidth)
851 return emitOpError(
"'inrange' bitwidth ")
852 << inrange.getLower().getBitWidth()
853 <<
" must match the pointer index bitwidth (" << *indexWidth
854 <<
") specified in the datalayout";
855 if (inrange.getLower().sge(inrange.getUpper()))
856 return emitOpError(
"expected 'inrange' end to be larger than start");
860 [&] {
return emitOpError(); });
867void LoadOp::getEffects(
876 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
877 getOrdering() != AtomicOrdering::unordered)) {
888 if (!isa<IntegerType, LLVMPointerType>(type))
893 if (bitWidth.isScalable())
896 return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
900template <
typename OpTy>
904 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
907 return memOp.emitOpError(
"unsupported type ")
908 << valueType <<
" for atomic access";
909 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
910 return memOp.emitOpError(
"unsupported ordering '")
911 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
912 if (!memOp.getAlignment())
913 return memOp.emitOpError(
"expected alignment for atomic access");
916 if (memOp.getSyncscope())
917 return memOp.emitOpError(
918 "expected syncscope to be null for non-atomic access");
922LogicalResult LoadOp::verify() {
923 Type valueType = getResult().getType();
925 {AtomicOrdering::release, AtomicOrdering::acq_rel});
929 Value addr,
unsigned alignment,
bool isVolatile,
930 bool isNonTemporal,
bool isInvariant,
bool isInvariantGroup,
931 AtomicOrdering ordering, StringRef syncscope) {
932 build(builder, state, type, addr,
934 isNonTemporal, isInvariant, isInvariantGroup, ordering,
935 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
946void StoreOp::getEffects(
955 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
956 getOrdering() != AtomicOrdering::unordered)) {
962LogicalResult StoreOp::verify() {
963 Type valueType = getValue().getType();
965 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
969 Value addr,
unsigned alignment,
bool isVolatile,
970 bool isNonTemporal,
bool isInvariantGroup,
971 AtomicOrdering ordering, StringRef syncscope) {
972 build(builder, state, value, addr,
974 isNonTemporal, isInvariantGroup, ordering,
975 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope),
977 nullptr,
nullptr,
nullptr);
987 Type resultType = calleeType.getReturnType();
988 if (!isa<LLVM::LLVMVoidType>(resultType))
989 results.push_back(resultType);
995 return calleeType.isVarArg() ? TypeAttr::get(calleeType) :
nullptr;
1002 if (results.empty())
1003 resultType = LLVMVoidType::get(context);
1005 resultType = results.front();
1006 return LLVMFunctionType::get(resultType, llvm::to_vector(args.
getTypes()),
1012 build(builder, state, results, builder.
getStringAttr(callee), args);
1017 build(builder, state, results, SymbolRefAttr::get(callee), args);
1022 assert(callee &&
"expected non-null callee in direct call builder");
1023 build(builder, state, results,
1024 nullptr, callee, args,
nullptr,
1027 nullptr,
nullptr,
nullptr,
1028 nullptr,
nullptr,
nullptr,
1032 nullptr,
nullptr,
nullptr,
1047 LLVMFunctionType calleeType, StringRef callee,
1049 build(builder, state, calleeType, builder.
getStringAttr(callee), args);
1053 LLVMFunctionType calleeType, StringAttr callee,
1055 build(builder, state, calleeType, SymbolRefAttr::get(callee), args);
1073 nullptr,
nullptr,
nullptr,
1082 nullptr,
nullptr,
nullptr,
1088 LLVMFunctionType calleeType,
ValueRange args) {
1093 nullptr,
nullptr,
nullptr,
1094 nullptr,
nullptr,
nullptr,
1100 nullptr,
nullptr,
nullptr,
1116 auto calleeType =
func.getFunctionType();
1120 nullptr,
nullptr,
nullptr,
1121 nullptr,
nullptr,
nullptr,
1127 nullptr,
nullptr,
nullptr,
1146 return getOperand(0);
1152 auto symRef = cast<SymbolRefAttr>(callee);
1153 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1156 return setOperand(0, cast<Value>(callee));
1161template <
typename OpTy>
1164 if (callOp.getCallee().has_value())
1171template <
typename OpTy>
1173 return callOp.getCalleeOperands().drop_front(
1185template <
typename OpTy>
1188 if (std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType())
1189 return operands.take_front(varCalleeType->getNumParams());
1208 if (callee.isExternal())
1210 auto parentFunc = callOp->getParentOfType<FunctionOpInterface>();
1214 auto hasSubprogram = [](
Operation *op) {
1219 if (!hasSubprogram(parentFunc) || !hasSubprogram(callee))
1221 bool containsLoc = !isa<UnknownLoc>(callOp->getLoc());
1223 return callOp.emitError()
1224 <<
"inlinable function call in a function with a DISubprogram "
1225 "location must have a debug location";
1231template <
typename OpTy>
1234 if (!callOp.getCallee().has_value() && callOp.getCalleeOperands().empty())
1235 return callOp.emitOpError(
1236 "must have either a `callee` attribute or at least an operand");
1238 std::optional<LLVMFunctionType> varCalleeType = callOp.getVarCalleeType();
1243 if (!varCalleeType->isVarArg())
1244 return callOp.emitOpError(
1245 "expected var_callee_type to be a variadic function type");
1253 if (varCalleeType->getNumParams() > passedOperands.size())
1254 return callOp.emitOpError(
"expected var_callee_type to have at most ")
1255 << passedOperands.size() <<
" parameters";
1258 for (
auto [paramType, operand] :
1259 llvm::zip(varCalleeType->getParams(), passedOperands))
1260 if (paramType != operand.getType())
1261 return callOp.emitOpError()
1262 <<
"var_callee_type parameter type mismatch: " << paramType
1263 <<
" != " << operand.getType();
1266 if (!callOp.getNumResults()) {
1267 if (!isa<LLVMVoidType>(varCalleeType->getReturnType()))
1268 return callOp.emitOpError(
"expected var_callee_type to return void");
1270 if (callOp.getResult().getType() != varCalleeType->getReturnType())
1271 return callOp.emitOpError(
"var_callee_type return type mismatch: ")
1272 << varCalleeType->getReturnType()
1273 <<
" != " << callOp.getResult().getType();
1278template <
typename OpType>
1281 std::optional<ArrayAttr> opBundleTags = op.getOpBundleTags();
1283 auto isStringAttr = [](
Attribute tagAttr) {
1284 return isa<StringAttr>(tagAttr);
1286 if (opBundleTags && !llvm::all_of(*opBundleTags, isStringAttr))
1287 return op.emitError(
"operand bundle tag must be a StringAttr");
1289 size_t numOpBundles = opBundleOperands.size();
1290 size_t numOpBundleTags = opBundleTags ? opBundleTags->size() : 0;
1291 if (numOpBundles != numOpBundleTags)
1292 return op.emitError(
"expected ")
1293 << numOpBundles <<
" operand bundle tags, but actually got "
1314 auto ptrType = llvm::dyn_cast<LLVMPointerType>(getOperand(0).
getType());
1316 return emitOpError(
"indirect call expects a pointer as callee: ")
1317 << getOperand(0).getType();
1325 return emitOpError()
1327 <<
"' does not reference a symbol in the current scope";
1328 if (
auto fn = dyn_cast<LLVMFuncOp>(callee)) {
1331 fnType = fn.getFunctionType();
1332 }
else if (
auto ifunc = dyn_cast<IFuncOp>(callee)) {
1333 fnType = ifunc.getIFuncType();
1334 }
else if (isa<AliasOp>(callee)) {
1338 fnType = getCalleeFunctionType();
1340 return emitOpError()
1342 <<
"' does not reference a valid LLVM function, IFunc, or alias";
1346 LLVMFunctionType funcType = llvm::dyn_cast<LLVMFunctionType>(fnType);
1348 return emitOpError(
"callee does not have a functional type: ") << fnType;
1350 if (funcType.isVarArg() && !getVarCalleeType())
1351 return emitOpError() <<
"missing var_callee_type attribute for vararg call";
1355 if (getNumResults() == 0 &&
1356 !llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1357 return emitOpError() <<
"expected function call to produce a value";
1359 if (getNumResults() != 0 &&
1360 llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1361 return emitOpError()
1362 <<
"calling function with void result must not produce values";
1364 if (getNumResults() > 1)
1365 return emitOpError()
1366 <<
"expected LLVM function call to produce 0 or 1 result";
1368 if (getNumResults() && getResult().
getType() != funcType.getReturnType())
1369 return emitOpError() <<
"result type mismatch: " << getResult().getType()
1370 <<
" != " << funcType.getReturnType();
1376 if (!llvm::isa<LLVM::LLVMVoidType>(funcType.getReturnType()))
1377 calleeResultTypes.push_back(funcType.getReturnType());
1383 auto callee = getCallee();
1384 bool isDirect = callee.has_value();
1389 if (getCConv() != LLVM::CConv::C)
1390 p << stringifyCConv(getCConv()) <<
' ';
1392 if (getTailCallKind() != LLVM::TailCallKind::None)
1393 p << tailcallkind::stringifyTailCallKind(getTailCallKind()) <<
' ';
1402 auto args = getCalleeOperands().drop_front(isDirect ? 0 : 1);
1403 p <<
'(' << args <<
')';
1406 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1407 p <<
" vararg(" << *varCalleeType <<
")";
1409 if (!getOpBundleOperands().empty()) {
1412 getOpBundleOperands().getTypes(), getOpBundleTags());
1416 {getCalleeAttrName(), getTailCallKindAttrName(),
1417 getVarCalleeTypeAttrName(), getCConvAttrName(),
1418 getOperandSegmentSizesAttrName(),
1419 getOpBundleSizesAttrName(),
1420 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1421 getResAttrsAttrName()});
1425 p << getOperand(0).getType() <<
", ";
1429 p, args.getTypes(), getArgAttrsAttr(),
1430 false, getResultTypes(), getResAttrsAttr());
1445 types.emplace_back();
1450 trailingTypesLoc,
"expected indirect call to have 2 trailing types");
1455 resTypes, resultAttrs)) {
1457 return parser.
emitError(trailingTypesLoc,
1458 "expected direct call to have 1 trailing types");
1459 return parser.
emitError(trailingTypesLoc,
1460 "expected trailing function type");
1463 if (resTypes.size() > 1)
1464 return parser.
emitError(trailingTypesLoc,
1465 "expected function with 0 or 1 result");
1466 if (resTypes.size() == 1 && llvm::isa<LLVM::LLVMVoidType>(resTypes[0]))
1467 return parser.
emitError(trailingTypesLoc,
1468 "expected a non-void result type");
1474 llvm::append_range(types, argTypes);
1478 if (!resTypes.empty())
1479 result.addTypes(resTypes);
1492 if (failed(*parseResult))
1493 return *parseResult;
1494 operands.push_back(funcPtrOperand);
1503 StringAttr opBundleSizesAttrName) {
1504 unsigned opBundleIndex = 0;
1505 for (
const auto &[operands, types] :
1506 llvm::zip_equal(opBundleOperands, opBundleOperandTypes)) {
1507 if (operands.size() != types.size())
1508 return parser.
emitError(loc,
"expected ")
1510 <<
" types for operand bundle operands for operand bundle #"
1511 << opBundleIndex <<
", but actually got " << types.size();
1517 opBundleSizes.reserve(opBundleOperands.size());
1518 for (
const auto &operands : opBundleOperands)
1519 opBundleSizes.push_back(operands.size());
1522 opBundleSizesAttrName,
1534 SymbolRefAttr funcAttr;
1535 TypeAttr varCalleeType;
1543 getCConvAttrName(
result.name),
1548 getTailCallKindAttrName(
result.name),
1551 parser, LLVM::TailCallKind::None)));
1556 bool isDirect = operands.empty();
1569 StringAttr varCalleeTypeAttrName =
1570 CallOp::getVarCalleeTypeAttrName(
result.name);
1582 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1585 if (opBundleTags && !opBundleTags.empty())
1586 result.addAttribute(CallOp::getOpBundleTagsAttrName(
result.name).getValue(),
1596 argAttrs, resultAttrs))
1600 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1602 opBundleOperandTypes,
1603 getOpBundleSizesAttrName(
result.name)))
1606 int32_t numOpBundleOperands = 0;
1607 for (
const auto &operands : opBundleOperands)
1608 numOpBundleOperands += operands.size();
1611 CallOp::getOperandSegmentSizeAttr(),
1613 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
1617LLVMFunctionType CallOp::getCalleeFunctionType() {
1618 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1619 return *varCalleeType;
1630 auto calleeType =
func.getFunctionType();
1633 nullptr,
nullptr, normalOps, unwindOps,
1634 nullptr,
nullptr,
nullptr,
1635 nullptr, {}, {}, normal, unwind);
1642 build(builder, state, tys,
1643 nullptr, callee, ops,
nullptr,
1644 nullptr, normalOps, unwindOps,
nullptr,
nullptr,
1646 nullptr, {}, {}, normal, unwind);
1655 nullptr,
nullptr, normalOps, unwindOps,
1656 nullptr,
nullptr,
nullptr,
1657 nullptr, {}, {}, normal, unwind);
1661 assert(
index < getNumSuccessors() &&
"invalid successor index");
1663 : getUnwindDestOperandsMutable());
1671 return getOperand(0);
1677 auto symRef = cast<SymbolRefAttr>(callee);
1678 return setCalleeAttr(cast<FlatSymbolRefAttr>(symRef));
1681 return setOperand(0, cast<Value>(callee));
1695LogicalResult InvokeOp::verify() {
1699 Block *unwindDest = getUnwindDest();
1700 if (unwindDest->
empty())
1701 return emitError(
"must have at least one operation in unwind destination");
1704 if (!isa<LandingpadOp>(unwindDest->
front()))
1705 return emitError(
"first operation in unwind destination should be a "
1706 "llvm.landingpad operation");
1715 auto callee = getCallee();
1716 bool isDirect = callee.has_value();
1721 if (getCConv() != LLVM::CConv::C)
1722 p << stringifyCConv(getCConv()) <<
' ';
1730 p <<
'(' << getCalleeOperands().drop_front(isDirect ? 0 : 1) <<
')';
1737 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1738 p <<
" vararg(" << *varCalleeType <<
")";
1740 if (!getOpBundleOperands().empty()) {
1743 getOpBundleOperands().getTypes(), getOpBundleTags());
1747 {getCalleeAttrName(), getOperandSegmentSizeAttr(),
1748 getCConvAttrName(), getVarCalleeTypeAttrName(),
1749 getOpBundleSizesAttrName(),
1750 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
1751 getResAttrsAttrName()});
1755 p << getOperand(0).getType() <<
", ";
1757 p, getCalleeOperands().drop_front(isDirect ? 0 : 1).getTypes(),
1759 false, getResultTypes(), getResAttrsAttr());
1772 SymbolRefAttr funcAttr;
1773 TypeAttr varCalleeType;
1777 Block *normalDest, *unwindDest;
1783 getCConvAttrName(
result.name),
1790 bool isDirect = operands.empty();
1806 StringAttr varCalleeTypeAttrName =
1807 InvokeOp::getVarCalleeTypeAttrName(
result.name);
1819 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
1822 if (opBundleTags && !opBundleTags.empty())
1824 InvokeOp::getOpBundleTagsAttrName(
result.name).getValue(),
1834 argAttrs, resultAttrs))
1838 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
1840 result.addSuccessors({normalDest, unwindDest});
1841 result.addOperands(normalOperands);
1842 result.addOperands(unwindOperands);
1845 opBundleOperandTypes,
1846 getOpBundleSizesAttrName(
result.name)))
1849 int32_t numOpBundleOperands = 0;
1850 for (
const auto &operands : opBundleOperands)
1851 numOpBundleOperands += operands.size();
1854 InvokeOp::getOperandSegmentSizeAttr(),
1856 static_cast<int32_t>(normalOperands.size()),
1857 static_cast<int32_t>(unwindOperands.size()),
1858 numOpBundleOperands}));
1862LLVMFunctionType InvokeOp::getCalleeFunctionType() {
1863 if (std::optional<LLVMFunctionType> varCalleeType = getVarCalleeType())
1864 return *varCalleeType;
1872LogicalResult LandingpadOp::verify() {
1874 if (LLVMFuncOp
func = (*this)->getParentOfType<LLVMFuncOp>()) {
1875 if (!
func.getPersonality())
1877 "llvm.landingpad needs to be in a function with a personality");
1883 if (!getCleanup() && getOperands().empty())
1884 return emitError(
"landingpad instruction expects at least one clause or "
1885 "cleanup attribute");
1888 value = getOperand(idx);
1889 bool isFilter = llvm::isa<LLVMArrayType>(value.
getType());
1896 if (
auto addrOp = bcOp.getArg().getDefiningOp<AddressOfOp>())
1899 <<
"global addresses expected as operand to "
1900 "bitcast used in clauses for landingpad";
1908 << idx <<
" is not a known constant - null, addressof, bitcast";
1915 p << (getCleanup() ?
" cleanup " :
" ");
1918 for (
auto value : getOperands()) {
1921 bool isArrayTy = llvm::isa<LLVMArrayType>(value.
getType());
1922 p <<
'(' << (isArrayTy ?
"filter " :
"catch ") << value <<
" : "
1969 Type llvmType = containerType;
1971 emitError(
"expected LLVM IR Dialect type, got ") << containerType;
1979 for (
int64_t idx : position) {
1980 if (
auto arrayType = llvm::dyn_cast<LLVMArrayType>(llvmType)) {
1981 if (idx < 0 ||
static_cast<unsigned>(idx) >= arrayType.getNumElements()) {
1982 emitError(
"position out of bounds: ") << idx;
1985 llvmType = arrayType.getElementType();
1986 }
else if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType)) {
1988 static_cast<unsigned>(idx) >= structType.getBody().size()) {
1989 emitError(
"position out of bounds: ") << idx;
1992 llvmType = structType.getBody()[idx];
1994 emitError(
"expected LLVM IR structure/array type, got: ") << llvmType;
2005 for (
int64_t idx : position) {
2006 if (
auto structType = llvm::dyn_cast<LLVMStructType>(llvmType))
2007 llvmType = structType.getBody()[idx];
2009 llvmType = llvm::cast<LLVMArrayType>(llvmType).getElementType();
2021 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
2022 ShapedType shapedType = elementsAttr.getShapedType();
2023 if (!shapedType.hasRank() || shapedType.getRank() != 1)
2025 if (
index <
static_cast<size_t>(elementsAttr.getNumElements()))
2029 if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
2030 if (
index < arrayAttr.getValue().size())
2031 return arrayAttr[
index];
2034 if (isa<ZeroAttr, UndefAttr, PoisonAttr>(attr))
2039OpFoldResult LLVM::ExtractValueOp::fold(FoldAdaptor adaptor) {
2040 if (
auto extractValueOp = getContainer().getDefiningOp<ExtractValueOp>()) {
2042 newPos.append(getPosition().begin(), getPosition().end());
2043 setPosition(newPos);
2044 getContainerMutable().set(extractValueOp.getContainer());
2050 for (
int64_t pos : getPosition()) {
2055 return containerAttr;
2058 Value container = getContainer();
2060 while (
auto insertValueOp = container.
getDefiningOp<InsertValueOp>()) {
2062 auto extractPosSize = extractPos.size();
2063 auto insertPosSize = insertPos.size();
2066 if (extractPos == insertPos)
2067 return insertValueOp.getValue();
2081 if (extractPosSize > insertPosSize &&
2082 extractPos.take_front(insertPosSize) == insertPos) {
2083 container = insertValueOp.getValue();
2084 extractPos = extractPos.drop_front(insertPosSize);
2100 if (insertPosSize > extractPosSize &&
2101 extractPos == insertPos.take_front(extractPosSize))
2106 container = insertValueOp.getContainer();
2112 if (container == getContainer())
2114 setPosition(extractPos);
2115 getContainerMutable().assign(container);
2119LogicalResult ExtractValueOp::verify() {
2120 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
2126 if (getRes().
getType() != valueType)
2127 return emitOpError() <<
"Type mismatch: extracting from "
2128 << getContainer().getType() <<
" should produce "
2129 << valueType <<
" but this op returns "
2130 << getRes().getType();
2136 build(builder, state,
2175 LogicalResult matchAndRewrite(InsertValueOp insertOp,
2176 PatternRewriter &rewriter)
const override {
2177 bool changed =
false;
2183 auto insertBaseIdx = insertOp.getPosition()[0];
2184 for (
auto &use : insertOp->getUses()) {
2185 if (
auto extractOp = dyn_cast<ExtractValueOp>(use.getOwner())) {
2186 auto baseIdx = extractOp.getPosition()[0];
2189 if (baseIdx == insertBaseIdx)
2191 posToExtractOps[baseIdx].push_back(extractOp);
2196 Value nextContainer = insertOp.getContainer();
2197 while (!posToExtractOps.empty()) {
2199 dyn_cast_or_null<InsertValueOp>(nextContainer.
getDefiningOp());
2202 nextContainer = curInsert.getContainer();
2205 auto curInsertBaseIdx = curInsert.getPosition()[0];
2206 auto it = posToExtractOps.find(curInsertBaseIdx);
2207 if (it == posToExtractOps.end())
2211 for (
auto &extractOp : it->second) {
2213 extractOp.getContainerMutable().assign(curInsert);
2218 assert(!it->second.empty());
2220 posToExtractOps.erase(it);
2224 for (
auto &[baseIdx, extracts] : posToExtractOps) {
2225 for (
auto &extractOp : extracts) {
2227 extractOp.getContainerMutable().assign(nextContainer);
2230 assert(!extracts.empty() &&
"Empty list in map");
2240 patterns.
add<ResolveExtractValueSource>(context);
2248 [&](StringRef msg) {
2260LogicalResult InsertValueOp::verify() {
2261 auto emitError = [
this](StringRef msg) {
return emitOpError(msg); };
2267 if (getValue().
getType() != valueType)
2268 return emitOpError() <<
"Type mismatch: cannot insert "
2269 << getValue().getType() <<
" into "
2270 << getContainer().getType();
2279LogicalResult ReturnOp::verify() {
2280 auto parent = (*this)->getParentOfType<LLVMFuncOp>();
2284 Type expectedType = parent.getFunctionType().getReturnType();
2285 if (llvm::isa<LLVMVoidType>(expectedType)) {
2289 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2293 if (llvm::isa<LLVMVoidType>(expectedType))
2296 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2299 if (expectedType != getArg().
getType()) {
2301 diag.attachNote(parent->getLoc()) <<
"when returning from function";
2312 return dyn_cast_or_null<GlobalOp>(
2317 return dyn_cast_or_null<LLVMFuncOp>(
2322 return dyn_cast_or_null<AliasOp>(
2327 return dyn_cast_or_null<IFuncOp>(
2336 auto global = dyn_cast_or_null<GlobalOp>(symbol);
2337 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2338 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2339 auto ifunc = dyn_cast_or_null<IFuncOp>(symbol);
2341 if (!global && !function && !alias && !ifunc)
2342 return emitOpError(
"must reference a global defined by 'llvm.mlir.global', "
2343 "'llvm.mlir.alias' or 'llvm.func' or 'llvm.mlir.ifunc'");
2345 LLVMPointerType type =
getType();
2346 if ((global && global.getAddrSpace() != type.getAddressSpace()) ||
2347 (alias && alias.getAddrSpace() != type.getAddressSpace()))
2348 return emitOpError(
"pointer address space must match address space of the "
2349 "referenced global or alias");
2356 return getGlobalNameAttr();
2377 getFunctionNameAttr());
2378 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
2379 auto alias = dyn_cast_or_null<AliasOp>(symbol);
2381 if (!function && !alias)
2383 "must reference a global defined by 'llvm.func' or 'llvm.mlir.alias'");
2386 if (alias.getInitializer()
2387 .walk([&](AddressOfOp addrOp) {
2388 if (addrOp.getGlobal(symbolTable))
2389 return WalkResult::interrupt();
2390 return WalkResult::advance();
2393 return emitOpError(
"must reference an alias to a function");
2396 if ((function && function.getLinkage() == LLVM::Linkage::ExternWeak) ||
2397 (alias && alias.getLinkage() == LLVM::Linkage::ExternWeak))
2399 "target function with 'extern_weak' linkage not allowed");
2407 return DSOLocalEquivalentAttr::get(
getContext(), getFunctionNameAttr());
2415 StringRef symName) {
2418 Region *body =
result.addRegion();
2422LogicalResult ComdatOp::verifyRegions() {
2423 Region &body = getBody();
2424 for (Operation &op : body.
getOps())
2425 if (!isa<ComdatSelectorOp>(op))
2426 return op.emitError(
2427 "only comdat selector symbols can appear in a comdat region");
2437 bool isConstant, Linkage linkage, StringRef name,
2438 Attribute value, uint64_t alignment,
unsigned addrSpace,
2439 bool dsoLocal, ThreadLocalMode threadModel,
2442 result.getOrAddProperties<Properties>().sym_name =
2444 result.addAttribute(getGlobalTypeAttrName(
result.name), TypeAttr::get(type));
2446 getTlsModeAttrName(
result.name),
2447 ThreadLocalModeAttr::get(builder.
getContext(), threadModel));
2452 result.addAttribute(getValueAttrName(
result.name), value);
2457 result.addAttribute(getComdatAttrName(
result.name), comdat);
2467 LinkageAttr::get(builder.
getContext(), linkage));
2471 result.attributes.append(attrs.begin(), attrs.end());
2473 if (!dbgExprs.empty())
2475 ArrayAttr::get(builder.
getContext(), dbgExprs));
2480template <
typename OpType>
2482 p <<
' ' << stringifyLinkage(op.getLinkage()) <<
' ';
2483 StringRef visibility = stringifyVisibility(op.getVisibility_());
2484 if (!visibility.empty())
2485 p << visibility <<
' ';
2487 if (ThreadLocalMode mode = op.getTlsMode();
2488 mode != ThreadLocalMode::NotThreadLocal) {
2489 p <<
"thread_local";
2490 if (mode != ThreadLocalMode::GeneralDynamic)
2491 p <<
'(' << mode <<
')';
2495 if (
auto unnamedAddr = op.getUnnamedAddr()) {
2496 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
2508 if (
auto value = getValueOrNull())
2511 if (
auto comdat = getComdat())
2512 p <<
" comdat(" << *comdat <<
')';
2519 *
this, {getDsoLocalAttrName(), getExternallyInitializedAttrName(),
2520 getAlignmentAttrName(), getAddrSpaceAttrName(),
2521 getSectionAttrName(), getAssociatedAttrName(),
2522 getAbsoluteSymbolAttrName(), getDbgExprsAttrName(),
2523 getTargetSpecificAttrsAttrName(), getSymVisibilityAttrName()})
2525 {getSymNameAttrName(), getGlobalTypeAttrName(), getConstantAttrName(),
2526 getValueAttrName(), getLinkageAttrName(), getUnnamedAddrAttrName(),
2527 getTlsModeAttrName(), getVisibility_AttrName(), getComdatAttrName()});
2530 if (llvm::dyn_cast_or_null<StringAttr>(getValueOrNull()))
2534 Region &initializer = getInitializerRegion();
2535 if (!initializer.
empty()) {
2542 std::optional<SymbolRefAttr> attr,
2548 if (!isa_and_nonnull<ComdatSelectorOp>(comdatSelector))
2549 return op->
emitError() <<
"expected comdat symbol";
2559 WalkResult res = funcOp.walk([&](BlockTagOp blockTagOp) {
2560 if (blockTags.contains(blockTagOp.getTag())) {
2561 blockTagOp.emitError()
2562 <<
"duplicate block tag '" << blockTagOp.getTag().getId()
2563 <<
"' in the same function: ";
2566 blockTags.insert(blockTagOp.getTag());
2570 return failure(res.wasInterrupted());
2575template <
typename OpType>
2582 OpType::getLinkageAttrName(
result.name),
2584 parser, LLVM::Linkage::External)));
2587 result.addAttribute(OpType::getVisibility_AttrName(
result.name),
2590 parser, LLVM::Visibility::Default)));
2593 ThreadLocalMode threadModel = ThreadLocalMode::GeneralDynamic;
2600 parser, ThreadLocalMode::NotThreadLocal);
2601 if (threadModel == ThreadLocalMode::NotThreadLocal) {
2602 parser.
emitError(kwLoc,
"invalid value for thread_local");
2608 result.addAttribute(OpType::getTlsModeAttrName(
result.name),
2609 ThreadLocalModeAttr::get(ctx, threadModel));
2613 result.addAttribute(OpType::getUnnamedAddrAttrName(
result.name),
2616 parser, LLVM::UnnamedAddr::None)));
2654 SymbolRefAttr comdat;
2659 result.addAttribute(getComdatAttrName(
result.name), comdat);
2667 if (types.size() > 1)
2671 if (types.empty()) {
2672 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(value)) {
2674 auto arrayType = LLVM::LLVMArrayType::get(IntegerType::get(context, 8),
2675 strAttr.getValue().size());
2676 types.push_back(arrayType);
2679 "type can only be omitted for string globals");
2689 result.addAttribute(getGlobalTypeAttrName(
result.name),
2690 TypeAttr::get(types[0]));
2695 if (
auto intValue = llvm::dyn_cast<IntegerAttr>(value))
2696 return intValue.getValue().isZero();
2697 if (
auto fpValue = llvm::dyn_cast<FloatAttr>(value))
2698 return fpValue.getValue().isZero();
2699 if (
auto splatValue = llvm::dyn_cast<SplatElementsAttr>(value))
2701 if (
auto elementsValue = llvm::dyn_cast<ElementsAttr>(value))
2703 if (
auto arrayValue = llvm::dyn_cast<ArrayAttr>(value))
2712LogicalResult GlobalOp::verify() {
2714 ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
2716 :
llvm::isa<PointerElementTypeInterface>(
getType());
2719 "expects type to be a valid element type for an LLVM global");
2721 return emitOpError(
"must appear at the module level");
2723 if (
auto strAttr = llvm::dyn_cast_or_null<StringAttr>(getValueOrNull())) {
2724 auto type = llvm::dyn_cast<LLVMArrayType>(
getType());
2725 IntegerType elementType =
2726 type ? llvm::dyn_cast<IntegerType>(type.getElementType()) :
nullptr;
2727 if (!elementType || elementType.getWidth() != 8 ||
2728 type.getNumElements() != strAttr.getValue().size())
2730 "requires an i8 array type of the length equal to that of the string "
2734 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType())) {
2735 if (!targetExtType.hasProperty(LLVMTargetExtType::CanBeGlobal))
2736 return emitOpError()
2737 <<
"this target extension type cannot be used in a global";
2740 return emitOpError() <<
"global with target extension type can only be "
2741 "initialized with zero-initializer";
2744 if (getLinkage() == Linkage::Common) {
2745 if (
Attribute value = getValueOrNull()) {
2747 return emitOpError()
2748 <<
"expected zero value for '"
2749 << stringifyLinkage(Linkage::Common) <<
"' linkage";
2754 if (getLinkage() == Linkage::Appending) {
2755 if (!llvm::isa<LLVMArrayType>(
getType())) {
2756 return emitOpError() <<
"expected array type for '"
2757 << stringifyLinkage(Linkage::Appending)
2762 std::optional<uint64_t> alignAttr = getAlignment();
2763 if (alignAttr.has_value()) {
2764 uint64_t value = alignAttr.value();
2765 if (!llvm::isPowerOf2_64(value))
2766 return emitError() <<
"alignment attribute is not a power of 2";
2770 if (associated.getValue() == getSymName())
2771 return emitOpError(
"associated cannot refer to the global itself");
2774 if (
ArrayAttr absSym = getAbsoluteSymbolAttr()) {
2775 if (absSym.empty() || absSym.size() % 2 != 0)
2777 "absolute_symbol must contain one or more integer range pairs");
2780 auto intAttr = dyn_cast<IntegerAttr>(attr);
2782 return emitOpError(
"absolute_symbol operands must be integers");
2784 pairType = intAttr.getType();
2785 else if (intAttr.getType() != pairType)
2786 return emitOpError(
"absolute_symbol range pair types must match");
2793LogicalResult GlobalOp::verifyRegions() {
2794 if (
Block *
b = getInitializerBlock()) {
2795 ReturnOp ret = cast<ReturnOp>(
b->getTerminator());
2796 if (ret.operand_type_begin() == ret.operand_type_end())
2797 return emitOpError(
"initializer region cannot return void");
2798 if (*ret.operand_type_begin() !=
getType())
2799 return emitOpError(
"initializer region type ")
2800 << *ret.operand_type_begin() <<
" does not match global type "
2804 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2805 if (!iface || !iface.hasNoEffect())
2806 return op.emitError()
2807 <<
"ops with side effects not allowed in global initializers";
2810 if (getValueOrNull())
2811 return emitOpError(
"cannot have both initializer value and region");
2826 return isa<FlatSymbolRefAttr, ZeroAttr>(v);
2829 return op->
emitError(
"data element must be symbol or #llvm.zero");
2842LogicalResult GlobalCtorsOp::verify() {
2846 if (getCtors().size() == getPriorities().size() &&
2847 getCtors().size() == getData().size())
2850 "ctors, priorities, and data must have the same number of elements");
2867LogicalResult GlobalDtorsOp::verify() {
2871 if (getDtors().size() == getPriorities().size() &&
2872 getDtors().size() == getData().size())
2875 "dtors, priorities, and data must have the same number of elements");
2883 Linkage linkage, StringRef name,
bool dsoLocal,
2884 ThreadLocalMode threadModel,
2888 result.addAttribute(getAliasTypeAttrName(
result.name), TypeAttr::get(type));
2890 getTlsModeAttrName(
result.name),
2891 ThreadLocalModeAttr::get(builder.
getContext(), threadModel));
2897 LinkageAttr::get(builder.
getContext(), linkage));
2898 result.attributes.append(attrs.begin(), attrs.end());
2909 {getDsoLocalAttrName(), getSymVisibilityAttrName()})
2911 {getSymNameAttrName(), getAliasTypeAttrName(), getLinkageAttrName(),
2912 getUnnamedAddrAttrName(), getTlsModeAttrName(),
2913 getVisibility_AttrName()});
2916 p <<
" : " <<
getType() <<
' ';
2942 if (types.size() > 1)
2950 TypeAttr::get(types[0]));
2954LogicalResult AliasOp::verify() {
2956 ? !llvm::isa<LLVMVoidType, TokenType, LLVMMetadataType,
2958 :
llvm::isa<PointerElementTypeInterface>(
getType());
2961 "expects type to be a valid element type for an LLVM global alias");
2964 switch (getLinkage()) {
2965 case Linkage::External:
2966 case Linkage::Internal:
2967 case Linkage::Private:
2969 case Linkage::WeakODR:
2970 case Linkage::Linkonce:
2971 case Linkage::LinkonceODR:
2972 case Linkage::AvailableExternally:
2975 return emitOpError()
2976 <<
"'" << stringifyLinkage(getLinkage())
2977 <<
"' linkage not supported in aliases, available options: private, "
2978 "internal, linkonce, weak, linkonce_odr, weak_odr, external or "
2979 "available_externally";
2985LogicalResult AliasOp::verifyRegions() {
2986 Block &
b = getInitializerBlock();
2987 auto ret = cast<ReturnOp>(
b.getTerminator());
2988 if (ret.getNumOperands() == 0 ||
2989 !isa<LLVM::LLVMPointerType>(ret.getOperand(0).getType()))
2990 return emitOpError(
"initializer region must always return a pointer");
2993 auto iface = dyn_cast<MemoryEffectOpInterface>(op);
2994 if (!iface || !iface.hasNoEffect())
2995 return op.emitError()
2996 <<
"ops with side effects are not allowed in alias initializers";
3002unsigned AliasOp::getAddrSpace() {
3003 Block &initializer = getInitializerBlock();
3005 auto ptrTy = cast<LLVMPointerType>(ret.getOperand(0).getType());
3006 return ptrTy.getAddressSpace();
3014 Type iFuncType, StringRef resolverName,
Type resolverType,
3015 Linkage linkage, LLVM::Visibility visibility) {
3016 return build(builder,
result, name, iFuncType, resolverName, resolverType,
3018 UnnamedAddr::None, visibility,
nullptr);
3025 auto resolver = dyn_cast<LLVMFuncOp>(symbol);
3026 auto alias = dyn_cast<AliasOp>(symbol);
3028 Block &initBlock = alias.getInitializerBlock();
3030 auto addrOp = returnOp.getArg().getDefiningOp<AddressOfOp>();
3037 resolver = addrOp.getFunction(symbolTable);
3038 alias = addrOp.getAlias(symbolTable);
3041 return emitOpError(
"must have a function resolver");
3042 Linkage linkage = resolver.getLinkage();
3043 if (resolver.isExternal() || linkage == Linkage::AvailableExternally)
3044 return emitOpError(
"resolver must be a definition");
3045 if (!isa<LLVMPointerType>(resolver.getFunctionType().getReturnType()))
3046 return emitOpError(
"resolver must return a pointer");
3047 auto resolverPtr = dyn_cast<LLVMPointerType>(getResolverType());
3048 if (!resolverPtr || resolverPtr.getAddressSpace() != getAddressSpace())
3049 return emitOpError(
"resolver has incorrect type");
3053LogicalResult IFuncOp::verify() {
3054 switch (getLinkage()) {
3055 case Linkage::External:
3056 case Linkage::Internal:
3057 case Linkage::Private:
3059 case Linkage::WeakODR:
3060 case Linkage::Linkonce:
3061 case Linkage::LinkonceODR:
3064 return emitOpError() <<
"'" << stringifyLinkage(getLinkage())
3065 <<
"' linkage not supported in ifuncs, available "
3066 "options: private, internal, linkonce, weak, "
3067 "linkonce_odr, weak_odr, or external linkage";
3079 auto containerType = v1.
getType();
3083 build(builder, state, vType, v1, v2, mask);
3098 "expected an LLVM compatible vector type");
3110LogicalResult ShuffleVectorOp::verify() {
3112 llvm::any_of(getMask(), [](int32_t v) {
return v != 0; }))
3113 return emitOpError(
"expected a splat operation for scalable vectors");
3119OpFoldResult ShuffleVectorOp::fold(FoldAdaptor adaptor) {
3121 auto vecType = llvm::dyn_cast<VectorType>(getV1().
getType());
3122 if (!vecType || vecType.getRank() != 1 || vecType.getNumElements() != 1)
3126 if (getMask().size() != 1 || getMask()[0] != 0)
3137 assert(empty() &&
"function already has an entry block");
3142 LLVMFunctionType type = getFunctionType();
3143 for (
unsigned i = 0, e = type.getNumParams(); i < e; ++i)
3144 entry->
addArgument(type.getParamType(i), getLoc());
3149 StringRef name,
Type type, LLVM::Linkage linkage,
3150 bool dsoLocal, CConv cconv, SymbolRefAttr comdat,
3153 std::optional<uint64_t> functionEntryCount) {
3157 result.addAttribute(getFunctionTypeAttrName(
result.name),
3158 TypeAttr::get(type));
3160 LinkageAttr::get(builder.
getContext(), linkage));
3162 CConvAttr::get(builder.
getContext(), cconv));
3163 result.attributes.append(attrs.begin(), attrs.end());
3168 result.addAttribute(getComdatAttrName(
result.name), comdat);
3169 if (functionEntryCount)
3170 result.addAttribute(getFunctionEntryCountAttrName(
result.name),
3171 FunctionEntryCountAttr::get(
3175 std::optional<NamedAttribute> duplicate =
result.attributes.findDuplicate();
3176 if (duplicate.has_value()) {
3177 llvm::report_fatal_error(
3178 Twine(
"LLVMFuncOp propagated an attribute that is meant "
3179 "to be constructed by the builder: ") +
3180 duplicate->getName().str());
3183 if (argAttrs.empty())
3186 assert(llvm::cast<LLVMFunctionType>(type).getNumParams() == argAttrs.size() &&
3187 "expected as many argument attribute lists as arguments");
3189 builder,
result, argAttrs, {},
3190 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3201 if (outputs.size() > 1) {
3202 parser.
emitError(loc,
"failed to construct function type: expected zero or "
3203 "one function result");
3209 for (
auto t : inputs) {
3211 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3212 "type for function arguments");
3215 llvmInputs.push_back(t);
3220 outputs.empty() ? LLVMVoidType::get(
b.getContext()) : outputs.front();
3222 parser.
emitError(loc,
"failed to construct function type: expected LLVM "
3223 "type for function results")
3227 return LLVMFunctionType::get(llvmOutput, llvmInputs,
3243 parser, LLVM::Linkage::External)));
3246 result.addAttribute(getVisibility_AttrName(
result.name),
3249 parser, LLVM::Visibility::Default)));
3252 result.addAttribute(getUnnamedAddrAttrName(
result.name),
3255 parser, LLVM::UnnamedAddr::None)));
3259 getCConvAttrName(
result.name),
3263 StringAttr nameAttr;
3273 parser,
true, entryArgs, isVariadic, resultTypes,
3278 for (
auto &arg : entryArgs)
3279 argTypes.push_back(arg.type);
3285 result.addAttribute(getFunctionTypeAttrName(
result.name),
3286 TypeAttr::get(type));
3294 auto intTy = IntegerType::get(parser.
getContext(), 32);
3296 getVscaleRangeAttrName(
result.name),
3297 LLVM::VScaleRangeAttr::get(parser.
getContext(),
3298 IntegerAttr::get(intTy, minRange),
3299 IntegerAttr::get(intTy, maxRange)));
3303 SymbolRefAttr comdat;
3308 result.addAttribute(getComdatAttrName(
result.name), comdat);
3315 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
3317 auto *body =
result.addRegion();
3328 if (getLinkage() != LLVM::Linkage::External)
3329 p << stringifyLinkage(getLinkage()) <<
' ';
3330 StringRef visibility = stringifyVisibility(getVisibility_());
3331 if (!visibility.empty())
3332 p << visibility <<
' ';
3333 if (
auto unnamedAddr = getUnnamedAddr()) {
3334 StringRef str = stringifyUnnamedAddr(*unnamedAddr);
3338 if (getCConv() != LLVM::CConv::C)
3339 p << stringifyCConv(getCConv()) <<
' ';
3343 LLVMFunctionType fnType = getFunctionType();
3346 argTypes.reserve(fnType.getNumParams());
3347 for (
unsigned i = 0, e = fnType.getNumParams(); i < e; ++i)
3348 argTypes.push_back(fnType.getParamType(i));
3350 Type returnType = fnType.getReturnType();
3351 if (!llvm::isa<LLVMVoidType>(returnType))
3352 resTypes.push_back(returnType);
3355 isVarArg(), resTypes);
3358 if (std::optional<VScaleRangeAttr> vscale = getVscaleRange())
3359 p <<
" vscale_range(" << vscale->getMinRange().getInt() <<
", "
3360 << vscale->getMaxRange().getInt() <<
')';
3363 if (
auto comdat = getComdat())
3364 p <<
" comdat(" << *comdat <<
')';
3368 {getFunctionTypeAttrName(), getArgAttrsAttrName(), getResAttrsAttrName(),
3369 getLinkageAttrName(), getCConvAttrName(), getVisibility_AttrName(),
3370 getComdatAttrName(), getUnnamedAddrAttrName(),
3371 getVscaleRangeAttrName()});
3374 Region &body = getBody();
3375 if (!body.empty()) {
3390LogicalResult LLVMFuncOp::verify() {
3391 if (getLinkage() == LLVM::Linkage::Common)
3392 return emitOpError() <<
"functions cannot have '"
3393 << stringifyLinkage(LLVM::Linkage::Common)
3397 if (getFunctionEntryCountAttr())
3398 return emitOpError() <<
"external functions cannot have "
3399 << getFunctionEntryCountAttrName() <<
" attribute";
3401 if (getLinkage() != LLVM::Linkage::External &&
3402 getLinkage() != LLVM::Linkage::ExternWeak)
3403 return emitOpError() <<
"external functions must have '"
3404 << stringifyLinkage(LLVM::Linkage::External)
3406 << stringifyLinkage(LLVM::Linkage::ExternWeak)
3412 if (isNoInline() && isAlwaysInline())
3413 return emitError(
"no_inline and always_inline attributes are incompatible");
3415 if (isOptimizeNone() && !isNoInline())
3416 return emitOpError(
"with optimize_none must also be no_inline");
3418 Type landingpadResultTy;
3419 StringRef diagnosticMessage;
3420 bool isLandingpadTypeConsistent =
3422 const auto checkType = [&](
Type type, StringRef errorMessage) {
3423 if (!landingpadResultTy) {
3424 landingpadResultTy = type;
3427 if (landingpadResultTy != type) {
3428 diagnosticMessage = errorMessage;
3434 .Case([&](LandingpadOp landingpad) {
3435 constexpr StringLiteral errorMessage =
3436 "'llvm.landingpad' should have a consistent result type "
3437 "inside a function";
3438 return checkType(landingpad.getType(), errorMessage);
3440 .Case([&](ResumeOp resume) {
3441 constexpr StringLiteral errorMessage =
3442 "'llvm.resume' should have a consistent input type inside a "
3444 return checkType(resume.getValue().getType(), errorMessage);
3447 }).wasInterrupted();
3448 if (!isLandingpadTypeConsistent) {
3449 assert(!diagnosticMessage.empty() &&
3450 "Expecting a non-empty diagnostic message");
3462LogicalResult LLVMFuncOp::verifyRegions() {
3466 unsigned numArguments = getFunctionType().getNumParams();
3467 Block &entryBlock = front();
3468 for (
unsigned i = 0; i < numArguments; ++i) {
3471 return emitOpError(
"entry block argument #")
3472 << i <<
" is not of LLVM type";
3478Region *LLVMFuncOp::getCallableRegion() {
3507OpFoldResult LLVM::MetadataAsValueOp::fold(FoldAdaptor) {
3508 return getMetadataAttr();
3515LogicalResult LLVM::ZeroOp::verify() {
3516 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3517 if (!targetExtType.hasProperty(LLVM::LLVMTargetExtType::HasZeroInit))
3518 return emitOpError()
3519 <<
"target extension type does not support zero-initializer";
3541 if (
auto vecType = dyn_cast<VectorType>(t)) {
3542 assert(!vecType.isScalable() &&
3543 "number of elements of a scalable vector type is unknown");
3544 return vecType.getNumElements() *
getNumElements(vecType.getElementType());
3546 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3547 return arrayType.getNumElements() *
3555 while (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(type))
3556 type = arrayType.getElementType();
3557 if (
auto vecType = dyn_cast<VectorType>(type))
3558 return vecType.getElementType();
3559 if (
auto tenType = dyn_cast<TensorType>(type))
3560 return tenType.getElementType();
3567 if (
auto vecType = dyn_cast<VectorType>(t)) {
3568 if (vecType.isScalable())
3572 if (
auto arrayType = dyn_cast<LLVM::LLVMArrayType>(t))
3580 LLVM::LLVMArrayType arrayType,
3582 if (arrayType.getNumElements() != arrayAttr.size())
3583 return op.emitOpError()
3584 <<
"array attribute size does not match array type size in "
3586 << dim <<
": " << arrayAttr.size() <<
" vs. "
3587 << arrayType.getNumElements();
3592 if (
auto subArrayType =
3593 dyn_cast<LLVM::LLVMArrayType>(arrayType.getElementType())) {
3594 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr))
3595 if (elementsVerified.insert(elementAttr).second) {
3596 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3598 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3600 return op.emitOpError()
3601 <<
"nested attribute for sub-array in dimension " << dim
3602 <<
" at index " << idx
3603 <<
" must be a zero, or undef, or array attribute";
3617 Type elementType = arrayType.getElementType();
3618 if (isa<LLVM::LLVMPointerType>(elementType)) {
3619 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3621 LLVM::PoisonAttr>(elementAttr))
3623 return op.emitOpError()
3624 <<
"pointer array element at index " << idx
3625 <<
" must be a flat symbol reference, zero, undef, or poison";
3629 auto structType = dyn_cast<LLVM::LLVMStructType>(elementType);
3631 return op.emitOpError() <<
"for array with an array attribute must have a "
3632 "struct element type";
3636 size_t numStructElements = structType.getBody().size();
3637 for (
auto [idx, elementAttr] : llvm::enumerate(arrayAttr)) {
3638 if (elementsVerified.insert(elementAttr).second) {
3639 if (isa<LLVM::ZeroAttr, LLVM::UndefAttr>(elementAttr))
3641 auto subArrayAttr = dyn_cast<ArrayAttr>(elementAttr);
3643 return op.emitOpError()
3644 <<
"nested attribute for struct element at index " << idx
3645 <<
" must be a zero, or undef, or array attribute";
3646 if (subArrayAttr.size() != numStructElements)
3647 return op.emitOpError()
3648 <<
"nested array attribute size for struct element at index "
3649 << idx <<
" must match struct size: " << subArrayAttr.size()
3650 <<
" vs. " << numStructElements;
3657LogicalResult LLVM::ConstantOp::verify() {
3658 if (StringAttr sAttr = llvm::dyn_cast<StringAttr>(getValue())) {
3659 auto arrayType = llvm::dyn_cast<LLVMArrayType>(
getType());
3660 if (!arrayType || arrayType.getNumElements() != sAttr.getValue().size() ||
3661 !arrayType.getElementType().isInteger(8)) {
3662 return emitOpError() <<
"expected array type of "
3663 << sAttr.getValue().size()
3664 <<
" i8 elements for the string constant";
3668 if (
auto structType = dyn_cast<LLVMStructType>(
getType())) {
3669 auto arrayAttr = dyn_cast<ArrayAttr>(getValue());
3671 return emitOpError() <<
"expected array attribute for struct type";
3674 if (arrayAttr.size() != elementTypes.size()) {
3675 return emitOpError() <<
"expected array attribute of size "
3676 << elementTypes.size();
3678 for (
auto [i, attr, type] : llvm::enumerate(arrayAttr, elementTypes)) {
3680 return emitOpError() <<
"expected struct element types to be floating "
3681 "point type or integer type";
3683 if (!isa<FloatAttr, IntegerAttr>(attr)) {
3684 return emitOpError() <<
"expected element of array attribute to be "
3685 "floating point or integer";
3687 if (cast<TypedAttr>(attr).
getType() != type)
3688 return emitOpError()
3689 <<
"struct element at index " << i <<
" is of wrong type";
3694 if (
auto targetExtType = dyn_cast<LLVMTargetExtType>(
getType()))
3695 return emitOpError() <<
"does not support target extension type.";
3706 auto verifyFloatSemantics =
3707 [
this](
const llvm::fltSemantics &attributeFloatSemantics,
3708 Type constantElementType) -> LogicalResult {
3709 if (
auto floatType = dyn_cast<FloatType>(constantElementType)) {
3710 if (&floatType.getFloatSemantics() != &attributeFloatSemantics) {
3711 return emitOpError()
3712 <<
"attribute and type have different float semantics";
3716 unsigned floatWidth = APFloat::getSizeInBits(attributeFloatSemantics);
3717 if (isa<IntegerType>(constantElementType)) {
3718 if (!constantElementType.isInteger(floatWidth))
3719 return emitOpError() <<
"expected integer type of width " << floatWidth;
3734 auto verifyIntegerSemantics = [
this](
Type attributeIntType,
3735 Type constantElementType,
3736 StringRef description) -> LogicalResult {
3737 if (attributeIntType != constantElementType)
3738 return emitOpError() <<
"attribute and type have different integer "
3739 << description <<
"s: " << attributeIntType
3740 <<
" vs. " << constantElementType;
3745 if (
auto intAttr = dyn_cast<IntegerAttr>(getValue())) {
3746 if (!llvm::isa<IntegerType>(
getType()))
3747 return emitOpError() <<
"expected integer type";
3748 return verifyIntegerSemantics(intAttr.getType(),
getType(),
"type");
3749 }
else if (
auto floatAttr = dyn_cast<FloatAttr>(getValue())) {
3750 return verifyFloatSemantics(floatAttr.getValue().getSemantics(),
getType());
3751 }
else if (
auto elementsAttr = dyn_cast<ElementsAttr>(getValue())) {
3755 auto verifyElementTypes = [&](ElementsAttr attr) -> LogicalResult {
3758 if (
auto floatType = dyn_cast<FloatType>(attrElmType))
3759 return verifyFloatSemantics(floatType.getFloatSemantics(),
3762 if (isa<IntegerType, IndexType>(attrElmType)) {
3763 if (!isa<IntegerType>(resultElmType))
3765 "expected integer element type for integer elements attribute");
3766 return verifyIntegerSemantics(attrElmType, resultElmType,
3775 auto splatElementsAttr = dyn_cast<SplatElementsAttr>(getValue());
3776 if (!splatElementsAttr)
3777 return emitOpError()
3778 <<
"scalable vector type requires a splat attribute";
3779 return verifyElementTypes(splatElementsAttr);
3781 if (!isa<VectorType, LLVM::LLVMArrayType>(
getType()))
3782 return emitOpError() <<
"expected vector or array type";
3785 int64_t attrNumElements = elementsAttr.getNumElements();
3787 return emitOpError()
3788 <<
"type and attribute have a different number of elements: "
3792 return verifyElementTypes(elementsAttr);
3793 }
else if (
auto arrayAttr = dyn_cast<ArrayAttr>(getValue())) {
3796 auto arrayType = dyn_cast<LLVM::LLVMArrayType>(
getType());
3798 return emitOpError()
3799 <<
"expected array or struct type for array attribute";
3805 return emitOpError()
3806 <<
"only supports integer, float, string or elements attributes";
3810bool LLVM::ConstantOp::isBuildableWith(
Attribute value,
Type type) {
3812 auto typedAttr = dyn_cast<TypedAttr>(value);
3819 return isa<IntegerAttr, FloatAttr, ElementsAttr>(value);
3824 if (isBuildableWith(value, type))
3825 return LLVM::ConstantOp::create(builder, loc, cast<TypedAttr>(value));
3830OpFoldResult LLVM::ConstantOp::fold(FoldAdaptor) {
return getValue(); }
3838 AtomicOrdering ordering, StringRef syncscope,
3839 unsigned alignment,
bool isVolatile) {
3840 build(builder, state, val.
getType(), binOp,
ptr, val, ordering,
3841 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3844 nullptr,
nullptr,
nullptr);
3847LogicalResult AtomicRMWOp::verify() {
3848 auto valType = getVal().getType();
3849 if (getBinOp() == AtomicBinOp::fadd || getBinOp() == AtomicBinOp::fsub ||
3850 getBinOp() == AtomicBinOp::fmin || getBinOp() == AtomicBinOp::fmax ||
3851 getBinOp() == AtomicBinOp::fminimum ||
3852 getBinOp() == AtomicBinOp::fmaximum ||
3853 getBinOp() == AtomicBinOp::fminimumnum ||
3854 getBinOp() == AtomicBinOp::fmaximumnum) {
3857 return emitOpError(
"expected LLVM IR fixed vector type");
3858 Type elemType = llvm::cast<VectorType>(valType).getElementType();
3861 "expected LLVM IR floating point type for vector element");
3863 return emitOpError(
"expected LLVM IR floating point type");
3865 }
else if (getBinOp() == AtomicBinOp::xchg) {
3868 return emitOpError(
"unexpected LLVM IR type for 'xchg' bin_op");
3870 auto intType = llvm::dyn_cast<IntegerType>(valType);
3871 unsigned intBitWidth = intType ? intType.getWidth() : 0;
3872 if (intBitWidth != 8 && intBitWidth != 16 && intBitWidth != 32 &&
3874 return emitOpError(
"expected LLVM IR integer type");
3877 if (
static_cast<unsigned>(getOrdering()) <
3878 static_cast<unsigned>(AtomicOrdering::monotonic))
3879 return emitOpError() <<
"expected at least '"
3880 << stringifyAtomicOrdering(AtomicOrdering::monotonic)
3892 auto boolType = IntegerType::get(valType.
getContext(), 1);
3893 return LLVMStructType::getLiteral(valType.
getContext(), {valType, boolType});
3898 AtomicOrdering successOrdering,
3899 AtomicOrdering failureOrdering, StringRef syncscope,
3900 unsigned alignment,
bool isWeak,
bool isVolatile) {
3902 successOrdering, failureOrdering,
3903 !syncscope.empty() ? builder.
getStringAttr(syncscope) :
nullptr,
3905 isVolatile,
nullptr,
3906 nullptr,
nullptr,
nullptr);
3909LogicalResult AtomicCmpXchgOp::verify() {
3910 auto ptrType = llvm::cast<LLVM::LLVMPointerType>(getPtr().
getType());
3912 return emitOpError(
"expected LLVM IR pointer type for operand #0");
3913 auto valType = getVal().getType();
3916 return emitOpError(
"unexpected LLVM IR type");
3917 if (getSuccessOrdering() < AtomicOrdering::monotonic ||
3918 getFailureOrdering() < AtomicOrdering::monotonic)
3919 return emitOpError(
"ordering must be at least 'monotonic'");
3920 if (getFailureOrdering() == AtomicOrdering::release ||
3921 getFailureOrdering() == AtomicOrdering::acq_rel)
3922 return emitOpError(
"failure ordering cannot be 'release' or 'acq_rel'");
3931 AtomicOrdering ordering, StringRef syncscope) {
3932 build(builder, state, ordering,
3933 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
3936LogicalResult FenceOp::verify() {
3937 if (getOrdering() == AtomicOrdering::not_atomic ||
3938 getOrdering() == AtomicOrdering::unordered ||
3939 getOrdering() == AtomicOrdering::monotonic)
3940 return emitOpError(
"can be given only acquire, release, acq_rel, "
3941 "and seq_cst orderings");
3951template <
class ExtOp>
3953 IntegerType inputType, outputType;
3956 return op.emitError(
3957 "input type is a vector but output type is an integer");
3960 return op.emitError(
"input and output vectors are of incompatible shape");
3963 inputType = cast<IntegerType>(
3964 cast<VectorType>(op.getArg().getType()).getElementType());
3965 outputType = cast<IntegerType>(
3966 cast<VectorType>(op.getResult().getType()).getElementType());
3970 inputType = cast<IntegerType>(op.getArg().getType());
3971 outputType = dyn_cast<IntegerType>(op.getResult().getType());
3973 return op.emitError(
3974 "input type is an integer but output type is a vector");
3977 if (outputType.getWidth() <= inputType.getWidth())
3978 return op.emitError(
"integer width of the output type is smaller or "
3979 "equal to the integer width of the input type");
3990 auto arg = dyn_cast_or_null<IntegerAttr>(adaptor.getArg());
3994 size_t targetSize = cast<IntegerType>(
getType()).getWidth();
3995 return IntegerAttr::get(
getType(), arg.getValue().zext(targetSize));
4009template <
typename T>
4011 typename T::FoldAdaptor adaptor) {
4013 if (castOp.getArg().getType() == castOp.getType())
4014 return castOp.getArg();
4015 if (
auto prev = castOp.getArg().template getDefiningOp<T>()) {
4017 if (prev.getArg().getType() == castOp.getType())
4018 return prev.getArg();
4020 castOp.getArgMutable().set(prev.getArg());
4021 return Value{castOp};
4026OpFoldResult LLVM::BitcastOp::fold(FoldAdaptor adaptor) {
4030LogicalResult LLVM::BitcastOp::verify() {
4036 if (isa<LLVMByteType>(srcElemType) || isa<LLVMByteType>(dstElemType))
4039 auto resultType = llvm::dyn_cast<LLVMPointerType>(dstElemType);
4040 auto sourceType = llvm::dyn_cast<LLVMPointerType>(srcElemType);
4044 if (
static_cast<bool>(resultType) !=
static_cast<bool>(sourceType))
4045 return emitOpError(
"can only cast pointers from and to pointers");
4050 auto isVector = llvm::IsaPred<VectorType>;
4054 if (isVector(getResult().
getType()) && !isVector(getArg().
getType()))
4055 return emitOpError(
"cannot cast pointer to vector of pointers");
4057 if (!isVector(getResult().
getType()) && isVector(getArg().
getType()))
4058 return emitOpError(
"cannot cast vector of pointers to pointer");
4062 if (resultType.getAddressSpace() != sourceType.getAddressSpace())
4063 return emitOpError(
"cannot cast pointers of different address spaces, "
4064 "use 'llvm.addrspacecast' instead");
4069LogicalResult LLVM::PtrToAddrOp::verify() {
4076 assert(width &&
"pointers always return an index bitwidth");
4077 if (width != integerType.getWidth())
4078 return emitOpError(
"bit-width of integer result type ")
4079 << integerType <<
" must match the pointer bitwidth (" << *width
4080 <<
") specified in the datalayout";
4089OpFoldResult LLVM::AddrSpaceCastOp::fold(FoldAdaptor adaptor) {
4093Value LLVM::AddrSpaceCastOp::getViewSource() {
return getArg(); }
4101 adaptor.getDynamicIndices());
4104 if (getInrangeAttr())
4109 if (
auto integer = llvm::dyn_cast_or_null<IntegerAttr>(
indices[0]))
4110 if (integer.getValue().isZero())
4114 bool changed =
false;
4116 for (
auto iter : llvm::enumerate(
indices)) {
4117 auto integer = llvm::dyn_cast_or_null<IntegerAttr>(iter.value());
4120 if (!
indices.isDynamicIndex(iter.index()) || !integer ||
4124 if (
Value val = llvm::dyn_cast_if_present<Value>(existing))
4125 gepArgs.emplace_back(val);
4127 gepArgs.emplace_back(cast<IntegerAttr>(existing).getInt());
4133 gepArgs.emplace_back(integer.getInt());
4141 getDynamicIndicesMutable().assign(dynamicIndices);
4142 setRawConstantIndices(rawConstantIndices);
4143 return Value{*
this};
4149Value LLVM::GEPOp::getViewSource() {
return getBase(); }
4156 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
4160 if (rhs.getValue().uge(getLhs().
getType().getIntOrFloatBitWidth()))
4163 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
4167 return IntegerAttr::get(
getType(), lhs.getValue().shl(rhs.getValue()));
4175 auto lhs = dyn_cast_or_null<IntegerAttr>(adaptor.getLhs());
4179 auto rhs = dyn_cast_or_null<IntegerAttr>(adaptor.getRhs());
4183 return IntegerAttr::get(
getType(), lhs.getValue() | rhs.getValue());
4190LogicalResult CallIntrinsicOp::verify() {
4191 if (!getIntrin().starts_with(
"llvm."))
4192 return emitOpError() <<
"intrinsic name must start with 'llvm.'";
4200 build(builder, state,
TypeRange{}, intrin, args,
4201 FastmathFlagsAttr{},
4208 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4209 build(builder, state,
TypeRange{}, intrin, args,
4216 mlir::Type resultType, mlir::StringAttr intrin,
4218 build(builder, state, {resultType}, intrin, args, FastmathFlagsAttr{},
4226 mlir::LLVM::FastmathFlagsAttr fastMathFlags) {
4227 build(builder, state, resultTypes, intrin, args, fastMathFlags,
4232ParseResult CallIntrinsicOp::parse(
OpAsmParser &parser,
4234 StringAttr intrinAttr;
4244 result.addAttribute(CallIntrinsicOp::getIntrinAttrName(
result.name),
4252 return mlir::failure();
4255 return mlir::failure();
4260 parser, opBundleOperands, opBundleOperandTypes, opBundleTags);
4263 if (opBundleTags && !opBundleTags.empty())
4265 CallIntrinsicOp::getOpBundleTagsAttrName(
result.name).getValue(),
4269 return mlir::failure();
4274 operands, argAttrs, resultAttrs))
4278 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
4281 opBundleOperandTypes,
4282 getOpBundleSizesAttrName(
result.name)))
4285 int32_t numOpBundleOperands = 0;
4286 for (
const auto &operands : opBundleOperands)
4287 numOpBundleOperands += operands.size();
4290 CallIntrinsicOp::getOperandSegmentSizeAttr(),
4292 {static_cast<int32_t>(operands.size()), numOpBundleOperands}));
4294 return mlir::success();
4302 p <<
"(" << args <<
")";
4305 if (!getOpBundleOperands().empty()) {
4308 getOpBundleOperands().getTypes(), getOpBundleTagsAttr());
4312 {getOperandSegmentSizesAttrName(),
4313 getOpBundleSizesAttrName(), getIntrinAttrName(),
4314 getOpBundleTagsAttrName(), getArgAttrsAttrName(),
4315 getResAttrsAttrName()});
4321 p, args.
getTypes(), getArgAttrsAttr(),
4322 false, getResultTypes(), getResAttrsAttr());
4329LogicalResult LinkerOptionsOp::verify() {
4332 return emitOpError(
"must appear at the module level");
4340LogicalResult ModuleFlagsOp::verify() {
4343 return emitOpError(
"must appear at the module level");
4347 auto moduleFlag = dyn_cast<ModuleFlagAttrInterface>(flag);
4349 return emitOpError(
"expected a module flag attribute");
4351 moduleFlag.getModuleFlagKey(), moduleFlag.getModuleFlagValue(),
4352 [&] { return emitOpError(); })))
4354 if (moduleFlag.getModuleFlagBehavior() == ModFlagBehavior::Require)
4356 StringAttr key = moduleFlag.getModuleFlagKey();
4357 if (!seenNonRequireKeys.insert(key).second)
4358 return emitOpError(
"expected module flag key '")
4359 << key.getValue() <<
"' to be unique for non-require flags";
4368void InlineAsmOp::getEffects(
4371 if (getHasSideEffects()) {
4384 getBlockAddr().getFunction());
4385 auto function = dyn_cast_or_null<LLVMFuncOp>(symbol);
4388 return emitOpError(
"must reference a function defined by 'llvm.func'");
4398BlockTagOp BlockAddressOp::getBlockTagOp() {
4403 auto funcOp = dyn_cast<LLVMFuncOp>(sym);
4406 BlockTagOp blockTagOp =
nullptr;
4407 funcOp.walk([&](LLVM::BlockTagOp labelOp) {
4408 if (labelOp.getTag() == getBlockAddr().getTag()) {
4409 blockTagOp = labelOp;
4417LogicalResult BlockAddressOp::verify() {
4418 if (!getBlockTagOp())
4420 "expects an existing block label target in the referenced function");
4427OpFoldResult BlockAddressOp::fold(FoldAdaptor) {
return getBlockAddr(); }
4434 assert(
index < getNumSuccessors() &&
"invalid successor index");
4446 rangeSegments.push_back(range.size());
4460 Block *destination = nullptr;
4461 SmallVector<OpAsmParser::UnresolvedOperand> operands;
4462 SmallVector<Type> operandTypes;
4464 if (parser.parseSuccessor(destination).failed())
4467 if (succeeded(parser.parseOptionalLParen())) {
4468 if (failed(parser.parseOperandList(
4469 operands, OpAsmParser::Delimiter::None)) ||
4470 failed(parser.parseColonTypeList(operandTypes)) ||
4471 failed(parser.parseRParen()))
4474 succOperandBlocks.push_back(destination);
4475 succOperands.emplace_back(operands);
4476 succOperandsTypes.emplace_back(operandTypes);
4479 "successor blocks")))
4489 llvm::zip(succs, succOperands),
4495 if (!succOperands.empty())
4507 auto resultStructType =
4508 mlir::dyn_cast<mlir::LLVM::LLVMStructType>(resultType);
4509 if (!resultStructType || resultStructType.getBody().size() != 2 ||
4510 resultStructType.getBody()[0] != operandType ||
4511 resultStructType.getBody()[1] != operandType) {
4513 "expected result type to be a homogeneous struct with "
4514 "two elements matching the operand type, but got ")
4520LogicalResult LLVM::SincosOp::verify() {
4525LogicalResult LLVM::ModfOp::verify() {
4536 return build(builder, state, cond, {},
4548 return build(builder, state, cond,
"align",
ValueRange{
ptr, align});
4554 return build(builder, state, cond,
"separate_storage",
4564LogicalResult LLVM::masked_gather::verify() {
4565 auto ptrsVectorType = getPtrs().getType();
4566 Type expectedPtrsVectorType =
4571 if (ptrsVectorType != expectedPtrsVectorType)
4572 return emitOpError(
"expected operand #1 type to be ")
4573 << expectedPtrsVectorType;
4581LogicalResult LLVM::masked_scatter::verify() {
4582 auto ptrsVectorType = getPtrs().getType();
4583 Type expectedPtrsVectorType =
4588 if (ptrsVectorType != expectedPtrsVectorType)
4589 return emitOpError(
"expected operand #2 type to be ")
4590 << expectedPtrsVectorType;
4603 build(builder, state, resTys,
ptr, mask, passthru, argAttrs,
4611void LLVM::masked_compressstore::build(
OpBuilder &builder,
4616 build(builder, state, value,
ptr, mask, argAttrs,
4624LogicalResult InlineAsmOp::verify() {
4625 if (!getTailCallKindAttr())
4628 if (getTailCallKindAttr().getTailCallKind() == TailCallKind::MustTail)
4630 "tail call kind 'musttail' is not supported by this operation");
4640 Value divisor = getRhs();
4655 Value divisor = getRhs();
4667void LLVMDialect::initialize() {
4668 registerAttributes();
4671 addTypes<LLVMVoidType,
4673 LLVMMetadataType>();
4677 registerLLVMDialectOperations(
this);
4680 allowUnknownOperations();
4681 declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
4685LogicalResult LLVMDialect::verifyDataLayoutString(
4688 llvm::DataLayout::parse(descr);
4689 if (maybeDataLayout)
4692 std::string message;
4693 llvm::raw_string_ostream messageStream(message);
4694 llvm::logAllUnhandledErrors(maybeDataLayout.takeError(), messageStream);
4695 reportError(
"invalid data layout descriptor: " + message);
4700LogicalResult LLVMDialect::verifyOperationAttribute(
Operation *op,
4706 if (attr.
getName() != LLVM::LLVMDialect::getDataLayoutAttrName())
4708 if (
auto stringAttr = llvm::dyn_cast<StringAttr>(attr.
getValue()))
4709 return verifyDataLayoutString(
4710 stringAttr.getValue(),
4711 [op](
const Twine &message) { op->emitOpError() << message.str(); });
4714 << LLVM::LLVMDialect::getDataLayoutAttrName()
4715 <<
"' to be a string attributes";
4718LogicalResult LLVMDialect::verifyParameterAttribute(
Operation *op,
4726 StringAttr name = paramAttr.
getName();
4728 auto checkUnitAttrType = [&]() -> LogicalResult {
4729 if (!llvm::isa<UnitAttr>(paramAttr.
getValue()))
4730 return op->
emitError() << name <<
" should be a unit attribute";
4733 auto checkTypeAttrType = [&]() -> LogicalResult {
4734 if (!llvm::isa<TypeAttr>(paramAttr.
getValue()))
4735 return op->
emitError() << name <<
" should be a type attribute";
4738 auto checkIntegerAttrType = [&]() -> LogicalResult {
4739 if (!llvm::isa<IntegerAttr>(paramAttr.
getValue()))
4740 return op->
emitError() << name <<
" should be an integer attribute";
4743 auto checkPointerType = [&]() -> LogicalResult {
4744 if (!llvm::isa<LLVMPointerType>(paramType))
4746 << name <<
" attribute attached to non-pointer LLVM type";
4749 auto checkIntegerType = [&]() -> LogicalResult {
4750 if (!llvm::isa<IntegerType>(paramType))
4752 << name <<
" attribute attached to non-integer LLVM type";
4755 auto checkPointerTypeMatches = [&]() -> LogicalResult {
4756 if (
failed(checkPointerType()))
4763 if (name == LLVMDialect::getNoAliasAttrName() ||
4764 name == LLVMDialect::getReadonlyAttrName() ||
4765 name == LLVMDialect::getReadnoneAttrName() ||
4766 name == LLVMDialect::getWriteOnlyAttrName() ||
4767 name == LLVMDialect::getNestAttrName() ||
4768 name == LLVMDialect::getNoCaptureAttrName() ||
4769 name == LLVMDialect::getNoFreeAttrName() ||
4770 name == LLVMDialect::getNoFreeObjAttrName() ||
4771 name == LLVMDialect::getNonNullAttrName()) {
4772 if (
failed(checkUnitAttrType()))
4774 if (verifyValueType &&
failed(checkPointerType()))
4780 if (name == LLVMDialect::getStructRetAttrName() ||
4781 name == LLVMDialect::getByValAttrName() ||
4782 name == LLVMDialect::getByRefAttrName() ||
4783 name == LLVMDialect::getElementTypeAttrName() ||
4784 name == LLVMDialect::getInAllocaAttrName() ||
4785 name == LLVMDialect::getPreallocatedAttrName()) {
4786 if (
failed(checkTypeAttrType()))
4788 if (verifyValueType &&
failed(checkPointerTypeMatches()))
4794 if (name == LLVMDialect::getSExtAttrName() ||
4795 name == LLVMDialect::getZExtAttrName()) {
4796 if (
failed(checkUnitAttrType()))
4798 if (verifyValueType &&
failed(checkIntegerType()))
4804 if (name == LLVMDialect::getAlignAttrName() ||
4805 name == LLVMDialect::getDereferenceableAttrName() ||
4806 name == LLVMDialect::getDereferenceableOrNullAttrName()) {
4807 if (
failed(checkIntegerAttrType()))
4809 if (verifyValueType &&
failed(checkPointerType()))
4815 if (name == LLVMDialect::getStackAlignmentAttrName()) {
4816 if (
failed(checkIntegerAttrType()))
4822 if (name == LLVMDialect::getNoUndefAttrName() ||
4823 name == LLVMDialect::getInRegAttrName() ||
4824 name == LLVMDialect::getReturnedAttrName())
4825 return checkUnitAttrType();
4831LogicalResult LLVMDialect::verifyRegionArgAttribute(
Operation *op,
4835 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4838 Type argType = funcOp.getArgumentTypes()[argIdx];
4840 return verifyParameterAttribute(op, argType, argAttr);
4843LogicalResult LLVMDialect::verifyRegionResultAttribute(
Operation *op,
4847 auto funcOp = dyn_cast<FunctionOpInterface>(op);
4850 Type resType = funcOp.getResultTypes()[resIdx];
4854 if (llvm::isa<LLVMVoidType>(resType))
4855 return op->
emitError() <<
"cannot attach result attributes to functions "
4856 "with a void return";
4860 auto name = resAttr.
getName();
4861 if (name == LLVMDialect::getAllocAlignAttrName() ||
4862 name == LLVMDialect::getAllocatedPointerAttrName() ||
4863 name == LLVMDialect::getByValAttrName() ||
4864 name == LLVMDialect::getByRefAttrName() ||
4865 name == LLVMDialect::getInAllocaAttrName() ||
4866 name == LLVMDialect::getNestAttrName() ||
4867 name == LLVMDialect::getNoCaptureAttrName() ||
4868 name == LLVMDialect::getNoFreeAttrName() ||
4869 name == LLVMDialect::getPreallocatedAttrName() ||
4870 name == LLVMDialect::getReadnoneAttrName() ||
4871 name == LLVMDialect::getReadonlyAttrName() ||
4872 name == LLVMDialect::getReturnedAttrName() ||
4873 name == LLVMDialect::getStackAlignmentAttrName() ||
4874 name == LLVMDialect::getStructRetAttrName() ||
4875 name == LLVMDialect::getWriteOnlyAttrName())
4876 return op->
emitError() << name <<
" is not a valid result attribute";
4877 return verifyParameterAttribute(op, resType, resAttr);
4885 if (
auto symbol = dyn_cast<FlatSymbolRefAttr>(value))
4886 if (isa<LLVM::LLVMPointerType>(type))
4887 return LLVM::AddressOfOp::create(builder, loc, type, symbol);
4888 if (isa<LLVM::UndefAttr>(value))
4889 return LLVM::UndefOp::create(builder, loc, type);
4890 if (isa<LLVM::PoisonAttr>(value))
4891 return LLVM::PoisonOp::create(builder, loc, type);
4892 if (isa<LLVM::ZeroAttr>(value))
4893 return LLVM::ZeroOp::create(builder, loc, type);
4894 if (isa<LLVM::MDStringAttr, LLVM::MDConstantAttr, LLVM::MDGlobalValueAttr,
4895 LLVM::MDNodeAttr>(value))
4896 if (isa<LLVM::LLVMMetadataType>(type))
4897 return LLVM::MetadataAsValueOp::create(builder, loc, type, value);
4899 return LLVM::ConstantOp::materialize(builder, value, type, loc);
4907 StringRef name, StringRef value,
4908 LLVM::Linkage linkage) {
4911 "expected builder to point to a block constrained in an op");
4913 builder.getInsertionBlock()->getParentOp()->getParentOfType<ModuleOp>();
4914 assert(module &&
"builder points to an op outside of a module");
4919 auto type = LLVM::LLVMArrayType::get(IntegerType::get(ctx, 8), value.size());
4920 auto global = LLVM::GlobalOp::create(
4921 moduleBuilder, loc, type,
true, linkage, name,
4924 LLVMPointerType ptrType = LLVMPointerType::get(ctx);
4927 LLVM::AddressOfOp::create(builder, loc, ptrType, global.getSymNameAttr());
4928 return LLVM::GEPOp::create(builder, loc, ptrType, type, globalPtr,
4940 module = module->getParentOp();
4941 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 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 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 verifyCallOpDebugInfo(CallOp callOp, LLVMFuncOp callee)
Verify that an inlinable callsite of a debug-info-bearing function in a debug-info-bearing function h...
static LogicalResult verifyExtOp(ExtOp op)
Verifies that the given extension operation operates on consistent scalars or vectors,...
static constexpr const char kElemTypeAttrName[]
static LogicalResult verifyStructIndices(Type baseGEPType, unsigned indexPos, GEPIndicesAdaptor< ValueRange > indices, function_ref< InFlightDiagnostic()> emitOpError)
For the given indices, check if they comply with baseGEPType, especially check against LLVMStructType...
static Attribute extractElementAt(Attribute attr, size_t index)
Extracts the element at the given index from an attribute.
static int64_t getNumElements(Type t)
Compute the total number of elements in the given type, also taking into account nested types.
#define REGISTER_ENUM_TYPE(Ty)
static Operation::operand_range getArgOperandsImpl(OpTy callOp)
Return the operands of callOp that correspond to the declared parameters of the callee,...
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity,...
This base class exposes generic asm parser hooks, usable across the various derived parsers.
ParseResult parseSymbolName(StringAttr &result)
Parse an -identifier and store it (without the '@' symbol) in a string attribute.
@ Paren
Parens surrounding zero or more operands.
@ None
Zero or more operands with no delimiters.
@ Square
Square brackets surrounding zero or more operands.
virtual OptionalParseResult parseOptionalInteger(APInt &result)=0
Parse an optional integer value from the stream.
virtual ParseResult parseColonTypeList(SmallVectorImpl< Type > &result)=0
Parse a colon followed by a type list, which must have at least one type.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual ParseResult parseOptionalAttrDict(NamedAttrList &result)=0
Parse a named dictionary into 'result' if it is present.
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
MLIRContext * getContext() const
virtual ParseResult parseRParen()=0
Parse a ) token.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseLSquare()=0
Parse a [ token.
virtual ParseResult parseRSquare()=0
Parse a ] token.
virtual ParseResult parseOptionalColonTypeList(SmallVectorImpl< Type > &result)=0
Parse an optional colon followed by a type list, which if present must have at least one type.
ParseResult parseInteger(IntT &result)
Parse an integer value from the stream.
virtual ParseResult parseOptionalRParen()=0
Parse a ) token if present.
virtual ParseResult parseCustomAttributeWithFallback(Attribute &result, Type type, function_ref< ParseResult(Attribute &result, Type type)> parseAttribute)=0
Parse a custom attribute with the provided callback, unless the next token is #, in which case the ge...
ParseResult parseString(std::string *string)
Parse a quoted string token.
virtual ParseResult parseOptionalAttrDictWithKeyword(NamedAttrList &result)=0
Parse a named dictionary into 'result' if the attributes keyword is present.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseOptionalComma()=0
Parse a , token if present.
virtual ParseResult parseColon()=0
Parse a : token.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseOptionalRSquare()=0
Parse a ] token if present.
virtual ParseResult parseLParen()=0
Parse a ( token.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual ParseResult parseComma()=0
Parse a , token.
virtual ParseResult parseOptionalLParen()=0
Parse a ( token if present.
ParseResult parseTypeList(SmallVectorImpl< Type > &result)
Parse a type list.
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
virtual ParseResult parseOptionalLSquare()=0
Parse a [ token if present.
virtual ParseResult parseAttribute(Attribute &result, Type type={})=0
Parse an arbitrary attribute of a given type and return it in result.
This base class exposes generic asm printer hooks, usable across the various derived printers.
virtual void printAttributeWithoutType(Attribute attr)
Print the given attribute without its type.
virtual void printSymbolName(StringRef symbolRef)
Print the given string as a symbol reference, i.e.
virtual void printString(StringRef string)
Print the given string as a quoted string, escaping any special or non-printable characters in it.
virtual void printAttribute(Attribute attr)
virtual void printNewline()
Print a newline and indent the printer to the start of the current operation/attribute/type.
Attributes are known-constant values of operations.
MLIRContext * getContext() const
Return the context this attribute belongs to.
This class provides an abstraction over the different types of ranges over Blocks.
Block represents an ordered list of Operations.
BlockArgument getArgument(unsigned i)
Operation * getTerminator()
Get the terminator operation of this block.
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
static BoolAttr get(MLIRContext *context, bool value)
This class is a general helper class for creating context-global objects like types,...
IntegerAttr getI32IntegerAttr(int32_t value)
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
IntegerAttr getI64IntegerAttr(int64_t value)
Ty getType(Args &&...args)
Get or construct an instance of the type Ty with provided arguments.
StringAttr getStringAttr(const Twine &bytes)
TypedAttr getZeroAttr(Type type)
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
MLIRContext * getContext() const
DictionaryAttr getDictionaryAttr(ArrayRef< NamedAttribute > value)
NamedAttribute getNamedAttr(StringRef name, Attribute val)
ArrayAttr getStrArrayAttr(ArrayRef< StringRef > values)
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
The main mechanism for performing data layout queries.
static DataLayout closest(Operation *op)
Returns the layout of the closest parent operation carrying layout info.
std::optional< uint64_t > getTypeIndexBitwidth(Type t) const
Returns the bitwidth that should be used when performing index computations for the given pointer-lik...
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
An attribute that represents a reference to a dense integer vector or tensor object.
static DenseIntElementsAttr get(const ShapedType &type, Arg &&arg)
Get an instance of a DenseIntElementsAttr with the given arguments.
A symbol reference with a reference path containing a single element.
StringRef getValue() const
Returns the name of the held symbol reference.
StringAttr getAttr() const
Returns the name of the held symbol reference as a StringAttr.
This class represents a fused location whose metadata is known to be an instance of the given type.
This class represents a diagnostic that is inflight and set to be reported.
Diagnostic & attachNote(std::optional< Location > noteLoc=std::nullopt)
Attaches a note to this diagnostic.
Class used for building a 'llvm.getelementptr'.
Class used for convenient access and iteration over GEP indices.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
This class provides a mutable adaptor for a range of operands.
MutableOperandRange slice(unsigned subStart, unsigned subLen, std::optional< OperandSegment > segment=std::nullopt) const
Slice this range into a sub range, with the additional operand segment.
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
ArrayRef< NamedAttribute > getAttrs() const
Return all of the attributes on this operation.
Attribute set(StringAttr name, Attribute value)
If the an attribute exists with the specified name, change it to the new value.
NamedAttribute represents a combination of a name and an Attribute value.
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual ParseResult parseRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region.
virtual ParseResult parseSuccessor(Block *&dest)=0
Parse a single operation successor.
virtual ParseResult resolveOperand(const UnresolvedOperand &operand, Type type, SmallVectorImpl< Value > &result)=0
Resolve an operand to an SSA value, emitting an error on failure.
virtual OptionalParseResult parseOptionalOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single operand if present.
virtual ParseResult parseSuccessorAndUseList(Block *&dest, SmallVectorImpl< Value > &operands)=0
Parse a single operation successor and its operand list.
virtual OptionalParseResult parseOptionalRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region if present.
ParseResult resolveOperands(Operands &&operands, Type type, SmallVectorImpl< Value > &result)
Resolve a list of operands to SSA values, emitting an error on failure, or appending the results to t...
virtual ParseResult parseOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single SSA value operand name along with a result number if allowResultNumber is true.
virtual ParseResult parseOperandList(SmallVectorImpl< UnresolvedOperand > &result, Delimiter delimiter=Delimiter::None, bool allowResultNumber=true, int requiredOperandCount=-1)=0
Parse zero or more SSA comma-separated operand references with a specified surrounding delimiter,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual void printSuccessorAndUseList(Block *successor, ValueRange succOperands)=0
Print the successor and its operands.
void printOperands(OperandRange operands)
Print a comma separated range of operation operands out of line to avoid instantiating the range iter...
virtual void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary with their values.
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
virtual void printOperand(Value value)=0
Print implementations for various things an operation contains.
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
Listener * getListener() const
Returns the current listener of this builder, or nullptr if this builder doesn't have a listener.
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
This class represents a single result from folding an operation.
This class provides the API for ops that are known to be isolated from above.
A trait used to provide symbol table functionalities to a region operation.
This class represents a contiguous range of operand ranges, e.g.
This class implements the operand iterators for the Operation class.
type_range getTypes() const
void walkInherentAttrs(Operation *op, InherentAttrVisitor visitor) const
Visit the inherent attributes stored in the properties of op.
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
std::optional< Attribute > getInherentAttr(StringRef name)
Access an inherent attribute by name: returns an empty optional if there is no inherent attribute wit...
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
DictionaryAttr getRawDictionaryAttrs()
Return all attributes that are not stored as properties.
OperandRange operand_range
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
OperationName getName()
The name of an operation is the key identifier for it.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
This class implements Optional functionality for ParseResult.
ParseResult value() const
Access the internal ParseResult value.
bool has_value() const
Returns true if we contain a valid ParseResult value.
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
This class contains a list of basic blocks and a link to the parent operation it is attached to.
iterator_range< OpIterator > getOps()
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
void modifyOpInPlace(Operation *root, CallableT &&callable)
This method is a utility wrapper around an in-place modification of an operation.
This class represents a specific instance of an effect.
static DerivedEffect * get()
This class models how operands are forwarded to block arguments in control flow.
This class implements the successor iterators for Block.
This class represents a collection of SymbolTables.
virtual Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
virtual Operation * lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol)
Look up a symbol with the specified name within the specified symbol table operation,...
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
This class provides an abstraction for a range of TypeRange.
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
bool isSignlessIntOrIndexOrFloat() const
Return true if this is a signless integer, index, or float type.
This class provides an abstraction over the different types of ranges over Values.
type_range getTypes() const
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
A utility result that is used to signal how to proceed with an ongoing walk:
static WalkResult advance()
static WalkResult interrupt()
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int32_t > content)
ArrayRef< T > asArrayRef() const
A named class for passing around the variadic flag.
The OpAsmOpInterface, see OpAsmInterface.td for more details.
LogicalResult verifyModuleFlagValue(StringAttr key, Attribute value, function_ref< InFlightDiagnostic()> emitError)
Verifies that a module flag value can be exported to LLVM IR.
void addBytecodeInterface(LLVMDialect *dialect)
Add the interfaces necessary for encoding the LLVM dialect components in bytecode.
Value createGlobalString(Location loc, OpBuilder &builder, StringRef name, StringRef value, Linkage linkage)
Create an LLVM global containing the string "value" at the module containing surrounding the insertio...
Operation * parentLLVMModule(Operation *op)
Lookup parent Module satisfying LLVM conditions on the Module Operation.
Type getVectorType(Type elementType, unsigned numElements, bool isScalable=false)
Creates an LLVM dialect-compatible vector type with the given element type and length.
mlir::ParseResult parseCmpPredicate(mlir::OpAsmParser &parser, mlir::LLVM::ICmpPredicateAttr &predicate)
bool isScalableVectorType(Type vectorType)
Returns whether a vector type is scalable or not.
void printCmpPredicate(mlir::OpAsmPrinter &printer, mlir::Operation *, mlir::LLVM::ICmpPredicateAttr predicate)
mlir::ParseResult parseInsertExtractValueElementType(mlir::AsmParser &parser, mlir::Type &valueType, mlir::Type containerType, mlir::DenseI64ArrayAttr position)
Infer the value type from the container type and position.
void printLLVMLinkage(mlir::OpAsmPrinter &p, mlir::Operation *, mlir::LLVM::LinkageAttr val)
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
bool isCompatibleOuterType(Type type)
Returns true if the given outer type is compatible with the LLVM dialect without checking its potenti...
void printOpBundles(mlir::OpAsmPrinter &p, mlir::Operation *op, mlir::OperandRangeRange opBundleOperands, mlir::TypeRangeRange opBundleOperandTypes, std::optional< mlir::ArrayAttr > opBundleTags)
bool satisfiesLLVMModule(Operation *op)
LLVM requires some operations to be inside of a Module operation.
mlir::ParseResult parseShuffleType(mlir::AsmParser &parser, mlir::Type v1Type, mlir::Type &resType, mlir::DenseI32ArrayAttr mask)
Build the result type of a shuffle vector operation.
constexpr int kGEPConstantBitWidth
Bit-width of a 'GEPConstantIndex' within GEPArg.
void printShuffleType(mlir::AsmPrinter &printer, mlir::Operation *op, mlir::Type v1Type, mlir::Type resType, mlir::DenseI32ArrayAttr mask)
Nothing to do when the result type is inferred.
mlir::Type getI1SameShape(mlir::Type type)
Returns a boolean type that has the same shape as type.
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
bool isTypeCompatibleWithAtomicOp(Type type, const DataLayout &dataLayout)
Returns true if the given type is supported by atomic operations.
void printSwitchOpCases(mlir::OpAsmPrinter &p, mlir::LLVM::SwitchOp op, mlir::Type flagType, mlir::DenseIntElementsAttr caseValues, mlir::SuccessorRange caseDestinations, mlir::OperandRangeRange caseOperands, const mlir::TypeRangeRange &caseOperandTypes)
void printIndirectBrOpSucessors(mlir::OpAsmPrinter &p, mlir::LLVM::IndirectBrOp op, mlir::Type flagType, mlir::SuccessorRange succs, mlir::OperandRangeRange succOperands, const mlir::TypeRangeRange &succOperandsTypes)
mlir::ParseResult parseIndirectBrOpSucessors(mlir::OpAsmParser &parser, mlir::Type &flagType, mlir::SmallVectorImpl< mlir::Block * > &succOperandBlocks, mlir::SmallVectorImpl< mlir::SmallVector< mlir::OpAsmParser::UnresolvedOperand > > &succOperands, mlir::SmallVectorImpl< mlir::SmallVector< mlir::Type > > &succOperandsTypes)
mlir::ParseResult parseLLVMLinkage(mlir::OpAsmParser &p, mlir::LLVM::LinkageAttr &val)
mlir::LLVM::LLVMStructType getValAndBoolStructType(mlir::Type valType)
Returns an LLVM struct type that contains a value type and a boolean type.
bool isCompatibleFloatingPointType(Type type)
Returns true if the given type is a floating-point type compatible with the LLVM dialect.
std::optional< mlir::ParseResult > parseOpBundles(mlir::OpAsmParser &p, mlir::SmallVector< mlir::SmallVector< mlir::OpAsmParser::UnresolvedOperand > > &opBundleOperands, mlir::SmallVector< mlir::SmallVector< mlir::Type > > &opBundleOperandTypes, mlir::ArrayAttr &opBundleTags)
Type getConstantElementType(Type type)
Determines the element type of type the way the llvm.mlir.constant verifier does, i....
mlir::ParseResult parseGEPIndices(mlir::OpAsmParser &parser, mlir::SmallVectorImpl< mlir::OpAsmParser::UnresolvedOperand > &indices, mlir::DenseI32ArrayAttr &rawConstantIndices)
void printGEPIndices(mlir::OpAsmPrinter &printer, mlir::LLVM::GEPOp gepOp, mlir::OperandRange indices, mlir::DenseI32ArrayAttr rawConstantIndices)
void printInsertExtractValueElementType(mlir::AsmPrinter &printer, mlir::Operation *op, mlir::Type valueType, mlir::Type containerType, mlir::DenseI64ArrayAttr position)
Nothing to print for an inferred type.
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
mlir::ParseResult parseSwitchOpCases(mlir::OpAsmParser &parser, mlir::Type flagType, mlir::DenseIntElementsAttr &caseValues, mlir::SmallVectorImpl< mlir::Block * > &caseDestinations, mlir::SmallVectorImpl< mlir::SmallVector< mlir::OpAsmParser::UnresolvedOperand > > &caseOperands, mlir::SmallVectorImpl< mlir::SmallVector< mlir::Type > > &caseOperandTypes)
<cases> ::= [ (case (, case )* )?
Speculatability
This enum is returned from the getSpeculatability method in the ConditionallySpeculatable op interfac...
constexpr auto Speculatable
constexpr auto NotSpeculatable
void printFunctionSignature(OpAsmPrinter &p, TypeRange argTypes, ArrayAttr argAttrs, bool isVariadic, TypeRange resultTypes, ArrayAttr resultAttrs, Region *body=nullptr, bool printEmptyResult=true)
Print a function signature for a call or callable operation.
ParseResult parseFunctionSignature(OpAsmParser &parser, SmallVectorImpl< Type > &argTypes, SmallVectorImpl< DictionaryAttr > &argAttrs, SmallVectorImpl< Type > &resultTypes, SmallVectorImpl< DictionaryAttr > &resultAttrs, bool mustParseEmptyResult=true)
Parses a function signature using parser.
LogicalResult verifyCallOpInterface(CallOpInterface call, TypeRange argumentTypes, TypeRange resultTypes)
Verify that the forwarded operands and results of call are in a 1:1 relationship with the given argum...
void addArgAndResultAttrs(Builder &builder, OperationState &result, ArrayRef< DictionaryAttr > argAttrs, ArrayRef< DictionaryAttr > resultAttrs, StringAttr argAttrsName, StringAttr resAttrsName)
Adds argument and result attributes, provided as argAttrs and resultAttrs arguments,...
void walk(Operation *op, function_ref< void(Region *)> callback, WalkOrder order)
Walk all of the regions, blocks, or operations nested under (and including) the given operation.
ParseResult parseFunctionSignatureWithArguments(OpAsmParser &parser, bool allowVariadic, SmallVectorImpl< OpAsmParser::Argument > &arguments, bool &isVariadic, SmallVectorImpl< Type > &resultTypes, SmallVectorImpl< DictionaryAttr > &resultAttrs)
Parses a function signature using parser.
void printFunctionAttributes(OpAsmPrinter &p, Operation *op, ArrayRef< StringRef > elided={})
Prints the list of function prefixed with the "attributes" keyword.
void printFunctionSignature(OpAsmPrinter &p, FunctionOpInterface op, ArrayRef< Type > argTypes, bool isVariadic, ArrayRef< Type > resultTypes)
Prints the signature of the function-like operation op.
Operation::operand_range getIndices(Operation *op)
Get the indices that the given load/store operation is operating on.
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
detail::constant_int_value_binder m_ConstantInt(IntegerAttr::ValueType *bind_value)
Matches a constant holding a scalar/vector/tensor integer (splat) and writes the integer value to bin...
detail::DenseArrayAttrImpl< int64_t > DenseI64ArrayAttr
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
detail::constant_int_range_predicate_matcher m_IntRangeWithoutNegOneS()
Matches a constant scalar / vector splat / tensor splat integer or a signed integer range that does n...
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
detail::DenseArrayAttrImpl< int32_t > DenseI32ArrayAttr
llvm::TypeSwitch< T, ResultT > TypeSwitch
detail::constant_int_range_predicate_matcher m_IntRangeWithoutZeroS()
Matches a constant scalar / vector splat / tensor splat integer or a signed integer range that does n...
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
llvm::function_ref< Fn > function_ref
detail::constant_int_range_predicate_matcher m_IntRangeWithoutZeroU()
Matches a constant scalar / vector splat / tensor splat integer or a unsigned integer range that does...
A callable is either a symbol, or an SSA value, that is referenced by a call-like operation.
This is the representation of an operand reference.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
OpRewritePattern(MLIRContext *context, PatternBenefit benefit=1, ArrayRef< StringRef > generatedNames={})
Patterns must specify the root operation name they match against, and can also specify the benefit of...
This represents an operation in an abstracted form, suitable for use with the builder APIs.
T & getOrAddProperties()
Get (or create) the properties of the provided type to be set on the operation on creation.
SmallVector< Value, 4 > operands
void addOperands(ValueRange newOperands)
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
void addSuccessors(Block *successor)
Adds a successor to the operation sate. successor must not be null.