Index: llvm/include/llvm/Transforms/IPO/Attributor.h =================================================================== --- llvm/include/llvm/Transforms/IPO/Attributor.h +++ llvm/include/llvm/Transforms/IPO/Attributor.h @@ -1545,6 +1545,31 @@ static const char ID; }; +/// An abstract interface for value simplify abstract attribute. +struct AAValueSimplify : public StateWrapper, + public IRPosition { + AAValueSimplify(const IRPosition &IRP) : IRPosition(IRP) {} + + /// Return an IR position, see struct IRPosition. + /// + ///{ + IRPosition &getIRPosition() { return *this; } + const IRPosition &getIRPosition() const { return *this; } + ///} + + /// Return an assumed simplified value if a single candidate is found. If + /// there cannot be one, return a nullptr. If it is not clear yet, return the + /// Optional::NoneType. + virtual Optional getAssumedSimplifiedValue(Attributor &A) const; + + /// Create an abstract attribute view for the position \p IRP. + static AAValueSimplify &createForPosition(const IRPosition &IRP, + Attributor &A); + + /// Unique ID (due to the unique address) + static const char ID; +}; + } // end namespace llvm #endif // LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H Index: llvm/lib/Transforms/IPO/Attributor.cpp =================================================================== --- llvm/lib/Transforms/IPO/Attributor.cpp +++ llvm/lib/Transforms/IPO/Attributor.cpp @@ -2348,6 +2348,157 @@ /// NoReturn attribute deduction for a call sites. using AANoReturnCallSite = AANoReturnFunction; +/// ------------------ Value Simplify Attribute ---------------------------- +struct AAValueSimplifyImpl : AAValueSimplify { + AAValueSimplifyImpl(const IRPosition &IRP) : AAValueSimplify(IRP) {} + + /// See AbstractAttribute::getAsStr(). + const std::string getAsStr() const override { + return getAssumed() ? (getKnown() ? "simplified" : "maybe-simple") + : "not-simple"; + } + + /// See AbstractAttribute::trackStatistics() + void trackStatistics() const override {} + + /// See AAValueSimplify::getAssumedSimplifiedValue() + Optional getAssumedSimplifiedValue(Attributor &A) const override { + if (!getAssumed()) + return nullptr; + return SimplifiedAssociatedValue; + } + + /// Helper function for querying AAValueSimplify and updating candicate. + static bool checkAndUpdate(Attributor &A, const AbstractAttribute &QueryingAA, + Value &V, bool &ExistNone, + Optional &SimplifiedValue) { + auto &ValueSimpifyAA = + A.getAAFor(QueryingAA, IRPosition::value(V), false); + + Optional Simplified = ValueSimpifyAA.getAssumedSimplifiedValue(A); + + if (!Simplified.hasValue()) { + ExistNone = true; + return true; + } + + if (SimplifiedValue.hasValue()) + return SimplifiedValue == Simplified; + + SimplifiedValue = Simplified; + return true; + } + +protected: + Optional SimplifiedAssociatedValue; +}; + +struct AAValueSimplifyArgument final : AAValueSimplifyImpl { + AAValueSimplifyArgument(const IRPosition &IRP) : AAValueSimplifyImpl(IRP) {} + + /// See AbstractAttribute::manifest(...). + ChangeStatus manifest(Attributor &A) override { + ChangeStatus Changed = ChangeStatus::UNCHANGED; + + // Bookkeeping. + assert(isValidState()); + // TODO: add stats + + if (!SimplifiedAssociatedValue.hasValue() || + !SimplifiedAssociatedValue.getValue()) + return Changed; + + if (auto *RVC = dyn_cast(SimplifiedAssociatedValue.getValue())) { + // We can replace the argument with the the constant. + if (Function *F = getAnchorScope()) { + Argument &Arg = cast(getAnchorValue()); + if (!Arg.user_empty()) { + Arg.replaceAllUsesWith(RVC); + Changed = ChangeStatus::CHANGED; + } + } + } + + return Changed | AAValueSimplifyImpl::manifest(A); + } + + /// See AbstractAttribute::initialize(...). + void initialize(Attributor &A) override { + if (!getAssociatedFunction()) + indicatePessimisticFixpoint(); + } + + /// See AbstractAttribute::updateImpl(...). + ChangeStatus updateImpl(Attributor &A) override { + bool ExistNone = false; + Optional SimplifiedValue; + + auto PredForCallSite = [&](CallSite CS) { + return checkAndUpdate(A, *this, *CS.getArgOperand(getArgNo()), ExistNone, + SimplifiedValue); + }; + + if (!A.checkForAllCallSites(PredForCallSite, *this, true)) + return indicatePessimisticFixpoint(); + + SimplifiedAssociatedValue = SimplifiedValue; + + // If everyting is clear, reach optimistic fixpoint. + return ExistNone ? ChangeStatus::UNCHANGED : indicateOptimisticFixpoint(); + } +}; + +struct AAValueSimplifyReturned final : AAValueSimplifyImpl { + AAValueSimplifyReturned(const IRPosition &IRP) : AAValueSimplifyImpl(IRP) {} + + /// See AbstractAttribute::initialize(...). + void initialize(Attributor &A) override { + if (!getAssociatedFunction()) + indicatePessimisticFixpoint(); + } + + /// See AbstractAttribute::updateImpl(...). + ChangeStatus updateImpl(Attributor &A) override { + bool ExistNone = false; + Optional SimplifiedValue; + + auto PredForReturned = [&](Value &V, + const SmallSetVector &) { + return checkAndUpdate(A, *this, V, ExistNone, SimplifiedValue); + }; + + if (!A.checkForAllReturnedValuesAndReturnInsts(PredForReturned, *this)) + return indicatePessimisticFixpoint(); + + SimplifiedAssociatedValue = SimplifiedValue; + + // If everyting is clear, reach optimistic fixpoint. + return ExistNone ? ChangeStatus::UNCHANGED : indicateOptimisticFixpoint(); + } +}; + +struct AAValueSimplifyFloating final : AAValueSimplifyImpl { + AAValueSimplifyFloating(const IRPosition &IRP) : AAValueSimplifyImpl(IRP) {} + + /// See AbstractAttribute::initialize(...). + void initialize(Attributor &A) override { + Value &V = getAnchorValue(); + if (isa(V)) { + // TODO: add other stuffs + SimplifiedAssociatedValue = &V; + indicateOptimisticFixpoint(); + } + } + + /// See AbstractAttribute::updateImpl(...). + ChangeStatus updateImpl(Attributor &A) override { + // TODO: Implement this for phi, GEP, and etc. + return indicatePessimisticFixpoint(); + } +}; +using AAValueSimplifyCallSiteReturned = AAValueSimplifyReturned; +using AAValueSimplifyCallSiteArgument = AAValueSimplifyFloating; + /// ---------------------------------------------------------------------------- /// Attributor /// ---------------------------------------------------------------------------- @@ -2806,8 +2957,9 @@ // though it is an argument attribute. checkAndRegisterAA(FPos, *this, Whitelist); + IRPosition RetPos = IRPosition::returned(F); + checkAndRegisterAA(RetPos, *this, Whitelist); if (ReturnType->isPointerTy()) { - IRPosition RetPos = IRPosition::returned(F); // Every function with pointer return type might be marked align. checkAndRegisterAA(RetPos, *this, Whitelist); @@ -2825,8 +2977,10 @@ } for (Argument &Arg : F.args()) { + IRPosition ArgPos = IRPosition::argument(Arg); + checkAndRegisterAA(ArgPos, *this, Whitelist); + if (Arg.getType()->isPointerTy()) { - IRPosition ArgPos = IRPosition::argument(Arg); // Every argument with pointer type might be marked nonnull. checkAndRegisterAA(ArgPos, *this, Whitelist); @@ -2890,9 +3044,13 @@ CallSite CS(&I); if (CS && CS.getCalledFunction()) { for (int i = 0, e = CS.getCalledFunction()->arg_size(); i < e; i++) { + + IRPosition CSArgPos = IRPosition::callsite_argument(CS, i); + checkAndRegisterAA(CSArgPos, *this, + Whitelist); + if (!CS.getArgument(i)->getType()->isPointerTy()) continue; - IRPosition CSArgPos = IRPosition::callsite_argument(CS, i); // Call site argument attribute "non-null". checkAndRegisterAA(CSArgPos, *this, @@ -3059,6 +3217,7 @@ const char AAIsDead::ID = 0; const char AADereferenceable::ID = 0; const char AAAlign::ID = 0; +const char AAValueSimplify::ID = 0; // Macro magic to create the static generator function for attributes that // follow the naming scheme. @@ -3119,6 +3278,7 @@ CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAlias) CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AADereferenceable) CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAlign) +CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueSimplify) #undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION #undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION Index: llvm/test/Transforms/FunctionAttrs/align.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/align.ll +++ llvm/test/Transforms/FunctionAttrs/align.ll @@ -105,7 +105,7 @@ ;