Commit 88b04ef8 authored by Hideto Ueno's avatar Hideto Ueno
Browse files

[Attributor] Use must-be-executed-context in align deduction

Summary:
This patch introduces align attribute deduction for callsite argument, function argument, function returned and floating value based on must-be-executed-context.

Reviewers: jdoerfert, sstefan1

Reviewed By: jdoerfert

Subscribers: hiraditya, jfb, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D69797
parent 43ff6347
Loading
Loading
Loading
Loading
+59 −20
Original line number Diff line number Diff line
@@ -3086,6 +3086,38 @@ struct AADereferenceableCallSiteReturned final

// ------------------------ Align Argument Attribute ------------------------

static unsigned int getKnownAlignForUse(Attributor &A,
                                        AbstractAttribute &QueryingAA,
                                        Value &AssociatedValue, const Use *U,
                                        const Instruction *I, bool &TrackUse) {
  if (ImmutableCallSite ICS = ImmutableCallSite(I)) {
    if (ICS.isBundleOperand(U) || ICS.isCallee(U))
      return 0;

    unsigned ArgNo = ICS.getArgumentNo(U);
    IRPosition IRP = IRPosition::callsite_argument(ICS, ArgNo);
    // As long as we only use known information there is no need to track
    // dependences here.
    auto &AlignAA = A.getAAFor<AAAlign>(QueryingAA, IRP,
                                        /* TrackDependence */ false);
    return AlignAA.getKnownAlign();
  }

  // We need to follow common pointer manipulation uses to the accesses they
  // feed into.
  // TODO: Consider gep instruction
  if (isa<CastInst>(I)) {
    TrackUse = true;
    return 0;
  }

  if (auto *SI = dyn_cast<StoreInst>(I))
    return SI->getAlignment();
  else if (auto *LI = dyn_cast<LoadInst>(I))
    return LI->getAlignment();

  return 0;
}
struct AAAlignImpl : AAAlign {
  AAAlignImpl(const IRPosition &IRP) : AAAlign(IRP) {}

@@ -3143,6 +3175,15 @@ struct AAAlignImpl : AAAlign {
      Attrs.emplace_back(
          Attribute::getWithAlignment(Ctx, Align(getAssumedAlign())));
  }
  /// See AAFromMustBeExecutedContext
  bool followUse(Attributor &A, const Use *U, const Instruction *I) {
    bool TrackUse = false;

    unsigned int KnownAlign = getKnownAlignForUse(A, *this, getAssociatedValue(), U, I, TrackUse);
    takeKnownMaximum(KnownAlign);

    return TrackUse;
  }

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr() const override {
@@ -3153,11 +3194,14 @@ struct AAAlignImpl : AAAlign {
};

/// Align attribute for a floating value.
struct AAAlignFloating : AAAlignImpl {
  AAAlignFloating(const IRPosition &IRP) : AAAlignImpl(IRP) {}
struct AAAlignFloating : AAFromMustBeExecutedContext<AAAlign, AAAlignImpl> {
  using Base = AAFromMustBeExecutedContext<AAAlign, AAAlignImpl>;
  AAAlignFloating(const IRPosition &IRP) : Base(IRP) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    Base::updateImpl(A);

    const DataLayout &DL = A.getDataLayout();

    auto VisitValueCB = [&](Value &V, AAAlign::StateType &T,
@@ -3203,9 +3247,12 @@ struct AAAlignReturned final

/// Align attribute for function argument.
struct AAAlignArgument final
    : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
    : AAArgumentFromCallSiteArgumentsAndMustBeExecutedContext<AAAlign,
                                                              AAAlignImpl> {
  AAAlignArgument(const IRPosition &IRP)
      : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>(IRP) {}
      : AAArgumentFromCallSiteArgumentsAndMustBeExecutedContext<AAAlign,
                                                                AAAlignImpl>(
            IRP) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(aligned) }
@@ -3224,30 +3271,22 @@ struct AAAlignCallSiteArgument final : AAAlignFloating {
};

/// Align attribute deduction for a call site return value.
struct AAAlignCallSiteReturned final : AAAlignImpl {
  AAAlignCallSiteReturned(const IRPosition &IRP) : AAAlignImpl(IRP) {}
struct AAAlignCallSiteReturned final
    : AACallSiteReturnedFromReturnedAndMustBeExecutedContext<AAAlign,
                                                             AAAlignImpl> {
  using Base =
      AACallSiteReturnedFromReturnedAndMustBeExecutedContext<AAAlign,
                                                             AAAlignImpl>;
  AAAlignCallSiteReturned(const IRPosition &IRP) : Base(IRP) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    AAAlignImpl::initialize(A);
    Base::initialize(A);
    Function *F = getAssociatedFunction();
    if (!F)
      indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness information and then it makes
    //       sense to specialize attributes for call sites arguments instead of
    //       redirecting requests to the callee argument.
    Function *F = getAssociatedFunction();
    const IRPosition &FnPos = IRPosition::returned(*F);
    auto &FnAA = A.getAAFor<AAAlign>(*this, FnPos);
    return clampStateAndIndicateChange(
        getState(), static_cast<const AAAlign::StateType &>(FnAA.getState()));
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(align); }
};
+7 −0
Original line number Diff line number Diff line
@@ -330,5 +330,12 @@ e:
  ret i32* %phi
}


; ATTRIBUTOR: define i64 @test11(i32* nocapture nofree nonnull readonly align 8 dereferenceable(8) %p)
define i64 @test11(i32* %p) {
  %p-cast = bitcast i32* %p to i64*
  %ret = load i64, i64* %p-cast, align 8
  ret i64 %ret
}
attributes #0 = { nounwind uwtable noinline }
attributes #1 = { uwtable noinline }
+4 −3
Original line number Diff line number Diff line
@@ -244,7 +244,7 @@ declare i32 @printf(i8* nocapture, ...)
; }
;
; There should *not* be a no-capture attribute on %a
; CHECK: define nonnull dereferenceable(8) i64* @not_captured_but_returned_0(i64* nofree nonnull returned writeonly dereferenceable(8) "no-capture-maybe-returned" %a)
; CHECK: define nonnull align 8 dereferenceable(8) i64* @not_captured_but_returned_0(i64* nofree nonnull returned writeonly align 8 dereferenceable(8) "no-capture-maybe-returned" %a)

define i64* @not_captured_but_returned_0(i64* %a) #0 {
entry:
@@ -260,7 +260,8 @@ entry:
; }
;
; There should *not* be a no-capture attribute on %a
; CHECK: define nonnull dereferenceable(8) i64* @not_captured_but_returned_1(i64* nofree nonnull writeonly dereferenceable(16) "no-capture-maybe-returned" %a)
; FIXME: %a should have align 8
; CHECK: define nonnull align 8 dereferenceable(8) i64* @not_captured_but_returned_1(i64* nofree nonnull writeonly dereferenceable(16) "no-capture-maybe-returned" %a)
define i64* @not_captured_but_returned_1(i64* %a) #0 {
entry:
  %add.ptr = getelementptr inbounds i64, i64* %a, i64 1
@@ -320,7 +321,7 @@ entry:
; }
;
; There should *not* be a no-capture attribute on %a
; CHECK: define nonnull dereferenceable(8) i64* @negative_test_not_captured_but_returned_call_1a(i64* nofree writeonly "no-capture-maybe-returned" %a)
; CHECK: define nonnull align 8 dereferenceable(8) i64* @negative_test_not_captured_but_returned_call_1a(i64* nofree writeonly "no-capture-maybe-returned" %a)
define i64* @negative_test_not_captured_but_returned_call_1a(i64* %a) #0 {
entry:
  %call = call i64* @not_captured_but_returned_1(i64* %a)
+2 −2
Original line number Diff line number Diff line
@@ -254,7 +254,7 @@ return: ; preds = %cond.end, %if.then3
;
; FNATTR:  define i32* @rt0(i32* readonly %a)
; BOTH:      Function Attrs: nofree noinline norecurse noreturn nosync nounwind readonly uwtable
; BOTH-NEXT: define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @rt0(i32* nocapture nofree nonnull readonly dereferenceable(4) %a)
; BOTH-NEXT: define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @rt0(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) %a)
define i32* @rt0(i32* %a) #0 {
entry:
  %v = load i32, i32* %a, align 4
@@ -272,7 +272,7 @@ entry:
;
; FNATTR:  define noalias i32* @rt1(i32* nocapture readonly %a)
; BOTH: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readonly uwtable
; BOTH-NEXT:    define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @rt1(i32* nocapture nofree nonnull readonly dereferenceable(4) %a)
; BOTH-NEXT:    define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @rt1(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) %a)
define i32* @rt1(i32* %a) #0 {
entry:
  %v = load i32, i32* %a, align 4
+1 −1
Original line number Diff line number Diff line
@@ -189,7 +189,7 @@ if.false:
}

define i32* @f7_3() {
; ATTRIBUTOR: define nonnull dereferenceable(4) i32* @f7_3()
; ATTRIBUTOR: define nonnull align 16 dereferenceable(4) i32* @f7_3()
  %ptr = tail call i32* @unkown_ptr()
  store i32 10, i32* %ptr, align 16
  ret i32* %ptr
Loading