mirror of
https://github.com/RPCS3/llvm.git
synced 2025-04-12 11:03:24 +00:00
[RS4GC] Strip noalias attribute after statepoint rewrite
We should remove noalias along with dereference and dereference_or_null attributes because statepoint could potentially touch the entire heap including noalias objects. Differential Revision: http://reviews.llvm.org/D14032 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251333 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
644d8eaae4
commit
14ff71aa42
@ -262,6 +262,13 @@ public:
|
||||
CALLSITE_DELEGATE_GETTER(getDereferenceableOrNullBytes(i));
|
||||
}
|
||||
|
||||
/// @brief Determine if the parameter or return value is marked with NoAlias
|
||||
/// attribute.
|
||||
/// @param n The parameter to check. 1 is the first parameter, 0 is the return
|
||||
bool doesNotAlias(unsigned n) const {
|
||||
CALLSITE_DELEGATE_GETTER(doesNotAlias(n));
|
||||
}
|
||||
|
||||
/// \brief Return true if the call should not be treated as a call to a
|
||||
/// builtin.
|
||||
bool isNoBuiltin() const {
|
||||
|
@ -348,7 +348,8 @@ public:
|
||||
AttributeSets.hasAttribute(2, Attribute::StructRet);
|
||||
}
|
||||
|
||||
/// @brief Determine if the parameter does not alias other parameters.
|
||||
/// @brief Determine if the parameter or return value is marked with NoAlias
|
||||
/// attribute.
|
||||
/// @param n The parameter to check. 1 is the first parameter, 0 is the return
|
||||
bool doesNotAlias(unsigned n) const {
|
||||
return AttributeSets.hasAttribute(n, Attribute::NoAlias);
|
||||
|
@ -1618,6 +1618,13 @@ public:
|
||||
return AttributeList.getDereferenceableOrNullBytes(i);
|
||||
}
|
||||
|
||||
/// @brief Determine if the parameter or return value is marked with NoAlias
|
||||
/// attribute.
|
||||
/// @param n The parameter to check. 1 is the first parameter, 0 is the return
|
||||
bool doesNotAlias(unsigned n) const {
|
||||
return AttributeList.hasAttribute(n, Attribute::NoAlias);
|
||||
}
|
||||
|
||||
/// \brief Return true if the call should not be treated as a call to a
|
||||
/// builtin.
|
||||
bool isNoBuiltin() const {
|
||||
@ -3480,6 +3487,13 @@ public:
|
||||
return AttributeList.getDereferenceableOrNullBytes(i);
|
||||
}
|
||||
|
||||
/// @brief Determine if the parameter or return value is marked with NoAlias
|
||||
/// attribute.
|
||||
/// @param n The parameter to check. 1 is the first parameter, 0 is the return
|
||||
bool doesNotAlias(unsigned n) const {
|
||||
return AttributeList.hasAttribute(n, Attribute::NoAlias);
|
||||
}
|
||||
|
||||
/// \brief Return true if the call should not be treated as a call to a
|
||||
/// builtin.
|
||||
bool isNoBuiltin() const {
|
||||
|
@ -115,7 +115,8 @@ struct RewriteStatepointsForGC : public ModulePass {
|
||||
/// heap. stripNonValidAttributes (conservatively) restores correctness
|
||||
/// by erasing all attributes in the module that externally imply
|
||||
/// dereferenceability.
|
||||
///
|
||||
/// Similar reasoning also applies to the noalias attributes. gc.statepoint
|
||||
/// can touch the entire heap including noalias objects.
|
||||
void stripNonValidAttributes(Module &M);
|
||||
|
||||
// Helpers for stripNonValidAttributes
|
||||
@ -2501,6 +2502,8 @@ static void RemoveNonValidAttrAtIndex(LLVMContext &Ctx, AttrHolder &AH,
|
||||
if (AH.getDereferenceableOrNullBytes(Index))
|
||||
R.addAttribute(Attribute::get(Ctx, Attribute::DereferenceableOrNull,
|
||||
AH.getDereferenceableOrNullBytes(Index)));
|
||||
if (AH.doesNotAlias(Index))
|
||||
R.addAttribute(Attribute::NoAlias);
|
||||
|
||||
if (!R.empty())
|
||||
AH.setAttributes(AH.getAttributes().removeAttributes(
|
||||
|
@ -3,6 +3,7 @@
|
||||
; CHECK: declare i8 addrspace(1)* @some_function_ret_deref()
|
||||
; CHECK: define i8 addrspace(1)* @test_deref_arg(i8 addrspace(1)* %a)
|
||||
; CHECK: define i8 addrspace(1)* @test_deref_or_null_arg(i8 addrspace(1)* %a)
|
||||
; CHECK: define i8 addrspace(1)* @test_noalias_arg(i8 addrspace(1)* %a)
|
||||
|
||||
declare void @foo()
|
||||
|
||||
@ -11,6 +12,7 @@ declare i8 addrspace(1)* @some_function() "gc-leaf-function"
|
||||
declare void @some_function_consumer(i8 addrspace(1)*) "gc-leaf-function"
|
||||
|
||||
declare dereferenceable(4) i8 addrspace(1)* @some_function_ret_deref() "gc-leaf-function"
|
||||
declare noalias i8 addrspace(1)* @some_function_ret_noalias() "gc-leaf-function"
|
||||
|
||||
define i8 addrspace(1)* @test_deref_arg(i8 addrspace(1)* dereferenceable(4) %a) gc "statepoint-example" {
|
||||
entry:
|
||||
@ -24,6 +26,12 @@ entry:
|
||||
ret i8 addrspace(1)* %a
|
||||
}
|
||||
|
||||
define i8 addrspace(1)* @test_noalias_arg(i8 addrspace(1)* noalias %a) gc "statepoint-example" {
|
||||
entry:
|
||||
call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
|
||||
ret i8 addrspace(1)* %a
|
||||
}
|
||||
|
||||
define i8 addrspace(1)* @test_deref_retval() gc "statepoint-example" {
|
||||
; CHECK-LABEL: @test_deref_retval(
|
||||
; CHECK: %a = call i8 addrspace(1)* @some_function()
|
||||
@ -42,6 +50,15 @@ entry:
|
||||
ret i8 addrspace(1)* %a
|
||||
}
|
||||
|
||||
define i8 addrspace(1)* @test_noalias_retval() gc "statepoint-example" {
|
||||
; CHECK-LABEL: @test_noalias_retval(
|
||||
; CHECK: %a = call i8 addrspace(1)* @some_function()
|
||||
entry:
|
||||
%a = call noalias i8 addrspace(1)* @some_function()
|
||||
call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
|
||||
ret i8 addrspace(1)* %a
|
||||
}
|
||||
|
||||
define i8 @test_md(i8 addrspace(1)* %ptr) gc "statepoint-example" {
|
||||
; CHECK-LABEL: @test_md(
|
||||
; CHECK: %tmp = load i8, i8 addrspace(1)* %ptr, !tbaa !0
|
||||
@ -61,6 +78,16 @@ entry:
|
||||
ret i8 addrspace(1)* %a
|
||||
}
|
||||
|
||||
define i8 addrspace(1)* @test_decl_only_noalias(i8 addrspace(1)* %ptr) gc "statepoint-example" {
|
||||
; CHECK-LABEL: @test_decl_only_noalias(
|
||||
; No change here, but the prototype of some_function_ret_noalias should have changed.
|
||||
; CHECK: call i8 addrspace(1)* @some_function_ret_noalias()
|
||||
entry:
|
||||
%a = call i8 addrspace(1)* @some_function_ret_noalias()
|
||||
call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
|
||||
ret i8 addrspace(1)* %a
|
||||
}
|
||||
|
||||
define i8 addrspace(1)* @test_callsite_arg_attribute(i8 addrspace(1)* %ptr) gc "statepoint-example" {
|
||||
; CHECK-LABEL: @test_callsite_arg_attribute(
|
||||
; CHECK: call void @some_function_consumer(i8 addrspace(1)* %ptr)
|
||||
@ -68,7 +95,7 @@ define i8 addrspace(1)* @test_callsite_arg_attribute(i8 addrspace(1)* %ptr) gc "
|
||||
; CHECK: !1 = !{!"red", !2}
|
||||
; CHECK: !2 = !{!"blue"}
|
||||
entry:
|
||||
call void @some_function_consumer(i8 addrspace(1)* dereferenceable(4) %ptr)
|
||||
call void @some_function_consumer(i8 addrspace(1)* dereferenceable(4) noalias %ptr)
|
||||
call void @foo() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ]
|
||||
ret i8 addrspace(1)* %ptr
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ declare i8 addrspace(1)* @some_function()
|
||||
declare void @some_function_consumer(i8 addrspace(1)*)
|
||||
declare dereferenceable(4) i8 addrspace(1)* @some_function_ret_deref()
|
||||
; CHECK: declare i8 addrspace(1)* @some_function_ret_deref()
|
||||
declare noalias i8 addrspace(1)* @some_function_ret_noalias()
|
||||
; CHECK: declare i8 addrspace(1)* @some_function_ret_noalias()
|
||||
|
||||
define i8 addrspace(1)* @test_deref_arg(i8 addrspace(1)* dereferenceable(4) %a) gc "statepoint-example" {
|
||||
; CHECK: define i8 addrspace(1)* @test_deref_arg(i8 addrspace(1)* %a)
|
||||
@ -66,6 +68,41 @@ entry:
|
||||
ret i8 addrspace(1)* %ptr
|
||||
}
|
||||
|
||||
define i8 addrspace(1)* @test_noalias_arg(i8 addrspace(1)* noalias %a) gc "statepoint-example" {
|
||||
; CHECK: define i8 addrspace(1)* @test_noalias_arg(i8 addrspace(1)* %a)
|
||||
entry:
|
||||
call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
|
||||
ret i8 addrspace(1)* %a
|
||||
}
|
||||
|
||||
define i8 addrspace(1)* @test_noalias_retval() gc "statepoint-example" {
|
||||
; CHECK-LABEL: @test_noalias_retval(
|
||||
entry:
|
||||
%a = call noalias i8 addrspace(1)* @some_function()
|
||||
; CHECK: %a = call i8 addrspace(1)* @some_function()
|
||||
call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
|
||||
ret i8 addrspace(1)* %a
|
||||
}
|
||||
|
||||
define i8 addrspace(1)* @test_decl_only_noalias(i8 addrspace(1)* %ptr) gc "statepoint-example" {
|
||||
; CHECK-LABEL: @test_decl_only_noalias(
|
||||
entry:
|
||||
; No change here, but the prototype of some_function_ret_noalias should have changed.
|
||||
; CHECK: call i8 addrspace(1)* @some_function_ret_noalias()
|
||||
%a = call i8 addrspace(1)* @some_function_ret_noalias()
|
||||
call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
|
||||
ret i8 addrspace(1)* %a
|
||||
}
|
||||
|
||||
define i8 addrspace(1)* @test_callsite_arg_noalias(i8 addrspace(1)* %ptr) gc "statepoint-example" {
|
||||
; CHECK-LABEL: @test_callsite_arg_noalias(
|
||||
entry:
|
||||
; CHECK: call void @some_function_consumer(i8 addrspace(1)* %ptr)
|
||||
call void @some_function_consumer(i8 addrspace(1)* noalias %ptr)
|
||||
call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
|
||||
ret i8 addrspace(1)* %ptr
|
||||
}
|
||||
|
||||
declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)
|
||||
|
||||
!0 = !{!1, !1, i64 0, i64 1}
|
||||
|
Loading…
x
Reference in New Issue
Block a user