From cc271861da5d9487cbcbb44f949b411a12ec0d96 Mon Sep 17 00:00:00 2001
From: Nick Lewycky
Date: Tue, 13 Oct 2009 07:03:23 +0000
Subject: [PATCH] Add new "memory use marker" intrinsics. These indicate
lifetimes and invariant sections of memory objects.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@83953 91177308-0d34-0410-b5e6-96231b3b80d8
---
docs/LangRef.html | 131 ++++++++++++++++++++++++++++++++++
include/llvm/Intrinsics.td | 16 +++++
test/Feature/memorymarkers.ll | 36 ++++++++++
3 files changed, 183 insertions(+)
create mode 100644 test/Feature/memorymarkers.ll
diff --git a/docs/LangRef.html b/docs/LangRef.html
index 1b1655e42fd..7adb89621f4 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -273,6 +273,14 @@
llvm.atomic.load.umin
+ Memory Use Markers
+
+ - llvm.lifetime.start
+ - llvm.lifetime.end
+ - llvm.invariant.start
+ - llvm.invariant.end
+
+
General intrinsics
-
@@ -6980,6 +6988,129 @@ LLVM.
+
+
+
+
+
+
+
This class of intrinsics exists to information about the lifetime of memory
+ objects and ranges where variables are immutable.
+
+
+
+
+
+
+
+
+
Syntax:
+
+ declare void @llvm.lifetime.start(i64 <size>, i8* nocapture <ptr>)
+
+
+
Overview:
+
The 'llvm.lifetime.start' intrinsic specifies the start of a memory
+ object's lifetime.
+
+
Arguments:
+
The first argument is a the size of the object, or -1 if it is variable
+ sized. The second argument is a pointer to the object.
+
+
Semantics:
+
This intrinsic indicates that before this point in the code, the value of the
+ memory pointed to by ptr is dead. This means that it is known to
+ never be used and has an undefined value. A load from the pointer that is
+ preceded by this intrinsic can be replaced with
+ 'undef'.
+
+
+
+
+
+
+
+
+
Syntax:
+
+ declare void @llvm.lifetime.end(i64 <size>, i8* nocapture <ptr>)
+
+
+
Overview:
+
The 'llvm.lifetime.end' intrinsic specifies the end of a memory
+ object's lifetime.
+
+
Arguments:
+
The first argument is a the size of the object, or -1 if it is variable
+ sized. The second argument is a pointer to the object.
+
+
Semantics:
+
This intrinsic indicates that after this point in the code, the value of the
+ memory pointed to by ptr is dead. This means that it is known to
+ never be used and has an undefined value. Any stores into the memory object
+ following this intrinsic may be removed as dead.
+
+
+
+
+
+
+
+
+
Syntax:
+
+ declare {}* @llvm.invariant.start(i64 <size>, i8* nocapture <ptr>) readonly
+
+
+
Overview:
+
The 'llvm.invariant.start' intrinsic specifies that the contents of
+ a memory object will not change.
+
+
Arguments:
+
The first argument is a the size of the object, or -1 if it is variable
+ sized. The second argument is a pointer to the object.
+
+
Semantics:
+
This intrinsic indicates that until an llvm.invariant.end that uses
+ the return value, the referenced memory location is constant and
+ unchanging.
+
+
+
+
+
+
+
+
+
Syntax:
+
+ declare void @llvm.invariant.end({}* <start>, i64 <size>, i8* nocapture <ptr>)
+
+
+
Overview:
+
The 'llvm.invariant.end' intrinsic specifies that the contents of
+ a memory object are mutable.
+
+
Arguments:
+
The first argument is the matching llvm.invariant.start intrinsic.
+ The second argument is a the size of the object, or -1 if it is variable
+ sized and the third argument is a pointer to the object.
+
+
Semantics:
+
This intrinsic indicates that the memory is mutable again.
+
+
+
General Intrinsics
diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td
index 9b0c876d72f..bfa924cd866 100644
--- a/include/llvm/Intrinsics.td
+++ b/include/llvm/Intrinsics.td
@@ -421,6 +421,22 @@ def int_atomic_load_umax : Intrinsic<[llvm_anyint_ty],
[IntrWriteArgMem, NoCapture<0>]>,
GCCBuiltin<"__sync_fetch_and_umax">;
+//===------------------------- Memory Use Markers -------------------------===//
+//
+def int_lifetime_start : Intrinsic<[llvm_void_ty],
+ [llvm_i64_ty, llvm_ptr_ty],
+ [IntrWriteArgMem, NoCapture<1>]>;
+def int_lifetime_end : Intrinsic<[llvm_void_ty],
+ [llvm_i64_ty, llvm_ptr_ty],
+ [IntrWriteArgMem, NoCapture<1>]>;
+def int_invariant_start : Intrinsic<[llvm_descriptor_ty],
+ [llvm_i64_ty, llvm_ptr_ty],
+ [IntrReadArgMem, NoCapture<1>]>;
+def int_invariant_end : Intrinsic<[llvm_void_ty],
+ [llvm_descriptor_ty, llvm_i64_ty,
+ llvm_ptr_ty],
+ [IntrWriteArgMem, NoCapture<2>]>;
+
//===-------------------------- Other Intrinsics --------------------------===//
//
def int_flt_rounds : Intrinsic<[llvm_i32_ty]>,
diff --git a/test/Feature/memorymarkers.ll b/test/Feature/memorymarkers.ll
new file mode 100644
index 00000000000..06b8376678f
--- /dev/null
+++ b/test/Feature/memorymarkers.ll
@@ -0,0 +1,36 @@
+; RUN: llvm-as -disable-output < %s
+
+%"struct.std::pair
" = type { i32, i32 }
+
+declare void @_Z3barRKi(i32*)
+
+declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind
+declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind
+declare {}* @llvm.invariant.start(i64, i8* nocapture) readonly nounwind
+declare void @llvm.invariant.end({}*, i64, i8* nocapture) nounwind
+
+define i32 @_Z4foo2v() nounwind {
+entry:
+ %x = alloca %"struct.std::pair"
+ %y = bitcast %"struct.std::pair"* %x to i8*
+
+ ;; Constructor starts here (this isn't needed since it is immediately
+ ;; preceded by an alloca, but shown for completeness).
+ call void @llvm.lifetime.start(i64 8, i8* %y)
+
+ %0 = getelementptr %"struct.std::pair"* %x, i32 0, i32 0
+ store i32 4, i32* %0, align 8
+ %1 = getelementptr %"struct.std::pair"* %x, i32 0, i32 1
+ store i32 5, i32* %1, align 4
+
+ ;; Constructor has finished here.
+ %inv = call {}* @llvm.invariant.start(i64 8, i8* %y)
+ call void @_Z3barRKi(i32* %0) nounwind
+ %2 = load i32* %0, align 8
+
+ ;; Destructor is run here.
+ call void @llvm.invariant.end({}* %inv, i64 8, i8* %y)
+ ;; Destructor is done here.
+ call void @llvm.lifetime.end(i64 8, i8* %y)
+ ret i32 %2
+}