Commit ff6254dc authored by Johannes Doerfert's avatar Johannes Doerfert
Browse files

[Attributor][FIX] Handle non-pointers when following uses

When we follow uses, e.g., in AAMemoryBehavior or AANoCapture, we need
to make sure the value is a pointer before we ask for abstract
attributes only valid for pointers. This happens because we follow
pointers through calls that do not capture but may return the value.
parent 9dcf889d
Loading
Loading
Loading
Loading
+14 −7
Original line number Diff line number Diff line
@@ -5074,12 +5074,16 @@ bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &A, const Use *U,
  // general capturing of the underlying argument. The reason is that the
  // call might the argument "through return", which we allow and for which we
  // need to check call users.
  if (U->get()->getType()->isPointerTy()) {
    unsigned ArgNo = ICS.getArgumentNo(U);
  const auto &ArgNoCaptureAA =
      A.getAAFor<AANoCapture>(*this, IRPosition::callsite_argument(ICS, ArgNo));
    const auto &ArgNoCaptureAA = A.getAAFor<AANoCapture>(
        *this, IRPosition::callsite_argument(ICS, ArgNo));
    return !ArgNoCaptureAA.isAssumedNoCapture();
  }

  return true;
}

void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &A, const Use *U,
                                            const Instruction *UserI) {
  assert(UserI->mayReadOrWriteMemory());
@@ -5123,9 +5127,12 @@ void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &A, const Use *U,

    // Adjust the possible access behavior based on the information on the
    // argument.
    unsigned ArgNo = ICS.getArgumentNo(U);
    const IRPosition &ArgPos = IRPosition::callsite_argument(ICS, ArgNo);
    const auto &MemBehaviorAA = A.getAAFor<AAMemoryBehavior>(*this, ArgPos);
    IRPosition Pos;
    if (U->get()->getType()->isPointerTy())
      Pos = IRPosition::callsite_argument(ICS, ICS.getArgumentNo(U));
    else
      Pos = IRPosition::callsite_function(ICS);
    const auto &MemBehaviorAA = A.getAAFor<AAMemoryBehavior>(*this, Pos);
    // "assumed" has at most the same bits as the MemBehaviorAA assumed
    // and at least "known".
    intersectAssumedBits(MemBehaviorAA.getAssumed());
+14 −0
Original line number Diff line number Diff line
@@ -342,5 +342,19 @@ entry:
  ret i8* %p
}

declare i8* @maybe_returned_ptr(i8* readonly %ptr) readonly nounwind
declare i8 @maybe_returned_val(i8* %ptr) readonly nounwind
declare void @val_use(i8 %ptr) readonly nounwind

; FIXME: Both pointers should be nocapture
define void @ptr_uses(i8* %ptr, i8* %wptr) {
; CHECK: define void @ptr_uses(i8* %ptr, i8* nocapture nonnull writeonly dereferenceable(1) %wptr)
  %call_ptr = call i8* @maybe_returned_ptr(i8* %ptr)
  %call_val = call i8 @maybe_returned_val(i8* %call_ptr)
  call void @val_use(i8 %call_val)
  store i8 0, i8* %wptr
  ret void
}

declare i8* @llvm.launder.invariant.group.p0i8(i8*)
declare i8* @llvm.strip.invariant.group.p0i8(i8*)
+12 −0
Original line number Diff line number Diff line
@@ -195,3 +195,15 @@ define void @testbyval(i8* %read_only) {
  ret void
}
;}

declare i8* @maybe_returned_ptr(i8* readonly %ptr) readonly nounwind
declare i8 @maybe_returned_val(i8* %ptr) readonly nounwind
declare void @val_use(i8 %ptr) readonly nounwind

define void @ptr_uses(i8* %ptr) {
; ATTRIBUTOR: define void @ptr_uses(i8* nocapture readonly %ptr)
  %call_ptr = call i8* @maybe_returned_ptr(i8* %ptr)
  %call_val = call i8 @maybe_returned_val(i8* %call_ptr)
  call void @val_use(i8 %call_val)
  ret void
}