[llvm] r256304 - Provide a way to specify inliner's attribute compatibility and merging.
Akira Hatanaka via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 22 15:57:37 PST 2015
Author: ahatanak
Date: Tue Dec 22 17:57:37 2015
New Revision: 256304
URL: http://llvm.org/viewvc/llvm-project?rev=256304&view=rev
Log:
Provide a way to specify inliner's attribute compatibility and merging.
This reapplies r256277 with two changes:
- In emitFnAttrCompatCheck, change FuncName's type to std::string to fix
a use-after-free bug.
- Remove an unnecessary install-local target in lib/IR/Makefile.
Original commit message for r252949:
Provide a way to specify inliner's attribute compatibility and merging
rules using table-gen. NFC.
This commit adds new classes CompatRule and MergeRule to Attributes.td,
which are used to generate code to check attribute compatibility and
merge attributes of the caller and callee.
rdar://problem/19836465
Modified:
llvm/trunk/include/llvm/IR/Attributes.h
llvm/trunk/include/llvm/IR/Attributes.td
llvm/trunk/lib/Analysis/InlineCost.cpp
llvm/trunk/lib/IR/Attributes.cpp
llvm/trunk/lib/IR/AttributesCompatFunc.td
llvm/trunk/lib/IR/CMakeLists.txt
llvm/trunk/lib/IR/Makefile
llvm/trunk/lib/Transforms/IPO/Inliner.cpp
llvm/trunk/utils/TableGen/Attributes.cpp
Modified: llvm/trunk/include/llvm/IR/Attributes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Attributes.h?rev=256304&r1=256303&r2=256304&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Attributes.h (original)
+++ llvm/trunk/include/llvm/IR/Attributes.h Tue Dec 22 17:57:37 2015
@@ -33,6 +33,7 @@ class AttributeSetImpl;
class AttributeSetNode;
class Constant;
template<typename T> struct DenseMapInfo;
+class Function;
class LLVMContext;
class Type;
@@ -532,6 +533,13 @@ namespace AttributeFuncs {
/// \brief Which attributes cannot be applied to a type.
AttrBuilder typeIncompatible(Type *Ty);
+/// \returns Return true if the two functions have compatible target-independent
+/// attributes for inlining purposes.
+bool areInlineCompatible(const Function &Caller, const Function &Callee);
+
+/// \brief Merge caller's and callee's attributes.
+void mergeAttributesForInlining(Function &Caller, const Function &Callee);
+
} // end AttributeFuncs namespace
} // end llvm namespace
Modified: llvm/trunk/include/llvm/IR/Attributes.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Attributes.td?rev=256304&r1=256303&r2=256304&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Attributes.td (original)
+++ llvm/trunk/include/llvm/IR/Attributes.td Tue Dec 22 17:57:37 2015
@@ -165,3 +165,28 @@ def LessPreciseFPMAD : StrBoolAttr<"less
def NoInfsFPMath : StrBoolAttr<"no-infs-fp-math">;
def NoNansFPMath : StrBoolAttr<"no-nans-fp-math">;
def UnsafeFPMath : StrBoolAttr<"unsafe-fp-math">;
+
+class CompatRule<string F> {
+ // The name of the function called to check the attribute of the caller and
+ // callee and decide whether inlining should be allowed. The function's
+ // signature must match "bool(const Function&, const Function &)", where the
+ // first parameter is the reference to the caller and the second parameter is
+ // the reference to the callee. It must return false if the attributes of the
+ // caller and callee are incompatible, and true otherwise.
+ string CompatFunc = F;
+}
+
+def : CompatRule<"isEqual<SanitizeAddressAttr>">;
+def : CompatRule<"isEqual<SanitizeThreadAttr>">;
+def : CompatRule<"isEqual<SanitizeMemoryAttr>">;
+
+class MergeRule<string F> {
+ // The name of the function called to merge the attributes of the caller and
+ // callee. The function's signature must match
+ // "void(Function&, const Function &)", where the first parameter is the
+ // reference to the caller and the second parameter is the reference to the
+ // callee.
+ string MergeFunc = F;
+}
+
+def : MergeRule<"adjustCallerSSPLevel">;
Modified: llvm/trunk/lib/Analysis/InlineCost.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InlineCost.cpp?rev=256304&r1=256303&r2=256304&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InlineCost.cpp (original)
+++ llvm/trunk/lib/Analysis/InlineCost.cpp Tue Dec 22 17:57:37 2015
@@ -1362,9 +1362,7 @@ static bool functionsHaveCompatibleAttri
Function *Callee,
TargetTransformInfo &TTI) {
return TTI.areInlineCompatible(Caller, Callee) &&
- attributeMatches(Caller, Callee, Attribute::SanitizeAddress) &&
- attributeMatches(Caller, Callee, Attribute::SanitizeMemory) &&
- attributeMatches(Caller, Callee, Attribute::SanitizeThread);
+ AttributeFuncs::areInlineCompatible(*Caller, *Callee);
}
InlineCost InlineCostAnalysis::getInlineCost(CallSite CS, Function *Callee,
Modified: llvm/trunk/lib/IR/Attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Attributes.cpp?rev=256304&r1=256303&r2=256304&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Attributes.cpp (original)
+++ llvm/trunk/lib/IR/Attributes.cpp Tue Dec 22 17:57:37 2015
@@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/Attributes.h"
+#include "llvm/IR/Function.h"
#include "AttributeImpl.h"
#include "LLVMContextImpl.h"
#include "llvm/ADT/STLExtras.h"
@@ -1431,3 +1432,80 @@ AttrBuilder AttributeFuncs::typeIncompat
return Incompatible;
}
+
+template<typename AttrClass>
+static bool isEqual(const Function &Caller, const Function &Callee) {
+ return Caller.getFnAttribute(AttrClass::getKind()) ==
+ Callee.getFnAttribute(AttrClass::getKind());
+}
+
+/// \brief Compute the logical AND of the attributes of the caller and the
+/// callee.
+///
+/// This function sets the caller's attribute to false if the callee's attribute
+/// is false.
+template<typename AttrClass>
+static void setAND(Function &Caller, const Function &Callee) {
+ if (AttrClass::isSet(Caller, AttrClass::getKind()) &&
+ !AttrClass::isSet(Callee, AttrClass::getKind()))
+ AttrClass::set(Caller, AttrClass::getKind(), false);
+}
+
+/// \brief Compute the logical OR of the attributes of the caller and the
+/// callee.
+///
+/// This function sets the caller's attribute to true if the callee's attribute
+/// is true.
+template<typename AttrClass>
+static void setOR(Function &Caller, const Function &Callee) {
+ if (!AttrClass::isSet(Caller, AttrClass::getKind()) &&
+ AttrClass::isSet(Callee, AttrClass::getKind()))
+ AttrClass::set(Caller, AttrClass::getKind(), true);
+}
+
+/// \brief If the inlined function had a higher stack protection level than the
+/// calling function, then bump up the caller's stack protection level.
+static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
+ // If upgrading the SSP attribute, clear out the old SSP Attributes first.
+ // Having multiple SSP attributes doesn't actually hurt, but it adds useless
+ // clutter to the IR.
+ AttrBuilder B;
+ B.addAttribute(Attribute::StackProtect)
+ .addAttribute(Attribute::StackProtectStrong)
+ .addAttribute(Attribute::StackProtectReq);
+ AttributeSet OldSSPAttr = AttributeSet::get(Caller.getContext(),
+ AttributeSet::FunctionIndex,
+ B);
+
+ if (Callee.hasFnAttribute(Attribute::SafeStack)) {
+ Caller.removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
+ Caller.addFnAttr(Attribute::SafeStack);
+ } else if (Callee.hasFnAttribute(Attribute::StackProtectReq) &&
+ !Caller.hasFnAttribute(Attribute::SafeStack)) {
+ Caller.removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
+ Caller.addFnAttr(Attribute::StackProtectReq);
+ } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
+ !Caller.hasFnAttribute(Attribute::SafeStack) &&
+ !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
+ Caller.removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
+ Caller.addFnAttr(Attribute::StackProtectStrong);
+ } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
+ !Caller.hasFnAttribute(Attribute::SafeStack) &&
+ !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
+ !Caller.hasFnAttribute(Attribute::StackProtectStrong))
+ Caller.addFnAttr(Attribute::StackProtect);
+}
+
+#define GET_ATTR_COMPAT_FUNC
+#include "AttributesCompatFunc.inc"
+
+bool AttributeFuncs::areInlineCompatible(const Function &Caller,
+ const Function &Callee) {
+ return hasCompatibleFnAttrs(Caller, Callee);
+}
+
+
+void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
+ const Function &Callee) {
+ mergeFnAttrs(Caller, Callee);
+}
Modified: llvm/trunk/lib/IR/AttributesCompatFunc.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AttributesCompatFunc.td?rev=256304&r1=256303&r2=256304&view=diff
==============================================================================
--- llvm/trunk/lib/IR/AttributesCompatFunc.td (original)
+++ llvm/trunk/lib/IR/AttributesCompatFunc.td Tue Dec 22 17:57:37 2015
@@ -0,0 +1 @@
+include "llvm/IR/Attributes.td"
Modified: llvm/trunk/lib/IR/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/CMakeLists.txt?rev=256304&r1=256303&r2=256304&view=diff
==============================================================================
--- llvm/trunk/lib/IR/CMakeLists.txt (original)
+++ llvm/trunk/lib/IR/CMakeLists.txt Tue Dec 22 17:57:37 2015
@@ -1,3 +1,7 @@
+set(LLVM_TARGET_DEFINITIONS AttributesCompatFunc.td)
+tablegen(LLVM AttributesCompatFunc.inc -gen-attrs)
+add_public_tablegen_target(AttributeCompatFuncTableGen)
+
add_llvm_library(LLVMCore
AsmWriter.cpp
Attributes.cpp
Modified: llvm/trunk/lib/IR/Makefile
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Makefile?rev=256304&r1=256303&r2=256304&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Makefile (original)
+++ llvm/trunk/lib/IR/Makefile Tue Dec 22 17:57:37 2015
@@ -11,16 +11,19 @@ LIBRARYNAME = LLVMCore
BUILD_ARCHIVE = 1
BUILT_SOURCES = $(PROJ_OBJ_ROOT)/include/llvm/IR/Intrinsics.gen \
- $(PROJ_OBJ_ROOT)/include/llvm/IR/Attributes.inc
+ $(PROJ_OBJ_ROOT)/include/llvm/IR/Attributes.inc \
+ $(PROJ_OBJ_ROOT)/lib/IR/AttributesCompatFunc.inc
include $(LEVEL)/Makefile.common
GENFILE:=$(PROJ_OBJ_ROOT)/include/llvm/IR/Intrinsics.gen
ATTRINCFILE:=$(PROJ_OBJ_ROOT)/include/llvm/IR/Attributes.inc
+ATTRCOMPATFUNCINCFILE:=$(PROJ_OBJ_ROOT)/lib/IR/AttributesCompatFunc.inc
INTRINSICTD := $(PROJ_SRC_ROOT)/include/llvm/IR/Intrinsics.td
INTRINSICTDS := $(wildcard $(PROJ_SRC_ROOT)/include/llvm/IR/Intrinsics*.td)
ATTRIBUTESTD := $(PROJ_SRC_ROOT)/include/llvm/IR/Attributes.td
+ATTRCOMPATFUNCTD := $(PROJ_SRC_ROOT)/lib/IR/AttributesCompatFunc.td
$(ObjDir)/Intrinsics.gen.tmp: $(ObjDir)/.dir $(INTRINSICTDS) $(LLVM_TBLGEN)
$(Echo) Building Intrinsics.gen.tmp from Intrinsics.td
@@ -40,6 +43,15 @@ $(ATTRINCFILE): $(ObjDir)/Attributes.inc
$(EchoCmd) Updated Attributes.inc because Attributes.inc.tmp \
changed significantly. )
+$(ObjDir)/AttributesCompatFunc.inc.tmp: $(ObjDir)/.dir $(ATTRCOMPATFUNCTD) $(LLVM_TBLGEN)
+ $(Echo) Building AttributesCompatFunc.inc.tmp from $(ATTRCOMPATFUNCTD)
+ $(Verb) $(LLVMTableGen) $(call SYSPATH, $(ATTRCOMPATFUNCTD)) -o $(call SYSPATH, $@) -gen-attrs
+
+$(ATTRCOMPATFUNCINCFILE): $(ObjDir)/AttributesCompatFunc.inc.tmp $(PROJ_OBJ_ROOT)/include/llvm/IR/.dir
+ $(Verb) $(CMP) -s $@ $< || ( $(CP) $< $@ && \
+ $(EchoCmd) Updated AttributesCompatFunc.inc because AttributesCompatFunc.inc.tmp \
+ changed significantly. )
+
install-local:: $(GENFILE)
$(Echo) Installing $(DESTDIR)$(PROJ_includedir)/llvm/IR/Intrinsics.gen
$(Verb) $(DataInstall) $(GENFILE) $(DESTDIR)$(PROJ_includedir)/llvm/IR/Intrinsics.gen
Modified: llvm/trunk/lib/Transforms/IPO/Inliner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Inliner.cpp?rev=256304&r1=256303&r2=256304&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/Inliner.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/Inliner.cpp Tue Dec 22 17:57:37 2015
@@ -86,39 +86,6 @@ void Inliner::getAnalysisUsage(AnalysisU
typedef DenseMap<ArrayType*, std::vector<AllocaInst*> >
InlinedArrayAllocasTy;
-/// \brief If the inlined function had a higher stack protection level than the
-/// calling function, then bump up the caller's stack protection level.
-static void AdjustCallerSSPLevel(Function *Caller, Function *Callee) {
- // If upgrading the SSP attribute, clear out the old SSP Attributes first.
- // Having multiple SSP attributes doesn't actually hurt, but it adds useless
- // clutter to the IR.
- AttrBuilder B;
- B.addAttribute(Attribute::StackProtect)
- .addAttribute(Attribute::StackProtectStrong)
- .addAttribute(Attribute::StackProtectReq);
- AttributeSet OldSSPAttr = AttributeSet::get(Caller->getContext(),
- AttributeSet::FunctionIndex,
- B);
-
- if (Callee->hasFnAttribute(Attribute::SafeStack)) {
- Caller->removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
- Caller->addFnAttr(Attribute::SafeStack);
- } else if (Callee->hasFnAttribute(Attribute::StackProtectReq) &&
- !Caller->hasFnAttribute(Attribute::SafeStack)) {
- Caller->removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
- Caller->addFnAttr(Attribute::StackProtectReq);
- } else if (Callee->hasFnAttribute(Attribute::StackProtectStrong) &&
- !Caller->hasFnAttribute(Attribute::SafeStack) &&
- !Caller->hasFnAttribute(Attribute::StackProtectReq)) {
- Caller->removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
- Caller->addFnAttr(Attribute::StackProtectStrong);
- } else if (Callee->hasFnAttribute(Attribute::StackProtect) &&
- !Caller->hasFnAttribute(Attribute::SafeStack) &&
- !Caller->hasFnAttribute(Attribute::StackProtectReq) &&
- !Caller->hasFnAttribute(Attribute::StackProtectStrong))
- Caller->addFnAttr(Attribute::StackProtect);
-}
-
/// If it is possible to inline the specified call site,
/// do so and update the CallGraph for this operation.
///
@@ -146,7 +113,7 @@ static bool InlineCallIfPossible(Pass &P
if (!InlineFunction(CS, IFI, &AAR, InsertLifetime))
return false;
- AdjustCallerSSPLevel(Caller, Callee);
+ AttributeFuncs::mergeAttributesForInlining(*Caller, *Callee);
// Look at all of the allocas that we inlined through this call site. If we
// have already inlined other allocas through other calls into this function,
Modified: llvm/trunk/utils/TableGen/Attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/Attributes.cpp?rev=256304&r1=256303&r2=256304&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/Attributes.cpp (original)
+++ llvm/trunk/utils/TableGen/Attributes.cpp Tue Dec 22 17:57:37 2015
@@ -27,6 +27,12 @@ public:
private:
void emitTargetIndependentEnums(raw_ostream &OS);
+ void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr);
+
+ void printEnumAttrClasses(raw_ostream &OS,
+ const std::vector<Record *> &Records);
+ void printStrBoolAttrClasses(raw_ostream &OS,
+ const std::vector<Record *> &Records);
RecordKeeper &Records;
};
@@ -37,7 +43,7 @@ void Attributes::emitTargetIndependentEn
OS << "#ifdef GET_ATTR_ENUM\n";
OS << "#undef GET_ATTR_ENUM\n";
- const std::vector<Record*> &Attrs =
+ std::vector<Record*> Attrs =
Records.getAllDerivedDefinitions("EnumAttr");
for (auto A : Attrs)
@@ -46,8 +52,99 @@ void Attributes::emitTargetIndependentEn
OS << "#endif\n";
}
+void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
+ OS << "#ifdef GET_ATTR_COMPAT_FUNC\n";
+ OS << "#undef GET_ATTR_COMPAT_FUNC\n";
+
+ OS << "struct EnumAttr {\n";
+ OS << " static bool isSet(const Function &Fn,\n";
+ OS << " Attribute::AttrKind Kind) {\n";
+ OS << " return Fn.hasFnAttribute(Kind);\n";
+ OS << " }\n\n";
+ OS << " static void set(Function &Fn,\n";
+ OS << " Attribute::AttrKind Kind, bool Val) {\n";
+ OS << " if (Val)\n";
+ OS << " Fn.addFnAttr(Kind);\n";
+ OS << " else\n";
+ OS << " Fn.removeFnAttr(Kind);\n";
+ OS << " }\n";
+ OS << "};\n\n";
+
+ OS << "struct StrBoolAttr {\n";
+ OS << " static bool isSet(const Function &Fn,\n";
+ OS << " StringRef Kind) {\n";
+ OS << " auto A = Fn.getFnAttribute(Kind);\n";
+ OS << " return A.getValueAsString().equals(\"true\");\n";
+ OS << " }\n\n";
+ OS << " static void set(Function &Fn,\n";
+ OS << " StringRef Kind, bool Val) {\n";
+ OS << " Fn.addFnAttr(Kind, Val ? \"true\" : \"false\");\n";
+ OS << " }\n";
+ OS << "};\n\n";
+
+ printEnumAttrClasses(OS ,Records.getAllDerivedDefinitions("EnumAttr"));
+ printStrBoolAttrClasses(OS , Records.getAllDerivedDefinitions("StrBoolAttr"));
+
+ OS << "static inline bool hasCompatibleFnAttrs(const Function &Caller,\n"
+ << " const Function &Callee) {\n";
+ OS << " bool Ret = true;\n\n";
+
+ std::vector<Record *> CompatRules =
+ Records.getAllDerivedDefinitions("CompatRule");
+
+ for (auto *Rule : CompatRules) {
+ std::string FuncName = Rule->getValueAsString("CompatFunc");
+ OS << " Ret &= " << FuncName << "(Caller, Callee);\n";
+ }
+
+ OS << "\n";
+ OS << " return Ret;\n";
+ OS << "}\n\n";
+
+ std::vector<Record *> MergeRules =
+ Records.getAllDerivedDefinitions("MergeRule");
+ OS << "static inline void mergeFnAttrs(Function &Caller,\n"
+ << " const Function &Callee) {\n";
+
+ for (auto *Rule : MergeRules) {
+ std::string FuncName = Rule->getValueAsString("MergeFunc");
+ OS << " " << FuncName << "(Caller, Callee);\n";
+ }
+
+ OS << "}\n\n";
+
+ OS << "#endif\n";
+}
+
+void Attributes::printEnumAttrClasses(raw_ostream &OS,
+ const std::vector<Record *> &Records) {
+ OS << "// EnumAttr classes\n";
+ for (const auto *R : Records) {
+ OS << "struct " << R->getName() << "Attr : EnumAttr {\n";
+ OS << " static enum Attribute::AttrKind getKind() {\n";
+ OS << " return llvm::Attribute::" << R->getName() << ";\n";
+ OS << " }\n";
+ OS << "};\n";
+ }
+ OS << "\n";
+}
+
+void Attributes::printStrBoolAttrClasses(raw_ostream &OS,
+ const std::vector<Record *> &Records) {
+ OS << "// StrBoolAttr classes\n";
+ for (const auto *R : Records) {
+ OS << "struct " << R->getName() << "Attr : StrBoolAttr {\n";
+ OS << " static const char *getKind() {\n";
+ OS << " return \"" << R->getValueAsString("AttrString") << "\";\n";
+ OS << " }\n";
+ OS << "};\n";
+ }
+ OS << "\n";
+}
+
void Attributes::emit(raw_ostream &OS) {
emitTargetIndependentEnums(OS);
+ emitFnAttrCompatCheck(OS, false);
}
namespace llvm {
More information about the llvm-commits
mailing list