diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -6191,6 +6191,8 @@ !2 = !DILabel(scope: !0, name: "foo", file: !1, line: 7) +.. _tbaa_metadata: + '``tbaa``' Metadata ^^^^^^^^^^^^^^^^^^^ @@ -26979,3 +26981,37 @@ environment ` *except* for the rounding mode. This intrinsic is not supported on all targets. Some targets may not support all rounding modes. + + +'``llvm.tbaa.fence``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" +:: + + declare void @llvm.tbaa.fence(ptr , i64 ) + +Overview: +""""""""" + +The '``llvm.tbaa.fence``' prevents NoAlias responses from type-based alias +analysis from resulting in the reordering or elision of memory operations to the +```` bytes starting at ````. + +Arguments: +"""""""""" + +The first argument to the intrinsic is a pointer to be fenced, and the second is +the number of bytes. + +Semantics: +"""""""""" + +Does nothing, but in an opaque manner that forces optimization passes to treat +the builtin as potentially reading from or writing to the given memory. This +prevents stores from being elided or loads from being folded away, even if the +associated :ref:`TBAA metadata` would otherwise justify such an +outcome. Optimization passes are permitted to remove or ignore the fence if they +can prove that TBAA will not return a NoAlias result when evaluating operations +to the pointed-to storage before the fence and those after it. diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h --- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -692,6 +692,7 @@ case Intrinsic::coro_subfn_addr: case Intrinsic::threadlocal_address: case Intrinsic::experimental_widenable_condition: + case Intrinsic::tbaa_fence: // These intrinsics don't actually represent code after lowering. return 0; } diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1252,6 +1252,11 @@ [LLVMMatchType<0>], [IntrSpeculatable, IntrNoMem, IntrWillReturn]>; +def int_tbaa_fence : DefaultAttrsIntrinsic<[], + [llvm_ptr_ty, llvm_i64_ty], + [IntrArgMemOnly, IntrWillReturn, + NoCapture>]>; + //===------------------------ Stackmap Intrinsics -------------------------===// // def int_experimental_stackmap : DefaultAttrsIntrinsic<[], diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -7013,6 +7013,7 @@ case Intrinsic::seh_scope_begin: case Intrinsic::seh_try_end: case Intrinsic::seh_scope_end: + case Intrinsic::tbaa_fence: // ignore return; case Intrinsic::experimental_stackmap: diff --git a/llvm/test/Analysis/TypeBasedAliasAnalysis/tbaa-fence.ll b/llvm/test/Analysis/TypeBasedAliasAnalysis/tbaa-fence.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/TypeBasedAliasAnalysis/tbaa-fence.ll @@ -0,0 +1,21 @@ +; RUN: opt < %s -aa-pipeline=tbaa -passes=aa-eval -evaluate-aa-metadata \ +; RUN: -print-no-aliases -print-modref -disable-output 2>&1 | FileCheck %s + +declare void @llvm.tbaa.fence(ptr, i64 %len) + +define void @simple(ptr %p) { +entry: + ; CHECK-LABEL: simple + ; CHECK: NoAlias: %x = load i8, ptr %p, align 1, !tbaa !3 <-> store i8 1, ptr %p, align 1, !tbaa !0 + ; CHECK: Both ModRef: Ptr: i8* %p <-> call void @llvm.tbaa.fence(ptr %p, i64 1) + store i8 1, ptr %p, !tbaa !3 + call void @llvm.tbaa.fence(ptr %p, i64 1) + %x = load i8, ptr %p, !tbaa !4 + ret void +} + +!0 = !{!"root"} +!1 = !{!"type1", !0, i64 0} +!2 = !{!"type2", !0, i64 0} +!3 = !{!1, !1, i64 0, i64 0} +!4 = !{!2, !2, i64 0, i64 0} diff --git a/llvm/test/CodeGen/Generic/tbaa-fence.ll b/llvm/test/CodeGen/Generic/tbaa-fence.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/Generic/tbaa-fence.ll @@ -0,0 +1,8 @@ +; RUN: llc < %s + +declare void @llvm.tbaa.fence(ptr, i64 %len) + +define void @call_fence(ptr %p, i64 %len) { + call void @llvm.tbaa.fence(ptr %p, i64 %len) + ret void +}