1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[BasicAA] Don't assume tail calls with byval don't alias allocas

Summary:
Calls marked 'tail' cannot read or write allocas from the current frame
because the current frame might be destroyed by the time they run.
However, a tail call may use an alloca with byval. Calling with byval
copies the contents of the alloca into argument registers or stack
slots, so there is no lifetime issue. Tail calls never modify allocas,
so we can return just ModRefInfo::Ref.

Fixes PR38466, a longstanding bug.

Reviewers: hfinkel, nlewycky, gbiv, george.burgess.iv

Subscribers: hiraditya, llvm-commits

Differential Revision: https://reviews.llvm.org/D50679

llvm-svn: 339636
This commit is contained in:
Reid Kleckner 2018-08-14 01:24:35 +00:00
parent f1e6ac9016
commit 6e852d9c3d
3 changed files with 45 additions and 6 deletions

View File

@ -801,14 +801,15 @@ ModRefInfo BasicAAResult::getModRefInfo(ImmutableCallSite CS,
const Value *Object = GetUnderlyingObject(Loc.Ptr, DL);
// If this is a tail call and Loc.Ptr points to a stack location, we know that
// the tail call cannot access or modify the local stack.
// We cannot exclude byval arguments here; these belong to the caller of
// the current function not to the current function, and a tail callee
// may reference them.
// Calls marked 'tail' cannot read or write allocas from the current frame
// because the current frame might be destroyed by the time they run. However,
// a tail call may use an alloca with byval. Calling with byval copies the
// contents of the alloca into argument registers or stack slots, so there is
// no lifetime issue.
if (isa<AllocaInst>(Object))
if (const CallInst *CI = dyn_cast<CallInst>(CS.getInstruction()))
if (CI->isTailCall())
if (CI->isTailCall() &&
!CI->getAttributes().hasAttrSomewhere(Attribute::ByVal))
return ModRefInfo::NoModRef;
// If the pointer is to a locally allocated object that does not escape,

View File

@ -0,0 +1,15 @@
; RUN: opt -basicaa -aa-eval -print-all-alias-modref-info -disable-output < %s 2>&1 | FileCheck %s
declare void @takebyval(i32* byval %p)
define i32 @tailbyval() {
entry:
%p = alloca i32
store i32 42, i32* %p
tail call void @takebyval(i32* byval %p)
%rv = load i32, i32* %p
ret i32 %rv
}
; FIXME: This should be Just Ref.
; CHECK-LABEL: Function: tailbyval: 1 pointers, 1 call sites
; CHECK-NEXT: Both ModRef: Ptr: i32* %p <-> tail call void @takebyval(i32* byval %p)

View File

@ -0,0 +1,23 @@
; RUN: opt -dse -S < %s | FileCheck %s
; Don't eliminate stores to allocas before tail calls to functions that use
; byval. It's correct to mark calls like these as 'tail'. To implement this tail
; call, the backend should copy the bytes from the alloca into the argument area
; before clearing the stack.
target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"
target triple = "i386-unknown-linux-gnu"
declare void @g(i32* byval %p)
define void @f(i32* byval %x) {
entry:
%p = alloca i32
%v = load i32, i32* %x
store i32 %v, i32* %p
tail call void @g(i32* byval %p)
ret void
}
; CHECK-LABEL: define void @f(i32* byval %x)
; CHECK: store i32 %v, i32* %p
; CHECK: tail call void @g(i32* byval %p)