Index: flang/test/Fir/target.fir =================================================================== --- flang/test/Fir/target.fir +++ flang/test/Fir/target.fir @@ -48,13 +48,13 @@ return %5 : !fir.complex<8> } -// I32: declare void @sink4(ptr) +// I32: declare void @sink4(ptr byval({ float, float }) align 4) // X64: declare void @sink4(<2 x float>) // AARCH64: declare void @sink4([2 x float]) // PPC: declare void @sink4(float, float) func.func private @sink4(!fir.complex<4>) -> () -// I32: declare void @sink8(ptr) +// I32: declare void @sink8(ptr byval({ double, double }) align 4) // X64: declare void @sink8(double, double) // AARCH64: declare void @sink8([2 x double]) // PPC: declare void @sink8(double, double) Index: mlir/lib/Target/LLVMIR/ModuleTranslation.cpp =================================================================== --- mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -826,104 +826,10 @@ debugTranslation->translate(func, *llvmFunc); // Add function arguments to the value remapping table. - // If there was noalias info then we decorate each argument accordingly. unsigned int argIdx = 0; for (auto kvp : llvm::zip(func.getArguments(), llvmFunc->args())) { llvm::Argument &llvmArg = std::get<1>(kvp); BlockArgument mlirArg = std::get<0>(kvp); - - if (auto attr = func.getArgAttrOfType( - argIdx, LLVMDialect::getNoAliasAttrName())) { - // NB: Attribute already verified to be boolean, so check if we can indeed - // attach the attribute to this argument, based on its type. - auto argTy = mlirArg.getType(); - if (!argTy.isa()) - return func.emitError( - "llvm.noalias attribute attached to LLVM non-pointer argument"); - llvmArg.addAttr(llvm::Attribute::AttrKind::NoAlias); - } - - if (auto attr = func.getArgAttrOfType( - argIdx, LLVMDialect::getAlignAttrName())) { - // NB: Attribute already verified to be int, so check if we can indeed - // attach the attribute to this argument, based on its type. - auto argTy = mlirArg.getType(); - if (!argTy.isa()) - return func.emitError( - "llvm.align attribute attached to LLVM non-pointer argument"); - llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext()) - .addAlignmentAttr(llvm::Align(attr.getInt()))); - } - - if (auto attr = func.getArgAttrOfType( - argIdx, LLVMDialect::getStructRetAttrName())) { - auto argTy = mlirArg.getType().dyn_cast(); - if (!argTy) - return func.emitError( - "llvm.sret attribute attached to LLVM non-pointer argument"); - if (!argTy.isOpaque() && argTy.getElementType() != attr.getValue()) - return func.emitError("llvm.sret attribute attached to LLVM pointer " - "argument of a different type"); - llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext()) - .addStructRetAttr(convertType(attr.getValue()))); - } - - if (auto attr = func.getArgAttrOfType( - argIdx, LLVMDialect::getByValAttrName())) { - auto argTy = mlirArg.getType().dyn_cast(); - if (!argTy) - return func.emitError( - "llvm.byval attribute attached to LLVM non-pointer argument"); - if (!argTy.isOpaque() && argTy.getElementType() != attr.getValue()) - return func.emitError("llvm.byval attribute attached to LLVM pointer " - "argument of a different type"); - llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext()) - .addByValAttr(convertType(attr.getValue()))); - } - - if (auto attr = func.getArgAttrOfType( - argIdx, LLVMDialect::getByRefAttrName())) { - auto argTy = mlirArg.getType().dyn_cast(); - if (!argTy) - return func.emitError( - "llvm.byref attribute attached to LLVM non-pointer argument"); - if (!argTy.isOpaque() && argTy.getElementType() != attr.getValue()) - return func.emitError("llvm.byref attribute attached to LLVM pointer " - "argument of a different type"); - llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext()) - .addByRefAttr(convertType(attr.getValue()))); - } - - if (auto attr = func.getArgAttrOfType( - argIdx, LLVMDialect::getInAllocaAttrName())) { - auto argTy = mlirArg.getType().dyn_cast(); - if (!argTy) - return func.emitError( - "llvm.inalloca attribute attached to LLVM non-pointer argument"); - if (!argTy.isOpaque() && argTy.getElementType() != attr.getValue()) - return func.emitError( - "llvm.inalloca attribute attached to LLVM pointer " - "argument of a different type"); - llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext()) - .addInAllocaAttr(convertType(attr.getValue()))); - } - - if (auto attr = func.getArgAttrOfType(argIdx, "llvm.nest")) { - auto argTy = mlirArg.getType(); - if (!argTy.isa()) - return func.emitError( - "llvm.nest attribute attached to LLVM non-pointer argument"); - llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext()) - .addAttribute(llvm::Attribute::Nest)); - } - - if (auto attr = func.getArgAttrOfType( - argIdx, LLVMDialect::getNoUndefAttrName())) { - // llvm.noundef can be added to any argument type. - llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext()) - .addAttribute(llvm::Attribute::NoUndef)); - } - mapValue(mlirArg, &llvmArg); argIdx++; } @@ -986,6 +892,106 @@ if (function->getAttrOfType(LLVMDialect::getReadnoneAttrName())) llvmFunc->setDoesNotAccessMemory(); + // Convert argument attributes. + unsigned int argIdx = 0; + for (auto kvp : llvm::zip(function.getArgumentTypes(), llvmFunc->args())) { + mlir::Type mlirArgTy = std::get<0>(kvp); + llvm::Argument &llvmArg = std::get<1>(kvp); + if (auto attr = function.getArgAttrOfType( + argIdx, LLVMDialect::getNoAliasAttrName())) { + // NB: Attribute already verified to be boolean, so check if we can + // indeed attach the attribute to this argument, based on its type. + if (!mlirArgTy.isa()) + return function.emitError( + "llvm.noalias attribute attached to LLVM non-pointer argument"); + llvmArg.addAttr(llvm::Attribute::AttrKind::NoAlias); + } + + if (auto attr = function.getArgAttrOfType( + argIdx, LLVMDialect::getAlignAttrName())) { + // NB: Attribute already verified to be int, so check if we can indeed + // attach the attribute to this argument, based on its type. + if (!mlirArgTy.isa()) + return function.emitError( + "llvm.align attribute attached to LLVM non-pointer argument"); + llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext()) + .addAlignmentAttr(llvm::Align(attr.getInt()))); + } + + if (auto attr = function.getArgAttrOfType( + argIdx, LLVMDialect::getStructRetAttrName())) { + auto argTy = mlirArgTy.dyn_cast(); + if (!argTy) + return function.emitError( + "llvm.sret attribute attached to LLVM non-pointer argument"); + if (!argTy.isOpaque() && argTy.getElementType() != attr.getValue()) + return function.emitError( + "llvm.sret attribute attached to LLVM pointer " + "argument of a different type"); + llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext()) + .addStructRetAttr(convertType(attr.getValue()))); + } + + if (auto attr = function.getArgAttrOfType( + argIdx, LLVMDialect::getByValAttrName())) { + auto argTy = mlirArgTy.dyn_cast(); + if (!argTy) + return function.emitError( + "llvm.byval attribute attached to LLVM non-pointer argument"); + if (!argTy.isOpaque() && argTy.getElementType() != attr.getValue()) + return function.emitError( + "llvm.byval attribute attached to LLVM pointer " + "argument of a different type"); + llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext()) + .addByValAttr(convertType(attr.getValue()))); + } + + if (auto attr = function.getArgAttrOfType( + argIdx, LLVMDialect::getByRefAttrName())) { + auto argTy = mlirArgTy.dyn_cast(); + if (!argTy) + return function.emitError( + "llvm.byref attribute attached to LLVM non-pointer argument"); + if (!argTy.isOpaque() && argTy.getElementType() != attr.getValue()) + return function.emitError( + "llvm.byref attribute attached to LLVM pointer " + "argument of a different type"); + llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext()) + .addByRefAttr(convertType(attr.getValue()))); + } + + if (auto attr = function.getArgAttrOfType( + argIdx, LLVMDialect::getInAllocaAttrName())) { + auto argTy = mlirArgTy.dyn_cast(); + if (!argTy) + return function.emitError( + "llvm.inalloca attribute attached to LLVM non-pointer argument"); + if (!argTy.isOpaque() && argTy.getElementType() != attr.getValue()) + return function.emitError( + "llvm.inalloca attribute attached to LLVM pointer " + "argument of a different type"); + llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext()) + .addInAllocaAttr(convertType(attr.getValue()))); + } + + if (auto attr = + function.getArgAttrOfType(argIdx, "llvm.nest")) { + if (!mlirArgTy.isa()) + return function.emitError( + "llvm.nest attribute attached to LLVM non-pointer argument"); + llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext()) + .addAttribute(llvm::Attribute::Nest)); + } + + if (auto attr = function.getArgAttrOfType( + argIdx, LLVMDialect::getNoUndefAttrName())) { + // llvm.noundef can be added to any argument type. + llvmArg.addAttrs(llvm::AttrBuilder(llvmArg.getContext()) + .addAttribute(llvm::Attribute::NoUndef)); + } + ++argIdx; + } + // Forward the pass-through attributes to LLVM. if (failed(forwardPassthroughAttributes( function.getLoc(), function.getPassthrough(), llvmFunc))) Index: mlir/test/Dialect/LLVMIR/func.mlir =================================================================== --- mlir/test/Dialect/LLVMIR/func.mlir +++ mlir/test/Dialect/LLVMIR/func.mlir @@ -104,6 +104,24 @@ llvm.return } + // CHECK: llvm.func @llvm_noalias_decl(!llvm.ptr {llvm.noalias}) + llvm.func @llvm_noalias_decl(!llvm.ptr {llvm.noalias}) + // CHECK: llvm.func @byrefattr_decl(!llvm.ptr {llvm.byref = i32}) + llvm.func @byrefattr_decl(!llvm.ptr {llvm.byref = i32}) + // CHECK: llvm.func @byvalattr_decl(!llvm.ptr {llvm.byval = i32}) + llvm.func @byvalattr_decl(!llvm.ptr {llvm.byval = i32}) + // CHECK: llvm.func @sretattr_decl(!llvm.ptr {llvm.sret = i32}) + llvm.func @sretattr_decl(!llvm.ptr {llvm.sret = i32}) + // CHECK: llvm.func @nestattr_decl(!llvm.ptr {llvm.nest}) + llvm.func @nestattr_decl(!llvm.ptr {llvm.nest}) + // CHECK: llvm.func @noundefattr_decl(i32 {llvm.noundef}) + llvm.func @noundefattr_decl(i32 {llvm.noundef}) + // CHECK: llvm.func @llvm_align_decl(!llvm.ptr {llvm.align = 4 : i64}) + llvm.func @llvm_align_decl(!llvm.ptr {llvm.align = 4}) + // CHECK: llvm.func @inallocaattr_decl(!llvm.ptr {llvm.inalloca = i32}) + llvm.func @inallocaattr_decl(!llvm.ptr {llvm.inalloca = i32}) + + // CHECK: llvm.func @variadic(...) llvm.func @variadic(...) Index: mlir/test/Target/LLVMIR/llvmir.mlir =================================================================== --- mlir/test/Target/LLVMIR/llvmir.mlir +++ mlir/test/Target/LLVMIR/llvmir.mlir @@ -1049,31 +1049,65 @@ llvm.return } +// CHECK-LABEL: declare void @llvm_noalias_decl(ptr noalias) +llvm.func @llvm_noalias_decl(!llvm.ptr {llvm.noalias}) + +// CHECK-LABEL: define void @byrefattr(ptr byref(i32) % +llvm.func @byrefattr(%arg0: !llvm.ptr {llvm.byref = i32}) { + llvm.return +} + +// CHECK-LABEL: declare void @byrefattr_decl(ptr byref(i32)) +llvm.func @byrefattr_decl(!llvm.ptr {llvm.byref = i32}) + // CHECK-LABEL: define void @byvalattr(ptr byval(i32) % llvm.func @byvalattr(%arg0: !llvm.ptr {llvm.byval = i32}) { llvm.return } +// CHECK-LABEL: declare void @byvalattr_decl(ptr byval(i32)) +llvm.func @byvalattr_decl(!llvm.ptr {llvm.byval = i32}) + // CHECK-LABEL: define void @sretattr(ptr sret(i32) % llvm.func @sretattr(%arg0: !llvm.ptr {llvm.sret = i32}) { llvm.return } +// CHECK-LABEL: declare void @sretattr_decl(ptr sret(i32)) +llvm.func @sretattr_decl(!llvm.ptr {llvm.sret = i32}) + // CHECK-LABEL: define void @nestattr(ptr nest % llvm.func @nestattr(%arg0: !llvm.ptr {llvm.nest}) { llvm.return } +// CHECK-LABEL: declare void @nestattr_decl(ptr nest) +llvm.func @nestattr_decl(!llvm.ptr {llvm.nest}) + // CHECK-LABEL: define void @noundefattr(i32 noundef % llvm.func @noundefattr(%arg0: i32 {llvm.noundef}) { llvm.return } +// CHECK-LABEL: declare void @noundefattr_decl(i32 noundef) +llvm.func @noundefattr_decl(i32 {llvm.noundef}) + // CHECK-LABEL: define void @llvm_align(ptr align 4 {{%*.}}) llvm.func @llvm_align(%arg0: !llvm.ptr {llvm.align = 4}) { llvm.return } +// CHECK-LABEL: declare void @llvm_align_decl(ptr align 4) +llvm.func @llvm_align_decl(!llvm.ptr {llvm.align = 4}) + +// CHECK-LABEL: define void @inallocaattr(ptr inalloca(i32) % +llvm.func @inallocaattr(%arg0: !llvm.ptr {llvm.inalloca = i32}) { + llvm.return +} + +// CHECK-LABEL: declare void @inallocaattr_decl(ptr inalloca(i32)) +llvm.func @inallocaattr_decl(!llvm.ptr {llvm.inalloca = i32}) + // CHECK-LABEL: @llvm_varargs(...) llvm.func @llvm_varargs(...)