blob: 945fe54f7d223b4a10a17ab269675bb15be6683c [file] [log] [blame]
; PR14190
; Verify that TD keeps unresolved callsites and properly
; marks nodes reachable from them as incomplete.
; This is important as otherwise a DSA client (like DSAA) will
; erroneously conclude that retptr/ptr in @indirect cannot alias.
; Verify we do eventually discover direct/indirect/indirect2 call foo
; RUN: dsaopt %s -dsa-td -analyze -check-callees=direct,foo
; RUN: dsaopt %s -dsa-td -analyze -check-callees=indirect,foo
; RUN: dsaopt %s -dsa-td -analyze -check-callees=indirect2,foo
; Within each, by the end of TD, we should either know the effects of calling @foo
; or mark the related nodes incomplete.
; Check this:
; RUN: dsaopt %s -dsa-td -analyze -check-same-node=@direct:ptr,@direct:retptr
; RUN: dsaopt %s -dsa-td -analyze -verify-flags=@direct:ptr-I,@direct:retptr-I
; RUN: dsaopt %s -dsa-td -analyze -check-not-same-node=@indirect:ptr,@indirect:retptr
; RUN: dsaopt %s -dsa-td -analyze -verify-flags=@indirect:ptr+I,@indirect:retptr+I
; RUN: dsaopt %s -dsa-td -analyze -check-not-same-node=@indirect2:ptr,@indirect2:retptr
; RUN: dsaopt %s -dsa-td -analyze -verify-flags=@indirect2:ptr+I,@indirect2:retptr+I
; Check that EQTD also has this behavior.
; RUN: dsaopt %s -dsa-eqtd -analyze -check-same-node=@direct:ptr,@direct:retptr
; RUN: dsaopt %s -dsa-eqtd -analyze -verify-flags=@direct:ptr-I,@direct:retptr-I
; RUN: dsaopt %s -dsa-eqtd -analyze -check-not-same-node=@indirect:ptr,@indirect:retptr
; RUN: dsaopt %s -dsa-eqtd -analyze -verify-flags=@indirect:ptr+I,@indirect:retptr+I
; RUN: dsaopt %s -dsa-eqtd -analyze -check-not-same-node=@indirect2:ptr,@indirect2:retptr
; RUN: dsaopt %s -dsa-eqtd -analyze -verify-flags=@indirect2:ptr+I,@indirect2:retptr+I
; ModuleID = 'test-fp.bc'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define i8* @foo(i8* %ptr) nounwind {
ret i8* %ptr
}
; Call foo with ptr
define void @direct(i8* %ptr) {
%retptr = call i8* @foo(i8* %ptr)
%val = load i8* %retptr
ret void
}
; Same, but using indirect fp not resolved until inlined into main
define void @indirect(i8* (i8*)* %fp, i8* %ptr) {
%retptr = call i8* %fp(i8* %ptr)
%val = load i8* %retptr
ret void
}
; Same, but using indirect fp not resolved until inlined into main
; with an additional level of indirection
define void @indirect2(i8* (i8*)** %fpp, i8* %ptr) {
%fp = load i8* (i8*)** %fpp
%retptr = call i8* %fp(i8* %ptr)
%val = load i8* %retptr
ret void
}
define i32 @main(i32 %argc, i8** nocapture %argv) nounwind {
; Conjure some i8*
%ptr = load i8** %argv, align 8
call void @direct(i8* %ptr)
call void @indirect(i8* (i8*)* @foo, i8* %ptr)
%fpp = alloca i8* (i8*)*, align 8
store i8* (i8*)* @foo, i8* (i8*)** %fpp, align 8
call void @indirect2(i8* (i8*)** %fpp, i8* %ptr)
ret i32 0
}