mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[Attributor] AAReachability : use isPotentiallyReachable in isKnownReachable
`isKnownReachable` had only interface (always returns true). Changed it to call `isPotentiallyReachable`. This change enables deductions of other Abstract Attributes depending on AAReachability to use reachability information obtained from CFG, and it can make them stronger. Reviewed By: jdoerfert Differential Revision: https://reviews.llvm.org/D76210
This commit is contained in:
parent
fbb9bfcd51
commit
72788d66f4
@ -102,6 +102,7 @@
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/AssumeBundleQueries.h"
|
||||
#include "llvm/Analysis/CFG.h"
|
||||
#include "llvm/Analysis/CGSCCPassManager.h"
|
||||
#include "llvm/Analysis/CallGraph.h"
|
||||
#include "llvm/Analysis/InlineCost.h"
|
||||
@ -2106,14 +2107,14 @@ struct AAReachability : public StateWrapper<BooleanState, AbstractAttribute>,
|
||||
/// determines (and caches) reachability.
|
||||
bool isAssumedReachable(const Instruction *From,
|
||||
const Instruction *To) const {
|
||||
return true;
|
||||
return isPotentiallyReachable(From, To);
|
||||
}
|
||||
|
||||
/// Returns true if 'From' instruction is known to reach, 'To' instruction.
|
||||
/// Users should provide two positions they are interested in, and the class
|
||||
/// determines (and caches) reachability.
|
||||
bool isKnownReachable(const Instruction *From, const Instruction *To) const {
|
||||
return true;
|
||||
return isPotentiallyReachable(From, To);
|
||||
}
|
||||
|
||||
/// Return an IR position, see struct IRPosition.
|
||||
|
@ -184,7 +184,7 @@ define void @test7() {
|
||||
define void @test8() {
|
||||
%1 = tail call noalias i8* @malloc(i64 4)
|
||||
; CHECK: %1 = tail call noalias i8* @malloc(i64 4)
|
||||
; CHECK-NEXT: @no_sync_func(i8* nocapture nofree %1)
|
||||
; CHECK-NEXT: @no_sync_func(i8* noalias nocapture nofree %1)
|
||||
tail call void @no_sync_func(i8* %1)
|
||||
%2 = bitcast i8* %1 to i32*
|
||||
store i32 10, i32* %2
|
||||
@ -199,7 +199,7 @@ define void @test8() {
|
||||
define void @test9() {
|
||||
%1 = tail call noalias i8* @malloc(i64 4)
|
||||
; CHECK: %1 = tail call noalias i8* @malloc(i64 4)
|
||||
; CHECK-NEXT: @no_sync_func(i8* nocapture nofree %1)
|
||||
; CHECK-NEXT: @no_sync_func(i8* noalias nocapture nofree %1)
|
||||
tail call void @no_sync_func(i8* %1)
|
||||
%2 = bitcast i8* %1 to i32*
|
||||
store i32 10, i32* %2
|
||||
|
@ -9,7 +9,7 @@ define internal void @internal(void (i8*)* %fp) {
|
||||
; CHECK-SAME: (void (i8*)* nonnull [[FP:%.*]])
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
|
||||
; CHECK-NEXT: call void @foo(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A]])
|
||||
; CHECK-NEXT: call void @foo(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A]])
|
||||
; CHECK-NEXT: call void [[FP]](i8* bitcast (void (i32*)* @foo to i8*))
|
||||
; CHECK-NEXT: call void @callback1(void (i32*)* nonnull @foo)
|
||||
; CHECK-NEXT: call void @callback2(void (i8*)* bitcast (void (i32*)* @foo to void (i8*)*))
|
||||
@ -22,7 +22,7 @@ define internal void @internal(void (i8*)* %fp) {
|
||||
; DECL_CS-SAME: (void (i8*)* nonnull [[FP:%.*]])
|
||||
; DECL_CS-NEXT: entry:
|
||||
; DECL_CS-NEXT: [[A:%.*]] = alloca i32, align 4
|
||||
; DECL_CS-NEXT: call void @foo(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A]])
|
||||
; DECL_CS-NEXT: call void @foo(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A]])
|
||||
; DECL_CS-NEXT: call void [[FP]](i8* bitcast (void (i32*)* @foo to i8*))
|
||||
; DECL_CS-NEXT: call void @callback1(void (i32*)* nonnull @foo)
|
||||
; DECL_CS-NEXT: call void @callback2(void (i8*)* nonnull bitcast (void (i32*)* @foo to void (i8*)*))
|
||||
@ -49,7 +49,7 @@ define void @external(void (i8*)* %fp) {
|
||||
; CHECK-SAME: (void (i8*)* [[FP:%.*]])
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
|
||||
; CHECK-NEXT: call void @foo(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A]])
|
||||
; CHECK-NEXT: call void @foo(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A]])
|
||||
; CHECK-NEXT: call void @callback1(void (i32*)* nonnull @foo)
|
||||
; CHECK-NEXT: call void @callback2(void (i8*)* bitcast (void (i32*)* @foo to void (i8*)*))
|
||||
; CHECK-NEXT: call void @callback2(void (i8*)* [[FP]])
|
||||
@ -63,7 +63,7 @@ define void @external(void (i8*)* %fp) {
|
||||
; DECL_CS-SAME: (void (i8*)* [[FP:%.*]])
|
||||
; DECL_CS-NEXT: entry:
|
||||
; DECL_CS-NEXT: [[A:%.*]] = alloca i32, align 4
|
||||
; DECL_CS-NEXT: call void @foo(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A]])
|
||||
; DECL_CS-NEXT: call void @foo(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A]])
|
||||
; DECL_CS-NEXT: call void @callback1(void (i32*)* nonnull @foo)
|
||||
; DECL_CS-NEXT: call void @callback2(void (i8*)* nonnull bitcast (void (i32*)* @foo to void (i8*)*))
|
||||
; DECL_CS-NEXT: call void @callback2(void (i8*)* [[FP]])
|
||||
|
@ -255,10 +255,8 @@ define void @test12_1() {
|
||||
define void @test12_2(){
|
||||
; CHECK-LABEL: @test12_2(
|
||||
; CHECK-NEXT: [[A:%.*]] = tail call noalias i8* @malloc(i64 4)
|
||||
; FIXME: This should be @use_nocapture(i8* noalias [[A]])
|
||||
; CHECK-NEXT: tail call void @use_nocapture(i8* nocapture [[A]])
|
||||
; FIXME: This should be @use_nocapture(i8* noalias nocapture [[A]])
|
||||
; CHECK-NEXT: tail call void @use_nocapture(i8* nocapture [[A]])
|
||||
; CHECK-NEXT: tail call void @use_nocapture(i8* noalias nocapture [[A]])
|
||||
; CHECK-NEXT: tail call void @use_nocapture(i8* noalias nocapture [[A]])
|
||||
; CHECK-NEXT: tail call void @use(i8* [[A]])
|
||||
; CHECK-NEXT: tail call void @use_nocapture(i8* nocapture [[A]])
|
||||
; CHECK-NEXT: ret void
|
||||
@ -393,3 +391,82 @@ declare dso_local double @__floatscan(%struct._IO_FILE*, i32, i32) local_unnamed
|
||||
|
||||
; Function Attrs: argmemonly nounwind willreturn
|
||||
declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)
|
||||
|
||||
; Test 15
|
||||
; propagate noalias to some callsite arguments that there is no possibly reachable capture before it
|
||||
|
||||
@alias_of_p = external global i32*
|
||||
|
||||
define void @make_alias(i32* %p) {
|
||||
store i32* %p, i32** @alias_of_p
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @only_store(i32* %p) {
|
||||
store i32 0, i32* %p
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL define void @test15_caller(i32* noalias %p, i32 %c)
|
||||
define void @test15_caller(i32* noalias %p, i32 %c) {
|
||||
%tobool = icmp eq i32 %c, 0
|
||||
br i1 %tobool, label %if.end, label %if.then
|
||||
|
||||
; CHECK tail call void @only_store(i32* noalias %p)
|
||||
; CHECK tail call void @make_alias(i32* %p)
|
||||
|
||||
if.then:
|
||||
tail call void @only_store(i32* %p)
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
tail call void @make_alias(i32* %p)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Test 16
|
||||
;
|
||||
; __attribute__((noinline)) static void test16_sub(int * restrict p, int c1, int c2) {
|
||||
; if (c1) {
|
||||
; only_store(p);
|
||||
; make_alias(p);
|
||||
; }
|
||||
; if (!c2) {
|
||||
; only_store(p);
|
||||
; }
|
||||
; }
|
||||
; void test16_caller(int * restrict p, int c) {
|
||||
; test16_sub(p, c, c);
|
||||
; }
|
||||
|
||||
; CHECK-LABEL define internal void @test16_sub(i32* noalias %p, i32 %c1, i32 %c2)
|
||||
define internal void @test16_sub(i32* noalias %p, i32 %c1, i32 %c2) {
|
||||
%tobool = icmp eq i32 %c1, 0
|
||||
br i1 %tobool, label %if.end, label %if.then
|
||||
|
||||
; CHECK tail call void @only_store(i32* noalias %p)
|
||||
if.then:
|
||||
tail call void @only_store(i32* %p)
|
||||
tail call void @make_alias(i32* %p)
|
||||
br label %if.end
|
||||
if.end:
|
||||
|
||||
%tobool1 = icmp eq i32 %c2, 0
|
||||
br i1 %tobool1, label %if.then2, label %if.end3
|
||||
|
||||
; FIXME: this should be tail @only_store(i32* noalias %p)
|
||||
; when test16_caller is called, c1 always equals to c2. (Note that linkage is internal)
|
||||
; Therefore, only one of the two conditions of if statementes will be fulfilled.
|
||||
; CHECK tail call void @only_store(i32* %p)
|
||||
if.then2:
|
||||
tail call void @only_store(i32* %p)
|
||||
br label %if.end3
|
||||
if.end3:
|
||||
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test16_caller(i32* %p, i32 %c) {
|
||||
tail call void @test16_sub(i32* %p, i32 %c, i32 %c)
|
||||
ret void
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user