diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -1719,6 +1719,10 @@ if (argAttr.first == "llvm.noalias" && !argAttr.second.isa()) return op->emitError() << "llvm.noalias argument attribute of non boolean type"; + // Check that llvm.align is an integer attribute. + if (argAttr.first == "llvm.align" && !argAttr.second.isa()) + return op->emitError() + << "llvm.align argument attribute of non integer type"; return success(); } diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -724,6 +724,18 @@ if (attr.getValue()) llvmArg.addAttr(llvm::Attribute::AttrKind::NoAlias); } + + if (auto attr = func.getArgAttrOfType(argIdx, "llvm.align")) { + // 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().dyn_cast(); + if (!argTy.getUnderlyingType()->isPointerTy()) + return func.emitError( + "llvm.align attribute attached to LLVM non-pointer argument"); + llvmArg.addAttrs( + llvm::AttrBuilder().addAlignmentAttr(llvm::Align(attr.getInt()))); + } + valueMapping[mlirArg] = &llvmArg; argIdx++; } diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir --- a/mlir/test/Dialect/LLVMIR/invalid.mlir +++ b/mlir/test/Dialect/LLVMIR/invalid.mlir @@ -5,6 +5,13 @@ "llvm.return"() : () -> () } +// ----- + +// expected-error@+1{{llvm.align argument attribute of non integer type}} +func @invalid_align(%arg0: !llvm.i32 {llvm.align = "foo"}) { + "llvm.return"() : () -> () +} + //////////////////////////////////////////////////////////////////////////////// // Check that parser errors are properly produced and do not crash the compiler. diff --git a/mlir/test/Target/llvmir-invalid.mlir b/mlir/test/Target/llvmir-invalid.mlir --- a/mlir/test/Target/llvmir-invalid.mlir +++ b/mlir/test/Target/llvmir-invalid.mlir @@ -7,6 +7,20 @@ // ----- +// expected-error @+1 {{llvm.noalias attribute attached to LLVM non-pointer argument}} +llvm.func @invalid_noalias(%arg0 : !llvm.float {llvm.noalias = true}) -> !llvm.float { + llvm.return %arg0 : !llvm.float +} + +// ----- + +// expected-error @+1 {{llvm.align attribute attached to LLVM non-pointer argument}} +llvm.func @invalid_align(%arg0 : !llvm.float {llvm.align = 4}) -> !llvm.float { + llvm.return %arg0 : !llvm.float +} + +// ----- + llvm.func @no_nested_struct() -> !llvm<"[2 x [2 x [2 x {i32}]]]"> { // expected-error @+1 {{struct types are not supported in constants}} %0 = llvm.mlir.constant(dense<[[[1, 2], [3, 4]], [[42, 43], [44, 45]]]> : tensor<2x2x2xi32>) : !llvm<"[2 x [2 x [2 x {i32}]]]"> diff --git a/mlir/test/Target/llvmir.mlir b/mlir/test/Target/llvmir.mlir --- a/mlir/test/Target/llvmir.mlir +++ b/mlir/test/Target/llvmir.mlir @@ -927,6 +927,11 @@ llvm.return } +// CHECK-LABEL: define void @llvm_align(float* align 4 {{%*.}}) +llvm.func @llvm_align(%arg0: !llvm<"float*"> {llvm.align = 4}) { + llvm.return +} + // CHECK-LABEL: @llvm_varargs(...) llvm.func @llvm_varargs(...)