[BasicAA] Don't short-circuit non-capturing arguments

This is an alternative to D153464. BasicAA currently assumes that
an unescaped alloca cannot be read through non-nocapture arguments
of a call, based on the argument that if the argument were based on
the alloca, it would not be unescaped.

This currently fails in the case where the call is an ephemeral value
and as such does not count as a capture. It also happens for calls
that are readonly+nounwind+void, though that case tends to not matter
in practice, because such calls will get DCEd anyway.

Differential Revision: https://reviews.llvm.org/D153511
This commit is contained in:
Nikita Popov committed 2023-06-26 12:27:32 +02:00
1 parent 81e3779a13
commit c0de28b92e
2 files changed
+13 -11

No files matched your search

+6 -9
View File
@@ -864,9 +864,11 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call,
if (!AI->isStaticAlloca() && isIntrinsicCall(Call, Intrinsic::stackrestore))
return ModRefInfo::Mod;
// If the pointer is to a locally allocated object that does not escape,
// then the call can not mod/ref the pointer unless the call takes the pointer
// as an argument, and itself doesn't capture it.
// A call can access a locally allocated object either because it is passed as
// an argument to the call, or because it has escaped prior to the call.
//
// Make sure the object has not escaped here, and then check that none of the
// call arguments alias the object below.
if (!isa<Constant>(Object) && Call != Object &&
AAQI.CI->isNotCapturedBeforeOrAt(Object, Call)) {
@@ -877,12 +879,7 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call,
unsigned OperandNo = 0;
for (auto CI = Call->data_operands_begin(), CE = Call->data_operands_end();
CI != CE; ++CI, ++OperandNo) {
// Only look at the no-capture or byval pointer arguments. If this
// pointer were passed to arguments that were neither of these, then it
// couldn't be no-capture.
if (!(*CI)->getType()->isPointerTy() ||
(!Call->doesNotCapture(OperandNo) && OperandNo < Call->arg_size() &&
!Call->isByValArgument(OperandNo)))
if (!(*CI)->getType()->isPointerTy())
continue;
// Call doesn't access memory through this operand, so we don't care
@@ -22,11 +22,16 @@ else:
ret i1 0
}
; FIXME: At the moment, the function is incorrectly simplified to unreachable.
define i32 @test() {
; CHECK-LABEL: define i32 @test() {
; CHECK-NEXT: entry:
; CHECK-NEXT: unreachable
; CHECK-NEXT: br label [[THEN_I:%.*]]
; CHECK: then.i:
; CHECK-NEXT: [[RES_I:%.*]] = call i1 @cond()
; CHECK-NEXT: br label [[CHECK_COND_EXIT:%.*]]
; CHECK: check_cond.exit:
; CHECK-NEXT: call void @llvm.assume(i1 [[RES_I]])
; CHECK-NEXT: ret i32 0
;
entry:
%a = alloca i32, align 4