Slava Zakharin 2f66c89130 [mlir] Support TBAA metadata in LLVMIR dialect.
This change introduces new LLVMIR dialect operations to represent
TBAA root, type descriptor and access tag metadata nodes.

For the purpose of importing TBAA metadata from LLVM IR it only
supports the current version of TBAA format described in
https://llvm.org/docs/LangRef.html#tbaa-metadata (i.e. size-aware
representation introduced in D41501 is not supported).

TBAA attribute support is only added for LLVM::LoadOp and LLVM::StoreOp.
Support for intrinsics operations (e.g. LLVM::MemcpyOp) may be added later.

The TBAA attribute is represented as an array of access tags, though,
LLVM IR supports only single access tag per memory accessing instruction.
I implemented it as an array anticipating similar support in LLVM IR
to combine TBAA graphs with different roots for Flang - one of the options
described in https://docs.google.com/document/d/16kKZVmI585wth01VSaJAqZMZpoX68rcdBmgfj0kNAt0/edit#heading=h.jzzheaz9vqac

It should be easy to restrict MLIR operation to a single access tag,
if we end up using a different approach for Flang.

Differential Revision: https://reviews.llvm.org/D140768
2023-01-06 11:16:31 -08:00

208 lines
5.4 KiB
LLVM

; RUN: not mlir-translate -import-llvm -split-input-file %s 2>&1 | FileCheck %s
; CHECK: error: unhandled instruction indirectbr i8* %dst, [label %bb1, label %bb2]
define i32 @unhandled_instruction(i8* %dst) {
indirectbr i8* %dst, [label %bb1, label %bb2]
bb1:
ret i32 0
bb2:
ret i32 1
}
; // -----
; CHECK: unhandled value ptr asm "bswap $0", "=r,r"
define i32 @unhandled_value(i32 %arg0) {
%1 = call i32 asm "bswap $0", "=r,r"(i32 %arg0)
ret i32 %1
}
; // -----
; CHECK: error: unhandled constant i8* blockaddress(@unhandled_constant, %bb1)
define i8* @unhandled_constant() {
bb1:
ret i8* blockaddress(@unhandled_constant, %bb1)
}
; // -----
; CHECK: error: unhandled constant i8* blockaddress(@unhandled_global, %bb1)
; CHECK: error: unhandled global variable @private = private global i8* blockaddress(@unhandled_global, %bb1)
@private = private global i8* blockaddress(@unhandled_global, %bb1)
define void @unhandled_global() {
bb1:
ret void
}
; // -----
declare void @llvm.gcroot(ptr %arg0, ptr %arg1)
; CHECK: error: unhandled intrinsic call void @llvm.gcroot(ptr %arg0, ptr %arg1)
define void @unhandled_intrinsic(ptr %arg0, ptr %arg1) {
call void @llvm.gcroot(ptr %arg0, ptr %arg1)
ret void
}
; // -----
; CHECK: warning: unhandled metadata (2) br i1 %arg1, label %bb1, label %bb2, !prof !0
define i64 @cond_br(i1 %arg1, i64 %arg2) {
entry:
br i1 %arg1, label %bb1, label %bb2, !prof !0
bb1:
ret i64 %arg2
bb2:
ret i64 %arg2
}
!0 = !{!"unknown metadata"}
; // -----
declare void @llvm.dbg.value(metadata, metadata, metadata)
; CHECK: warning: dropped instruction call void @llvm.dbg.value(metadata i64 %arg1, metadata !3, metadata !DIExpression(DW_OP_plus_uconst, 42, DW_OP_stack_value)), !dbg !5
define void @dropped_instruction(i64 %arg1) {
call void @llvm.dbg.value(metadata i64 %arg1, metadata !3, metadata !DIExpression(DW_OP_plus_uconst, 42, DW_OP_stack_value)), !dbg !5
ret void
}
!llvm.dbg.cu = !{!1}
!llvm.module.flags = !{!0}
!0 = !{i32 2, !"Debug Info Version", i32 3}
!1 = distinct !DICompileUnit(language: DW_LANG_C, file: !2)
!2 = !DIFile(filename: "import-failure.ll", directory: "/")
!3 = !DILocalVariable(scope: !4, name: "arg", file: !2, line: 1, arg: 1, align: 32);
!4 = distinct !DISubprogram(name: "intrinsic", scope: !2, file: !2, spFlags: DISPFlagDefinition, unit: !1)
!5 = !DILocation(line: 1, column: 2, scope: !4)
; // -----
; global_ctors requires the appending linkage type.
; CHECK: error: unhandled global variable @llvm.global_ctors
@llvm.global_ctors = global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @foo, ptr null }]
define void @foo() {
ret void
}
; // -----
; global_dtors with non-null data fields cannot be represented in MLIR.
; CHECK: error: unhandled global variable @llvm.global_dtors
@llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @foo, ptr @foo }]
define void @foo() {
ret void
}
; // -----
; global_ctors without a data field should not be imported.
; CHECK: error: unhandled global variable @llvm.global_ctors
@llvm.global_ctors = appending global [1 x { i32, ptr }] [{ i32, ptr } { i32 0, ptr @foo }]
define void @foo() {
ret void
}
; // -----
; global_dtors with a wrong argument order should not be imported.
; CHECK: error: unhandled global variable @llvm.global_dtors
@llvm.global_dtors = appending global [1 x { ptr, i32, ptr }] [{ ptr, i32, ptr } { ptr @foo, i32 0, ptr null }]
define void @foo() {
ret void
}
; // -----
; CHECK: error: TBAA root node must have non-empty identity: !2 = !{!""}
define dso_local void @tbaa(ptr %0) {
store i8 1, ptr %0, align 4, !tbaa !2
ret void
}
!0 = !{!""}
!1 = !{!"omnipotent char", !0, i64 0}
!2 = !{!1, !1, i64 0}
; // -----
; CHECK: error: unsupported TBAA node format: !0 = !{!1, i64 0, i64 0}
define dso_local void @tbaa(ptr %0) {
store i8 1, ptr %0, align 4, !tbaa !2
ret void
}
!0 = !{!"Simple C/C++ TBAA"}
!1 = !{!"omnipotent char", !0, i64 0}
!2 = !{!1, i64 0, i64 0}
; // -----
; CHECK: error: operand '1' must be MDNode: !1 = !{!"omnipotent char", i64 0, i64 0}
define dso_local void @tbaa(ptr %0) {
store i8 1, ptr %0, align 4, !tbaa !2
ret void
}
!0 = !{!"Simple C/C++ TBAA"}
!1 = !{!"omnipotent char", i64 0, i64 0}
!2 = !{!1, !1, i64 0}
; // -----
; CHECK: error: missing member offset: !1 = !{!"agg_t", !2, i64 0, !2}
define dso_local void @tbaa(ptr %0) {
store i8 1, ptr %0, align 4, !tbaa !3
ret void
}
!0 = !{!"Simple C/C++ TBAA"}
!1 = !{!"omnipotent char", !0, i64 0}
!2 = !{!"agg_t", !1, i64 0, !1}
!3 = !{!2, !1, i64 0}
; // -----
; CHECK: error: operand '4' must be ConstantInt: !1 = !{!"agg_t", !2, i64 0, !2, double 1.000000e+00}
define dso_local void @tbaa(ptr %0) {
store i8 1, ptr %0, align 4, !tbaa !3
ret void
}
!0 = !{!"Simple C/C++ TBAA"}
!1 = !{!"omnipotent char", !0, i64 0}
!2 = !{!"agg_t", !1, i64 0, !1, double 1.0}
!3 = !{!2, !1, i64 0}
; // -----
; CHECK: error: operand '3' must be ConstantInt: !0 = !{!1, !1, i64 0, double 1.000000e+00}
define dso_local void @tbaa(ptr %0) {
store i8 1, ptr %0, align 4, !tbaa !2
ret void
}
!0 = !{!"Simple C/C++ TBAA"}
!1 = !{!"omnipotent char", !0, i64 0}
!2 = !{!1, !1, i64 0, double 1.0}
; // -----
; CHECK: error: unsupported TBAA node format: !0 = !{!1, !1, i64 0, i64 4}
define dso_local void @tbaa(ptr %0) {
store i32 1, ptr %0, align 4, !tbaa !2
ret void
}
!2 = !{!3, !3, i64 0, i64 4}
!3 = !{!4, i64 4, !"int"}
!4 = !{!5, i64 1, !"omnipotent char"}
!5 = !{!"Simple C++ TBAA"}