[llvm] r256277 - 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 12:00:05 PST 2015
Author: ahatanak
Date: Tue Dec 22 14:00:05 2015
New Revision: 256277
URL: http://llvm.org/viewvc/llvm-project?rev=256277&view=rev
Log:
Provide a way to specify inliner's attribute compatibility and merging.
This reapplies r252990 and r252949. I've added member function getKind
to the Attr classes which returns the enum or string of the attribute.
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/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=256277&r1=256276&r2=256277&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Attributes.h (original)
+++ llvm/trunk/include/llvm/IR/Attributes.h Tue Dec 22 14:00:05 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=256277&r1=256276&r2=256277&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Attributes.td (original)
+++ llvm/trunk/include/llvm/IR/Attributes.td Tue Dec 22 14:00:05 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=256277&r1=256276&r2=256277&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InlineCost.cpp (original)
+++ llvm/trunk/lib/Analysis/InlineCost.cpp Tue Dec 22 14:00:05 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=256277&r1=256276&r2=256277&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Attributes.cpp (original)
+++ llvm/trunk/lib/IR/Attributes.cpp Tue Dec 22 14:00:05 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/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/CMakeLists.txt?rev=256277&r1=256276&r2=256277&view=diff
==============================================================================
--- llvm/trunk/lib/IR/CMakeLists.txt (original)
+++ llvm/trunk/lib/IR/CMakeLists.txt Tue Dec 22 14:00:05 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=256277&r1=256276&r2=256277&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Makefile (original)
+++ llvm/trunk/lib/IR/Makefile Tue Dec 22 14:00:05 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
@@ -47,3 +59,7 @@ install-local:: $(GENFILE)
install-local:: $(ATTRINCFILE)
$(Echo) Installing $(DESTDIR)$(PROJ_includedir)/llvm/IR/Attributes.inc
$(Verb) $(DataInstall) $(ATTRINCFILE) $(DESTDIR)$(PROJ_includedir)/llvm/IR/Attributes.inc
+
+install-local:: $(ATTRCOMPATFUNCINCFILE)
+ $(Echo) Installing $(DESTDIR)$(PROJ_libdir)/IR/AttributesCompatFunc.inc
+ $(Verb) $(DataInstall) $(ATTRCOMPATFUNCINCFILE) $(DESTDIR)$(PROJ_libdir)/IR/AttributesCompatFunc.inc
Modified: llvm/trunk/lib/Transforms/IPO/Inliner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Inliner.cpp?rev=256277&r1=256276&r2=256277&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/Inliner.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/Inliner.cpp Tue Dec 22 14:00:05 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=256277&r1=256276&r2=256277&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/Attributes.cpp (original)
+++ llvm/trunk/utils/TableGen/Attributes.cpp Tue Dec 22 14:00:05 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;
};
@@ -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) {
+ StringRef 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) {
+ StringRef 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