forked from OSchip/llvm-project
[IPSCCP] Move common functions to ValueLatticeUtils (NFC)
This patch moves some common utility functions out of IPSCCP and makes them available globally. The functions determine if interprocedural data-flow analyses can propagate information through function returns, arguments, and global variables. Differential Revision: https://reviews.llvm.org/D37638 llvm-svn: 315719
This commit is contained in:
parent
c419c9f640
commit
2284937bbc
|
@ -0,0 +1,41 @@
|
||||||
|
//===-- ValueLatticeUtils.h - Utils for solving lattices --------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file declares common functions useful for performing data-flow analyses
|
||||||
|
// that propagate values across function boundaries.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_ANALYSIS_VALUELATTICEUTILS_H
|
||||||
|
#define LLVM_ANALYSIS_VALUELATTICEUTILS_H
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
class Function;
|
||||||
|
class GlobalVariable;
|
||||||
|
|
||||||
|
/// Determine if the values of the given function's arguments can be tracked
|
||||||
|
/// interprocedurally. The value of an argument can be tracked if the function
|
||||||
|
/// has local linkage and its address is not taken.
|
||||||
|
bool canTrackArgumentsInterprocedurally(Function *F);
|
||||||
|
|
||||||
|
/// Determine if the values of the given function's returns can be tracked
|
||||||
|
/// interprocedurally. Return values can be tracked if the function has an
|
||||||
|
/// exact definition and it doesn't have the "naked" attribute. Naked functions
|
||||||
|
/// may contain assembly code that returns untrackable values.
|
||||||
|
bool canTrackReturnsInterprocedurally(Function *F);
|
||||||
|
|
||||||
|
/// Determine if the value maintained in the given global variable can be
|
||||||
|
/// tracked interprocedurally. A value can be tracked if the global variable
|
||||||
|
/// has local linkage and is only used by non-volatile loads and stores.
|
||||||
|
bool canTrackGlobalVariableInterprocedurally(GlobalVariable *GV);
|
||||||
|
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
|
#endif // LLVM_ANALYSIS_VALUELATTICEUTILS_H
|
|
@ -81,6 +81,7 @@ add_llvm_library(LLVMAnalysis
|
||||||
TypeMetadataUtils.cpp
|
TypeMetadataUtils.cpp
|
||||||
ScopedNoAliasAA.cpp
|
ScopedNoAliasAA.cpp
|
||||||
ValueLattice.cpp
|
ValueLattice.cpp
|
||||||
|
ValueLatticeUtils.cpp
|
||||||
ValueTracking.cpp
|
ValueTracking.cpp
|
||||||
VectorUtils.cpp
|
VectorUtils.cpp
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
//===-- ValueLatticeUtils.cpp - Utils for solving lattices ------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file implements common functions useful for performing data-flow
|
||||||
|
// analyses that propagate values across function boundaries.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "llvm/Analysis/ValueLatticeUtils.h"
|
||||||
|
#include "llvm/IR/GlobalVariable.h"
|
||||||
|
#include "llvm/IR/Instructions.h"
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
bool llvm::canTrackArgumentsInterprocedurally(Function *F) {
|
||||||
|
return F->hasLocalLinkage() && !F->hasAddressTaken();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool llvm::canTrackReturnsInterprocedurally(Function *F) {
|
||||||
|
return F->hasExactDefinition() && !F->hasFnAttribute(Attribute::Naked);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool llvm::canTrackGlobalVariableInterprocedurally(GlobalVariable *GV) {
|
||||||
|
if (GV->isConstant() || !GV->hasLocalLinkage() ||
|
||||||
|
!GV->hasDefinitiveInitializer())
|
||||||
|
return false;
|
||||||
|
return !any_of(GV->users(), [&](User *U) {
|
||||||
|
if (auto *Store = dyn_cast<StoreInst>(U)) {
|
||||||
|
if (Store->getValueOperand() == GV || Store->isVolatile())
|
||||||
|
return true;
|
||||||
|
} else if (auto *Load = dyn_cast<LoadInst>(U)) {
|
||||||
|
if (Load->isVolatile())
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
|
@ -27,6 +27,7 @@
|
||||||
#include "llvm/Analysis/ConstantFolding.h"
|
#include "llvm/Analysis/ConstantFolding.h"
|
||||||
#include "llvm/Analysis/GlobalsModRef.h"
|
#include "llvm/Analysis/GlobalsModRef.h"
|
||||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||||
|
#include "llvm/Analysis/ValueLatticeUtils.h"
|
||||||
#include "llvm/IR/CallSite.h"
|
#include "llvm/IR/CallSite.h"
|
||||||
#include "llvm/IR/Constants.h"
|
#include "llvm/IR/Constants.h"
|
||||||
#include "llvm/IR/DataLayout.h"
|
#include "llvm/IR/DataLayout.h"
|
||||||
|
@ -263,6 +264,12 @@ public:
|
||||||
TrackingIncomingArguments.insert(F);
|
TrackingIncomingArguments.insert(F);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if the given function is in the solver's set of
|
||||||
|
/// argument-tracked functions.
|
||||||
|
bool isArgumentTrackedFunction(Function *F) {
|
||||||
|
return TrackingIncomingArguments.count(F);
|
||||||
|
}
|
||||||
|
|
||||||
/// Solve - Solve for constants and executable blocks.
|
/// Solve - Solve for constants and executable blocks.
|
||||||
///
|
///
|
||||||
void Solve();
|
void Solve();
|
||||||
|
@ -1699,38 +1706,11 @@ INITIALIZE_PASS_END(SCCPLegacyPass, "sccp",
|
||||||
// createSCCPPass - This is the public interface to this file.
|
// createSCCPPass - This is the public interface to this file.
|
||||||
FunctionPass *llvm::createSCCPPass() { return new SCCPLegacyPass(); }
|
FunctionPass *llvm::createSCCPPass() { return new SCCPLegacyPass(); }
|
||||||
|
|
||||||
static bool AddressIsTaken(const GlobalValue *GV) {
|
|
||||||
// Delete any dead constantexpr klingons.
|
|
||||||
GV->removeDeadConstantUsers();
|
|
||||||
|
|
||||||
for (const Use &U : GV->uses()) {
|
|
||||||
const User *UR = U.getUser();
|
|
||||||
if (const auto *SI = dyn_cast<StoreInst>(UR)) {
|
|
||||||
if (SI->getOperand(0) == GV || SI->isVolatile())
|
|
||||||
return true; // Storing addr of GV.
|
|
||||||
} else if (isa<InvokeInst>(UR) || isa<CallInst>(UR)) {
|
|
||||||
// Make sure we are calling the function, not passing the address.
|
|
||||||
ImmutableCallSite CS(cast<Instruction>(UR));
|
|
||||||
if (!CS.isCallee(&U))
|
|
||||||
return true;
|
|
||||||
} else if (const auto *LI = dyn_cast<LoadInst>(UR)) {
|
|
||||||
if (LI->isVolatile())
|
|
||||||
return true;
|
|
||||||
} else if (isa<BlockAddress>(UR)) {
|
|
||||||
// blockaddress doesn't take the address of the function, it takes addr
|
|
||||||
// of label.
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void findReturnsToZap(Function &F,
|
static void findReturnsToZap(Function &F,
|
||||||
SmallPtrSet<Function *, 32> &AddressTakenFunctions,
|
SmallVector<ReturnInst *, 8> &ReturnsToZap,
|
||||||
SmallVector<ReturnInst *, 8> &ReturnsToZap) {
|
SCCPSolver &Solver) {
|
||||||
// We can only do this if we know that nothing else can call the function.
|
// We can only do this if we know that nothing else can call the function.
|
||||||
if (!F.hasLocalLinkage() || AddressTakenFunctions.count(&F))
|
if (!Solver.isArgumentTrackedFunction(&F))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (BasicBlock &BB : F)
|
for (BasicBlock &BB : F)
|
||||||
|
@ -1743,13 +1723,6 @@ static bool runIPSCCP(Module &M, const DataLayout &DL,
|
||||||
const TargetLibraryInfo *TLI) {
|
const TargetLibraryInfo *TLI) {
|
||||||
SCCPSolver Solver(DL, TLI);
|
SCCPSolver Solver(DL, TLI);
|
||||||
|
|
||||||
// AddressTakenFunctions - This set keeps track of the address-taken functions
|
|
||||||
// that are in the input. As IPSCCP runs through and simplifies code,
|
|
||||||
// functions that were address taken can end up losing their
|
|
||||||
// address-taken-ness. Because of this, we keep track of their addresses from
|
|
||||||
// the first pass so we can use them for the later simplification pass.
|
|
||||||
SmallPtrSet<Function*, 32> AddressTakenFunctions;
|
|
||||||
|
|
||||||
// Loop over all functions, marking arguments to those with their addresses
|
// Loop over all functions, marking arguments to those with their addresses
|
||||||
// taken or that are external as overdefined.
|
// taken or that are external as overdefined.
|
||||||
//
|
//
|
||||||
|
@ -1757,25 +1730,16 @@ static bool runIPSCCP(Module &M, const DataLayout &DL,
|
||||||
if (F.isDeclaration())
|
if (F.isDeclaration())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If this is an exact definition of this function, then we can propagate
|
// Determine if we can track the function's return values. If so, add the
|
||||||
// information about its result into callsites of it.
|
// function to the solver's set of return-tracked functions.
|
||||||
// Don't touch naked functions. They may contain asm returning a
|
if (canTrackReturnsInterprocedurally(&F))
|
||||||
// value we don't see, so we may end up interprocedurally propagating
|
|
||||||
// the return value incorrectly.
|
|
||||||
if (F.hasExactDefinition() && !F.hasFnAttribute(Attribute::Naked))
|
|
||||||
Solver.AddTrackedFunction(&F);
|
Solver.AddTrackedFunction(&F);
|
||||||
|
|
||||||
// If this function only has direct calls that we can see, we can track its
|
// Determine if we can track the function's arguments. If so, add the
|
||||||
// arguments and return value aggressively, and can assume it is not called
|
// function to the solver's set of argument-tracked functions.
|
||||||
// unless we see evidence to the contrary.
|
if (canTrackArgumentsInterprocedurally(&F)) {
|
||||||
if (F.hasLocalLinkage()) {
|
Solver.AddArgumentTrackedFunction(&F);
|
||||||
if (F.hasAddressTaken()) {
|
continue;
|
||||||
AddressTakenFunctions.insert(&F);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Solver.AddArgumentTrackedFunction(&F);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assume the function is called.
|
// Assume the function is called.
|
||||||
|
@ -1786,13 +1750,14 @@ static bool runIPSCCP(Module &M, const DataLayout &DL,
|
||||||
Solver.markOverdefined(&AI);
|
Solver.markOverdefined(&AI);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop over global variables. We inform the solver about any internal global
|
// Determine if we can track any of the module's global variables. If so, add
|
||||||
// variables that do not have their 'addresses taken'. If they don't have
|
// the global variables we can track to the solver's set of tracked global
|
||||||
// their addresses taken, we can propagate constants through them.
|
// variables.
|
||||||
for (GlobalVariable &G : M.globals())
|
for (GlobalVariable &G : M.globals()) {
|
||||||
if (!G.isConstant() && G.hasLocalLinkage() &&
|
G.removeDeadConstantUsers();
|
||||||
G.hasDefinitiveInitializer() && !AddressIsTaken(&G))
|
if (canTrackGlobalVariableInterprocedurally(&G))
|
||||||
Solver.TrackValueOfGlobalVariable(&G);
|
Solver.TrackValueOfGlobalVariable(&G);
|
||||||
|
}
|
||||||
|
|
||||||
// Solve for constants.
|
// Solve for constants.
|
||||||
bool ResolvedUndefs = true;
|
bool ResolvedUndefs = true;
|
||||||
|
@ -1897,7 +1862,7 @@ static bool runIPSCCP(Module &M, const DataLayout &DL,
|
||||||
Function *F = I.first;
|
Function *F = I.first;
|
||||||
if (I.second.isOverdefined() || F->getReturnType()->isVoidTy())
|
if (I.second.isOverdefined() || F->getReturnType()->isVoidTy())
|
||||||
continue;
|
continue;
|
||||||
findReturnsToZap(*F, AddressTakenFunctions, ReturnsToZap);
|
findReturnsToZap(*F, ReturnsToZap, Solver);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &F : Solver.getMRVFunctionsTracked()) {
|
for (const auto &F : Solver.getMRVFunctionsTracked()) {
|
||||||
|
@ -1905,7 +1870,7 @@ static bool runIPSCCP(Module &M, const DataLayout &DL,
|
||||||
"The return type should be a struct");
|
"The return type should be a struct");
|
||||||
StructType *STy = cast<StructType>(F->getReturnType());
|
StructType *STy = cast<StructType>(F->getReturnType());
|
||||||
if (Solver.isStructLatticeConstant(F, STy))
|
if (Solver.isStructLatticeConstant(F, STy))
|
||||||
findReturnsToZap(*F, AddressTakenFunctions, ReturnsToZap);
|
findReturnsToZap(*F, ReturnsToZap, Solver);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zap all returns which we've identified as zap to change.
|
// Zap all returns which we've identified as zap to change.
|
||||||
|
|
Loading…
Reference in New Issue