forked from OSchip/llvm-project
[NFC] Move a recently added utility into a location to enable reuse
About to refresh a patch that uses this in FunctionAtrrs, doing the move seperately to control build times.
This commit is contained in:
parent
61a85da882
commit
3ce61fb6d6
|
@ -488,6 +488,15 @@ bool canReplaceOperandWithVariable(const Instruction *I, unsigned OpIdx);
|
||||||
/// Invert the given true/false value, possibly reusing an existing copy.
|
/// Invert the given true/false value, possibly reusing an existing copy.
|
||||||
Value *invertCondition(Value *Condition);
|
Value *invertCondition(Value *Condition);
|
||||||
|
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Assorted
|
||||||
|
//
|
||||||
|
|
||||||
|
/// If we can infer one attribute from another on the declaration of a
|
||||||
|
/// function, explicitly materialize the maximal set in the IR.
|
||||||
|
bool inferAttributesFromOthers(Function &F);
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif // LLVM_TRANSFORMS_UTILS_LOCAL_H
|
#endif // LLVM_TRANSFORMS_UTILS_LOCAL_H
|
||||||
|
|
|
@ -15,52 +15,21 @@
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include "llvm/Transforms/Utils/BuildLibCalls.h"
|
#include "llvm/Transforms/Utils/BuildLibCalls.h"
|
||||||
|
#include "llvm/Transforms/Utils/Local.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
#define DEBUG_TYPE "inferattrs"
|
#define DEBUG_TYPE "inferattrs"
|
||||||
|
|
||||||
/// If we can infer one attribute from another on the declaration of a
|
|
||||||
/// function, explicitly materialize the maximal set for readability in the IR.
|
|
||||||
/// Doing this also allows our CGSCC inference to avoid needing to duplicate
|
|
||||||
/// this logic on all calls to declarations (as declarations aren't explicitly
|
|
||||||
/// visited by CGSCC passes in the new pass manager.)
|
|
||||||
static bool inferAttributesFromOthers(Function &F) {
|
|
||||||
// Note: We explicitly check for attributes rather than using cover functions
|
|
||||||
// because some of the cover functions include the logic being implemented.
|
|
||||||
|
|
||||||
bool Changed = false;
|
|
||||||
// readnone + not convergent implies nosync
|
|
||||||
if (!F.hasFnAttribute(Attribute::NoSync) &&
|
|
||||||
F.doesNotAccessMemory() && !F.isConvergent()) {
|
|
||||||
F.setNoSync();
|
|
||||||
Changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// readonly implies nofree
|
|
||||||
if (!F.hasFnAttribute(Attribute::NoFree) && F.onlyReadsMemory()) {
|
|
||||||
F.setDoesNotFreeMemory();
|
|
||||||
Changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// willreturn implies mustprogress
|
|
||||||
if (!F.hasFnAttribute(Attribute::MustProgress) && F.willReturn()) {
|
|
||||||
F.setMustProgress();
|
|
||||||
Changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: There are a bunch of cases of restrictive memory effects we
|
|
||||||
// can infer by inspecting arguments of argmemonly-ish functions.
|
|
||||||
|
|
||||||
return Changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool inferAllPrototypeAttributes(
|
static bool inferAllPrototypeAttributes(
|
||||||
Module &M, function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
|
Module &M, function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
|
|
||||||
for (Function &F : M.functions())
|
for (Function &F : M.functions())
|
||||||
// We only infer things using the prototype and the name; we don't need
|
// We only infer things using the prototype and the name; we don't need
|
||||||
// definitions.
|
// definitions. This ensures libfuncs are annotated and also allows our
|
||||||
|
// CGSCC inference to avoid needing to duplicate the inference from other
|
||||||
|
// attribute logic on all calls to declarations (as declarations aren't
|
||||||
|
// explicitly visited by CGSCC passes in the new pass manager.)
|
||||||
if (F.isDeclaration() && !F.hasOptNone()) {
|
if (F.isDeclaration() && !F.hasOptNone()) {
|
||||||
Changed |= inferLibFuncAttributes(F, GetTLI(F));
|
Changed |= inferLibFuncAttributes(F, GetTLI(F));
|
||||||
Changed |= inferAttributesFromOthers(F);
|
Changed |= inferAttributesFromOthers(F);
|
||||||
|
|
|
@ -3392,3 +3392,33 @@ Value *llvm::invertCondition(Value *Condition) {
|
||||||
Inverted->insertBefore(&*Parent->getFirstInsertionPt());
|
Inverted->insertBefore(&*Parent->getFirstInsertionPt());
|
||||||
return Inverted;
|
return Inverted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool llvm::inferAttributesFromOthers(Function &F) {
|
||||||
|
// Note: We explicitly check for attributes rather than using cover functions
|
||||||
|
// because some of the cover functions include the logic being implemented.
|
||||||
|
|
||||||
|
bool Changed = false;
|
||||||
|
// readnone + not convergent implies nosync
|
||||||
|
if (!F.hasFnAttribute(Attribute::NoSync) &&
|
||||||
|
F.doesNotAccessMemory() && !F.isConvergent()) {
|
||||||
|
F.setNoSync();
|
||||||
|
Changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// readonly implies nofree
|
||||||
|
if (!F.hasFnAttribute(Attribute::NoFree) && F.onlyReadsMemory()) {
|
||||||
|
F.setDoesNotFreeMemory();
|
||||||
|
Changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// willreturn implies mustprogress
|
||||||
|
if (!F.hasFnAttribute(Attribute::MustProgress) && F.willReturn()) {
|
||||||
|
F.setMustProgress();
|
||||||
|
Changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: There are a bunch of cases of restrictive memory effects we
|
||||||
|
// can infer by inspecting arguments of argmemonly-ish functions.
|
||||||
|
|
||||||
|
return Changed;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue