Skip to content

Commit 473d001

Browse files
committed
[mlir][llvmir] Convert attributes for functions without bodies.
So far the function argument attributes were only translated for functions with bodies. This change makes sure that this happens for functions without bodies (declarations) as well. This is needed for llvm#58579 Reviewed By: ftynse Differential Revision: https://reviews.llvm.org/D137047
1 parent d97e8cd commit 473d001

File tree

4 files changed

+155
-102
lines changed

4 files changed

+155
-102
lines changed

flang/test/Fir/target.fir

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,13 @@ func.func @gen8() -> !fir.complex<8> {
4848
return %5 : !fir.complex<8>
4949
}
5050

51-
// I32: declare void @sink4(ptr)
51+
// I32: declare void @sink4(ptr byval({ float, float }) align 4)
5252
// X64: declare void @sink4(<2 x float>)
5353
// AARCH64: declare void @sink4([2 x float])
5454
// PPC: declare void @sink4(float, float)
5555
func.func private @sink4(!fir.complex<4>) -> ()
5656

57-
// I32: declare void @sink8(ptr)
57+
// I32: declare void @sink8(ptr byval({ double, double }) align 4)
5858
// X64: declare void @sink8(double, double)
5959
// AARCH64: declare void @sink8([2 x double])
6060
// PPC: declare void @sink8(double, double)

mlir/lib/Target/LLVMIR/ModuleTranslation.cpp

Lines changed: 101 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -826,107 +826,9 @@ LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
826826
debugTranslation->translate(func, *llvmFunc);
827827

828828
// Add function arguments to the value remapping table.
829-
// If there was noalias info then we decorate each argument accordingly.
830-
unsigned int argIdx = 0;
831-
for (auto kvp : llvm::zip(func.getArguments(), llvmFunc->args())) {
832-
llvm::Argument &llvmArg = std::get<1>(kvp);
833-
BlockArgument mlirArg = std::get<0>(kvp);
834-
835-
if (auto attr = func.getArgAttrOfType<UnitAttr>(
836-
argIdx, LLVMDialect::getNoAliasAttrName())) {
837-
// NB: Attribute already verified to be boolean, so check if we can indeed
838-
// attach the attribute to this argument, based on its type.
839-
auto argTy = mlirArg.getType();
840-
if (!argTy.isa<LLVM::LLVMPointerType>())
841-
return func.emitError(
842-
"llvm.noalias attribute attached to LLVM non-pointer argument");
843-
llvmArg.addAttr(llvm::Attribute::AttrKind::NoAlias);
844-
}
845-
846-
if (auto attr = func.getArgAttrOfType<IntegerAttr>(
847-
argIdx, LLVMDialect::getAlignAttrName())) {
848-
// NB: Attribute already verified to be int, so check if we can indeed
849-
// attach the attribute to this argument, based on its type.
850-
auto argTy = mlirArg.getType();
851-
if (!argTy.isa<LLVM::LLVMPointerType>())
852-
return func.emitError(
853-
"llvm.align attribute attached to LLVM non-pointer argument");
854-
llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext())
855-
.addAlignmentAttr(llvm::Align(attr.getInt())));
856-
}
857-
858-
if (auto attr = func.getArgAttrOfType<TypeAttr>(
859-
argIdx, LLVMDialect::getStructRetAttrName())) {
860-
auto argTy = mlirArg.getType().dyn_cast<LLVM::LLVMPointerType>();
861-
if (!argTy)
862-
return func.emitError(
863-
"llvm.sret attribute attached to LLVM non-pointer argument");
864-
if (!argTy.isOpaque() && argTy.getElementType() != attr.getValue())
865-
return func.emitError("llvm.sret attribute attached to LLVM pointer "
866-
"argument of a different type");
867-
llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext())
868-
.addStructRetAttr(convertType(attr.getValue())));
869-
}
870-
871-
if (auto attr = func.getArgAttrOfType<TypeAttr>(
872-
argIdx, LLVMDialect::getByValAttrName())) {
873-
auto argTy = mlirArg.getType().dyn_cast<LLVM::LLVMPointerType>();
874-
if (!argTy)
875-
return func.emitError(
876-
"llvm.byval attribute attached to LLVM non-pointer argument");
877-
if (!argTy.isOpaque() && argTy.getElementType() != attr.getValue())
878-
return func.emitError("llvm.byval attribute attached to LLVM pointer "
879-
"argument of a different type");
880-
llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext())
881-
.addByValAttr(convertType(attr.getValue())));
882-
}
883-
884-
if (auto attr = func.getArgAttrOfType<TypeAttr>(
885-
argIdx, LLVMDialect::getByRefAttrName())) {
886-
auto argTy = mlirArg.getType().dyn_cast<LLVM::LLVMPointerType>();
887-
if (!argTy)
888-
return func.emitError(
889-
"llvm.byref attribute attached to LLVM non-pointer argument");
890-
if (!argTy.isOpaque() && argTy.getElementType() != attr.getValue())
891-
return func.emitError("llvm.byref attribute attached to LLVM pointer "
892-
"argument of a different type");
893-
llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext())
894-
.addByRefAttr(convertType(attr.getValue())));
895-
}
896-
897-
if (auto attr = func.getArgAttrOfType<TypeAttr>(
898-
argIdx, LLVMDialect::getInAllocaAttrName())) {
899-
auto argTy = mlirArg.getType().dyn_cast<LLVM::LLVMPointerType>();
900-
if (!argTy)
901-
return func.emitError(
902-
"llvm.inalloca attribute attached to LLVM non-pointer argument");
903-
if (!argTy.isOpaque() && argTy.getElementType() != attr.getValue())
904-
return func.emitError(
905-
"llvm.inalloca attribute attached to LLVM pointer "
906-
"argument of a different type");
907-
llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext())
908-
.addInAllocaAttr(convertType(attr.getValue())));
909-
}
910-
911-
if (auto attr = func.getArgAttrOfType<UnitAttr>(argIdx, "llvm.nest")) {
912-
auto argTy = mlirArg.getType();
913-
if (!argTy.isa<LLVM::LLVMPointerType>())
914-
return func.emitError(
915-
"llvm.nest attribute attached to LLVM non-pointer argument");
916-
llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext())
917-
.addAttribute(llvm::Attribute::Nest));
918-
}
919-
920-
if (auto attr = func.getArgAttrOfType<UnitAttr>(
921-
argIdx, LLVMDialect::getNoUndefAttrName())) {
922-
// llvm.noundef can be added to any argument type.
923-
llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext())
924-
.addAttribute(llvm::Attribute::NoUndef));
925-
}
926-
829+
for (auto [mlirArg, llvmArg] :
830+
llvm::zip(func.getArguments(), llvmFunc->args()))
927831
mapValue(mlirArg, &llvmArg);
928-
argIdx++;
929-
}
930832

931833
// Check the personality and set it.
932834
if (func.getPersonality()) {
@@ -986,6 +888,105 @@ LogicalResult ModuleTranslation::convertFunctionSignatures() {
986888
if (function->getAttrOfType<UnitAttr>(LLVMDialect::getReadnoneAttrName()))
987889
llvmFunc->setDoesNotAccessMemory();
988890

891+
// Convert argument attributes.
892+
unsigned int argIdx = 0;
893+
for (auto [mlirArgTy, llvmArg] :
894+
llvm::zip(function.getArgumentTypes(), llvmFunc->args())) {
895+
if (auto attr = function.getArgAttrOfType<UnitAttr>(
896+
argIdx, LLVMDialect::getNoAliasAttrName())) {
897+
// NB: Attribute already verified to be boolean, so check if we can
898+
// indeed attach the attribute to this argument, based on its type.
899+
if (!mlirArgTy.isa<LLVM::LLVMPointerType>())
900+
return function.emitError(
901+
"llvm.noalias attribute attached to LLVM non-pointer argument");
902+
llvmArg.addAttr(llvm::Attribute::AttrKind::NoAlias);
903+
}
904+
905+
if (auto attr = function.getArgAttrOfType<IntegerAttr>(
906+
argIdx, LLVMDialect::getAlignAttrName())) {
907+
// NB: Attribute already verified to be int, so check if we can indeed
908+
// attach the attribute to this argument, based on its type.
909+
if (!mlirArgTy.isa<LLVM::LLVMPointerType>())
910+
return function.emitError(
911+
"llvm.align attribute attached to LLVM non-pointer argument");
912+
llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext())
913+
.addAlignmentAttr(llvm::Align(attr.getInt())));
914+
}
915+
916+
if (auto attr = function.getArgAttrOfType<TypeAttr>(
917+
argIdx, LLVMDialect::getStructRetAttrName())) {
918+
auto argTy = mlirArgTy.dyn_cast<LLVM::LLVMPointerType>();
919+
if (!argTy)
920+
return function.emitError(
921+
"llvm.sret attribute attached to LLVM non-pointer argument");
922+
if (!argTy.isOpaque() && argTy.getElementType() != attr.getValue())
923+
return function.emitError(
924+
"llvm.sret attribute attached to LLVM pointer "
925+
"argument of a different type");
926+
llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext())
927+
.addStructRetAttr(convertType(attr.getValue())));
928+
}
929+
930+
if (auto attr = function.getArgAttrOfType<TypeAttr>(
931+
argIdx, LLVMDialect::getByValAttrName())) {
932+
auto argTy = mlirArgTy.dyn_cast<LLVM::LLVMPointerType>();
933+
if (!argTy)
934+
return function.emitError(
935+
"llvm.byval attribute attached to LLVM non-pointer argument");
936+
if (!argTy.isOpaque() && argTy.getElementType() != attr.getValue())
937+
return function.emitError(
938+
"llvm.byval attribute attached to LLVM pointer "
939+
"argument of a different type");
940+
llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext())
941+
.addByValAttr(convertType(attr.getValue())));
942+
}
943+
944+
if (auto attr = function.getArgAttrOfType<TypeAttr>(
945+
argIdx, LLVMDialect::getByRefAttrName())) {
946+
auto argTy = mlirArgTy.dyn_cast<LLVM::LLVMPointerType>();
947+
if (!argTy)
948+
return function.emitError(
949+
"llvm.byref attribute attached to LLVM non-pointer argument");
950+
if (!argTy.isOpaque() && argTy.getElementType() != attr.getValue())
951+
return function.emitError(
952+
"llvm.byref attribute attached to LLVM pointer "
953+
"argument of a different type");
954+
llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext())
955+
.addByRefAttr(convertType(attr.getValue())));
956+
}
957+
958+
if (auto attr = function.getArgAttrOfType<TypeAttr>(
959+
argIdx, LLVMDialect::getInAllocaAttrName())) {
960+
auto argTy = mlirArgTy.dyn_cast<LLVM::LLVMPointerType>();
961+
if (!argTy)
962+
return function.emitError(
963+
"llvm.inalloca attribute attached to LLVM non-pointer argument");
964+
if (!argTy.isOpaque() && argTy.getElementType() != attr.getValue())
965+
return function.emitError(
966+
"llvm.inalloca attribute attached to LLVM pointer "
967+
"argument of a different type");
968+
llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext())
969+
.addInAllocaAttr(convertType(attr.getValue())));
970+
}
971+
972+
if (auto attr =
973+
function.getArgAttrOfType<UnitAttr>(argIdx, "llvm.nest")) {
974+
if (!mlirArgTy.isa<LLVM::LLVMPointerType>())
975+
return function.emitError(
976+
"llvm.nest attribute attached to LLVM non-pointer argument");
977+
llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext())
978+
.addAttribute(llvm::Attribute::Nest));
979+
}
980+
981+
if (auto attr = function.getArgAttrOfType<UnitAttr>(
982+
argIdx, LLVMDialect::getNoUndefAttrName())) {
983+
// llvm.noundef can be added to any argument type.
984+
llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext())
985+
.addAttribute(llvm::Attribute::NoUndef));
986+
}
987+
++argIdx;
988+
}
989+
989990
// Forward the pass-through attributes to LLVM.
990991
if (failed(forwardPassthroughAttributes(
991992
function.getLoc(), function.getPassthrough(), llvmFunc)))

mlir/test/Dialect/LLVMIR/func.mlir

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,24 @@ module {
104104
llvm.return
105105
}
106106

107+
// CHECK: llvm.func @llvm_noalias_decl(!llvm.ptr<f32> {llvm.noalias})
108+
llvm.func @llvm_noalias_decl(!llvm.ptr<f32> {llvm.noalias})
109+
// CHECK: llvm.func @byrefattr_decl(!llvm.ptr<i32> {llvm.byref = i32})
110+
llvm.func @byrefattr_decl(!llvm.ptr<i32> {llvm.byref = i32})
111+
// CHECK: llvm.func @byvalattr_decl(!llvm.ptr<i32> {llvm.byval = i32})
112+
llvm.func @byvalattr_decl(!llvm.ptr<i32> {llvm.byval = i32})
113+
// CHECK: llvm.func @sretattr_decl(!llvm.ptr<i32> {llvm.sret = i32})
114+
llvm.func @sretattr_decl(!llvm.ptr<i32> {llvm.sret = i32})
115+
// CHECK: llvm.func @nestattr_decl(!llvm.ptr<i32> {llvm.nest})
116+
llvm.func @nestattr_decl(!llvm.ptr<i32> {llvm.nest})
117+
// CHECK: llvm.func @noundefattr_decl(i32 {llvm.noundef})
118+
llvm.func @noundefattr_decl(i32 {llvm.noundef})
119+
// CHECK: llvm.func @llvm_align_decl(!llvm.ptr<f32> {llvm.align = 4 : i64})
120+
llvm.func @llvm_align_decl(!llvm.ptr<f32> {llvm.align = 4})
121+
// CHECK: llvm.func @inallocaattr_decl(!llvm.ptr<i32> {llvm.inalloca = i32})
122+
llvm.func @inallocaattr_decl(!llvm.ptr<i32> {llvm.inalloca = i32})
123+
124+
107125
// CHECK: llvm.func @variadic(...)
108126
llvm.func @variadic(...)
109127

mlir/test/Target/LLVMIR/llvmir.mlir

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,31 +1049,65 @@ llvm.func @llvm_noalias(%arg0: !llvm.ptr<f32> {llvm.noalias}) {
10491049
llvm.return
10501050
}
10511051

1052+
// CHECK-LABEL: declare void @llvm_noalias_decl(ptr noalias)
1053+
llvm.func @llvm_noalias_decl(!llvm.ptr<f32> {llvm.noalias})
1054+
1055+
// CHECK-LABEL: define void @byrefattr(ptr byref(i32) %
1056+
llvm.func @byrefattr(%arg0: !llvm.ptr<i32> {llvm.byref = i32}) {
1057+
llvm.return
1058+
}
1059+
1060+
// CHECK-LABEL: declare void @byrefattr_decl(ptr byref(i32))
1061+
llvm.func @byrefattr_decl(!llvm.ptr<i32> {llvm.byref = i32})
1062+
10521063
// CHECK-LABEL: define void @byvalattr(ptr byval(i32) %
10531064
llvm.func @byvalattr(%arg0: !llvm.ptr<i32> {llvm.byval = i32}) {
10541065
llvm.return
10551066
}
10561067

1068+
// CHECK-LABEL: declare void @byvalattr_decl(ptr byval(i32))
1069+
llvm.func @byvalattr_decl(!llvm.ptr<i32> {llvm.byval = i32})
1070+
10571071
// CHECK-LABEL: define void @sretattr(ptr sret(i32) %
10581072
llvm.func @sretattr(%arg0: !llvm.ptr<i32> {llvm.sret = i32}) {
10591073
llvm.return
10601074
}
10611075

1076+
// CHECK-LABEL: declare void @sretattr_decl(ptr sret(i32))
1077+
llvm.func @sretattr_decl(!llvm.ptr<i32> {llvm.sret = i32})
1078+
10621079
// CHECK-LABEL: define void @nestattr(ptr nest %
10631080
llvm.func @nestattr(%arg0: !llvm.ptr<i32> {llvm.nest}) {
10641081
llvm.return
10651082
}
10661083

1084+
// CHECK-LABEL: declare void @nestattr_decl(ptr nest)
1085+
llvm.func @nestattr_decl(!llvm.ptr<i32> {llvm.nest})
1086+
10671087
// CHECK-LABEL: define void @noundefattr(i32 noundef %
10681088
llvm.func @noundefattr(%arg0: i32 {llvm.noundef}) {
10691089
llvm.return
10701090
}
10711091

1092+
// CHECK-LABEL: declare void @noundefattr_decl(i32 noundef)
1093+
llvm.func @noundefattr_decl(i32 {llvm.noundef})
1094+
10721095
// CHECK-LABEL: define void @llvm_align(ptr align 4 {{%*.}})
10731096
llvm.func @llvm_align(%arg0: !llvm.ptr<f32> {llvm.align = 4}) {
10741097
llvm.return
10751098
}
10761099

1100+
// CHECK-LABEL: declare void @llvm_align_decl(ptr align 4)
1101+
llvm.func @llvm_align_decl(!llvm.ptr<f32> {llvm.align = 4})
1102+
1103+
// CHECK-LABEL: define void @inallocaattr(ptr inalloca(i32) %
1104+
llvm.func @inallocaattr(%arg0: !llvm.ptr<i32> {llvm.inalloca = i32}) {
1105+
llvm.return
1106+
}
1107+
1108+
// CHECK-LABEL: declare void @inallocaattr_decl(ptr inalloca(i32))
1109+
llvm.func @inallocaattr_decl(!llvm.ptr<i32> {llvm.inalloca = i32})
1110+
10771111
// CHECK-LABEL: @llvm_varargs(...)
10781112
llvm.func @llvm_varargs(...)
10791113

0 commit comments

Comments
 (0)