diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h --- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h @@ -210,6 +210,14 @@ LogicalResult convertCallTypeAndOperands(llvm::CallBase *callInst, SmallVectorImpl &types, SmallVectorImpl &operands); + /// Converts the parameter attributes attached to `func` and adds them to the + /// `funcOp`. + void convertParameterAttributes(llvm::Function *func, LLVMFuncOp funcOp, + OpBuilder &builder); + /// Converts the AttributeSet of one parameter in LLVM IR to a corresponding + /// DictionaryAttr for the LLVM dialect. + DictionaryAttr convertParameterAttribute(llvm::AttributeSet llvmParamAttrs, + OpBuilder &builder); /// Returns the builtin type equivalent to be used in attributes for the given /// LLVM IR dialect type. Type getStdTypeForAttr(Type type); diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -1482,6 +1482,61 @@ processPassthroughAttrs(func, funcOp); } +DictionaryAttr +ModuleImport::convertParameterAttribute(llvm::AttributeSet llvmParamAttrs, + OpBuilder &builder) { + using ElemTy = std::pair; + // Mapping from llvm attribute kinds to their corresponding MLIR name. + static const SmallVector kindNamePairs = { + {llvm::Attribute::AttrKind::NoAlias, LLVMDialect::getNoAliasAttrName()}, + {llvm::Attribute::AttrKind::ReadOnly, LLVMDialect::getReadonlyAttrName()}, + {llvm::Attribute::AttrKind::Nest, LLVMDialect::getNestAttrName()}, + {llvm::Attribute::AttrKind::SExt, LLVMDialect::getSExtAttrName()}, + {llvm::Attribute::AttrKind::ZExt, LLVMDialect::getZExtAttrName()}, + {llvm::Attribute::AttrKind::NoUndef, LLVMDialect::getNoUndefAttrName()}, + {llvm::Attribute::AttrKind::StructRet, + LLVMDialect::getStructRetAttrName()}, + {llvm::Attribute::AttrKind::ByVal, LLVMDialect::getByValAttrName()}, + {llvm::Attribute::AttrKind::ByRef, LLVMDialect::getByRefAttrName()}, + {llvm::Attribute::AttrKind::InAlloca, LLVMDialect::getInAllocaAttrName()}, + {llvm::Attribute::AttrKind::Alignment, LLVMDialect::getAlignAttrName()}}; + + SmallVector paramAttrs; + for (auto [llvmKind, mlirName] : kindNamePairs) { + auto llvmAttr = llvmParamAttrs.getAttribute(llvmKind); + // Skip attributes that are not attached. + if (!llvmAttr.isValid()) + continue; + Attribute mlirAttr; + if (llvmAttr.isTypeAttribute()) + mlirAttr = TypeAttr::get(convertType(llvmAttr.getValueAsType())); + else if (llvmAttr.isIntAttribute()) + mlirAttr = builder.getI64IntegerAttr(llvmAttr.getValueAsInt()); + else if (llvmAttr.isEnumAttribute()) + mlirAttr = builder.getUnitAttr(); + else + llvm_unreachable("unexpected parameter attribute kind"); + paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr)); + } + + return builder.getDictionaryAttr(paramAttrs); +} + +void ModuleImport::convertParameterAttributes(llvm::Function *func, + LLVMFuncOp funcOp, + OpBuilder &builder) { + auto llvmAttrs = func->getAttributes(); + for (size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) { + llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i); + funcOp.setArgAttrs(i, convertParameterAttribute(llvmArgAttrs, builder)); + } + // Convert the result attributes and attach them wrapped in an ArrayAttribute + // to the funcOp. + llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs(); + funcOp.setResAttrsAttr( + builder.getArrayAttr(convertParameterAttribute(llvmResAttr, builder))); +} + LogicalResult ModuleImport::processFunction(llvm::Function *func) { clearBlockAndValueMapping(); @@ -1505,35 +1560,7 @@ // Set the function debug information if available. debugImporter->translate(func, funcOp); - for (const auto &it : llvm::enumerate(functionType.getParams())) { - llvm::SmallVector argAttrs; - if (auto *type = func->getParamByValType(it.index())) { - Type mlirType = convertType(type); - argAttrs.push_back( - NamedAttribute(builder.getStringAttr(LLVMDialect::getByValAttrName()), - TypeAttr::get(mlirType))); - } - if (auto *type = func->getParamByRefType(it.index())) { - Type mlirType = convertType(type); - argAttrs.push_back( - NamedAttribute(builder.getStringAttr(LLVMDialect::getByRefAttrName()), - TypeAttr::get(mlirType))); - } - if (auto *type = func->getParamStructRetType(it.index())) { - Type mlirType = convertType(type); - argAttrs.push_back(NamedAttribute( - builder.getStringAttr(LLVMDialect::getStructRetAttrName()), - TypeAttr::get(mlirType))); - } - if (auto *type = func->getParamInAllocaType(it.index())) { - Type mlirType = convertType(type); - argAttrs.push_back(NamedAttribute( - builder.getStringAttr(LLVMDialect::getInAllocaAttrName()), - TypeAttr::get(mlirType))); - } - - funcOp.setArgAttrs(it.index(), argAttrs); - } + convertParameterAttributes(func, funcOp, builder); if (FlatSymbolRefAttr personality = getPersonalityAsAttr(func)) funcOp.setPersonalityAttr(personality); diff --git a/mlir/test/Target/LLVMIR/Import/function-attributes.ll b/mlir/test/Target/LLVMIR/Import/function-attributes.ll --- a/mlir/test/Target/LLVMIR/Import/function-attributes.ll +++ b/mlir/test/Target/LLVMIR/Import/function-attributes.ll @@ -31,14 +31,52 @@ ; CHECK-SAME: !llvm.ptr {llvm.byref = i64} ; CHECK-SAME: !llvm.ptr {llvm.sret = i64} ; CHECK-SAME: !llvm.ptr {llvm.inalloca = i64} +; CHECK-SAME: !llvm.ptr {llvm.noalias} +; CHECK-SAME: !llvm.ptr {llvm.readonly} +; CHECK-SAME: !llvm.ptr {llvm.nest} +; CHECK-SAME: i32 {llvm.signext} +; CHECK-SAME: i64 {llvm.zeroext} +; CHECK-SAME: !llvm.ptr {llvm.align = 64 : i64, llvm.noundef} define void @func_arg_attrs( ptr byval(i64) %arg0, ptr byref(i64) %arg1, ptr sret(i64) %arg2, - ptr inalloca(i64) %arg3) { + ptr inalloca(i64) %arg3, + ptr noalias %arg4, + ptr readonly %arg5, + ptr nest %arg6, + i32 signext %arg7, + i64 zeroext %arg8, + ptr align(64) noundef %arg9) { ret void } +; // ----- + +; CHECK-LABEL: @func_res_attr_align +; CHECK-SAME: !llvm.ptr {llvm.align = 16 : i64} +declare align(16) ptr @func_res_attr_align() + +; // ----- + +; CHECK-LABEL: @func_res_attr_noalias +; CHECK-SAME: !llvm.ptr {llvm.noalias} +declare noalias ptr @func_res_attr_noalias() + +; // ----- + +; CHECK-LABEL: @func_res_attr_signext +; CHECK-DAG: llvm.noundef +; CHECK-DAG: llvm.signext +declare noundef signext i32 @func_res_attr_signext() + +; // ----- + +; CHECK-LABEL: @func_res_attr_zeroext +; CHECK-SAME: i32 {llvm.zeroext} +declare zeroext i32 @func_res_attr_zeroext() + + ; // ----- ; CHECK-LABEL: @entry_count