[Transforms] Fix some Clang-tidy modernize and Include What You Use warnings; other minor fixes (NFC).

llvm-svn: 316241
This commit is contained in:
Eugene Zelenko 2017-10-20 21:47:29 +00:00
parent 12fd3da9d1
commit 99241d75c1
6 changed files with 304 additions and 149 deletions

View File

@ -1,4 +1,4 @@
//===----- NewGVN.h - Global Value Numbering Pass ---------------*- C++ -*-===//
//===- NewGVN.h - Global Value Numbering Pass -------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@ -6,9 +6,10 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \file
/// This file provides the interface for LLVM's Global Value Numbering pass.
///
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TRANSFORMS_SCALAR_NEWGVN_H
@ -17,12 +18,16 @@
#include "llvm/IR/PassManager.h"
namespace llvm {
class Function;
class NewGVNPass : public PassInfoMixin<NewGVNPass> {
public:
/// \brief Run the pass over the function.
PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM);
};
}
} // end namespace llvm
#endif // LLVM_TRANSFORMS_SCALAR_NEWGVN_H

View File

@ -6,7 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
//
// \file
// This file implements sparse conditional constant propagation and merging:
//
// Specifically, this:
@ -15,22 +16,23 @@
// * Proves values to be constant, and replaces them with constants
// * Proves conditional branches to be unconditional
//
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_TRANSFORMS_SCALAR_SCCP_H
#define LLVM_TRANSFORMS_SCALAR_SCCP_H
#include "llvm/IR/Function.h"
#include "llvm/IR/PassManager.h"
namespace llvm {
class Function;
/// This pass performs function-level constant propagation and merging.
class SCCPPass : public PassInfoMixin<SCCPPass> {
public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
}
} // end namespace llvm
#endif // LLVM_TRANSFORMS_SCALAR_SCCP_H

View File

@ -1,4 +1,4 @@
//===---- NewGVN.cpp - Global Value Numbering Pass --------------*- C++ -*-===//
//===- NewGVN.cpp - Global Value Numbering Pass ---------------------------===//
//
// The LLVM Compiler Infrastructure
//
@ -6,6 +6,7 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \file
/// This file implements the new LLVM's Global Value Numbering pass.
/// GVN partitions values computed by a function into congruence classes.
@ -48,39 +49,81 @@
/// published algorithms are O(Instructions). Instead, we use a technique that
/// is O(number of operations with the same value number), enabling us to skip
/// trying to eliminate things that have unique value numbers.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Scalar/NewGVN.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SparseBitVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/CFG.h"
#include "llvm/Analysis/CFGPrinter.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Pass.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/ArrayRecycler.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DebugCounter.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/GVNExpression.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/PredicateInfo.h"
#include "llvm/Transforms/Utils/VNCoercion.h"
#include <numeric>
#include <unordered_map>
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <iterator>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
using namespace llvm;
using namespace PatternMatch;
using namespace llvm::GVNExpression;
using namespace llvm::VNCoercion;
#define DEBUG_TYPE "newgvn"
STATISTIC(NumGVNInstrDeleted, "Number of instructions deleted");
@ -118,6 +161,7 @@ static cl::opt<bool> EnablePhiOfOps("enable-phi-of-ops", cl::init(true),
// Anchor methods.
namespace llvm {
namespace GVNExpression {
Expression::~Expression() = default;
BasicExpression::~BasicExpression() = default;
CallExpression::~CallExpression() = default;
@ -125,10 +169,12 @@ LoadExpression::~LoadExpression() = default;
StoreExpression::~StoreExpression() = default;
AggregateValueExpression::~AggregateValueExpression() = default;
PHIExpression::~PHIExpression() = default;
}
}
} // end namespace GVNExpression
} // end namespace llvm
namespace {
// Tarjan's SCC finding algorithm with Nuutila's improvements
// SCCIterator is actually fairly complex for the simple thing we want.
// It also wants to hand us SCC's that are unrelated to the phi node we ask
@ -138,7 +184,6 @@ namespace {
// instructions,
// not generic values (arguments, etc).
struct TarjanSCC {
TarjanSCC() : Components(1) {}
void Start(const Instruction *Start) {
@ -193,15 +238,19 @@ private:
Stack.push_back(I);
}
}
unsigned int DFSNum = 1;
SmallPtrSet<const Value *, 8> InComponent;
DenseMap<const Value *, unsigned int> Root;
SmallVector<const Value *, 8> Stack;
// Store the components as vector of ptr sets, because we need the topo order
// of SCC's, but not individual member order
SmallVector<SmallPtrSet<const Value *, 8>, 8> Components;
DenseMap<const Value *, unsigned> ValueToComponent;
};
// Congruence classes represent the set of expressions/instructions
// that are all the same *during some scope in the function*.
// That is, because of the way we perform equality propagation, and
@ -250,7 +299,9 @@ public:
explicit CongruenceClass(unsigned ID) : ID(ID) {}
CongruenceClass(unsigned ID, Value *Leader, const Expression *E)
: ID(ID), RepLeader(Leader), DefiningExpr(E) {}
unsigned getID() const { return ID; }
// True if this class has no members left. This is mainly used for assertion
// purposes, and for skipping empty classes.
bool isDead() const {
@ -258,6 +309,7 @@ public:
// perspective, it's really dead.
return empty() && memory_empty();
}
// Leader functions
Value *getLeader() const { return RepLeader; }
void setLeader(Value *Leader) { RepLeader = Leader; }
@ -265,7 +317,6 @@ public:
return NextLeader;
}
void resetNextLeader() { NextLeader = {nullptr, ~0}; }
void addPossibleNextLeader(std::pair<Value *, unsigned int> LeaderPair) {
if (LeaderPair.second < NextLeader.second)
NextLeader = LeaderPair;
@ -300,6 +351,7 @@ public:
iterator_range<MemoryMemberSet::const_iterator> memory() const {
return make_range(memory_begin(), memory_end());
}
void memory_insert(const MemoryMemberType *M) { MemoryMembers.insert(M); }
void memory_erase(const MemoryMemberType *M) { MemoryMembers.erase(M); }
@ -339,35 +391,48 @@ public:
private:
unsigned ID;
// Representative leader.
Value *RepLeader = nullptr;
// The most dominating leader after our current leader, because the member set
// is not sorted and is expensive to keep sorted all the time.
std::pair<Value *, unsigned int> NextLeader = {nullptr, ~0U};
// If this is represented by a store, the value of the store.
Value *RepStoredValue = nullptr;
// If this class contains MemoryDefs or MemoryPhis, this is the leading memory
// access.
const MemoryAccess *RepMemoryAccess = nullptr;
// Defining Expression.
const Expression *DefiningExpr = nullptr;
// Actual members of this class.
MemberSet Members;
// This is the set of MemoryPhis that exist in the class. MemoryDefs and
// MemoryUses have real instructions representing them, so we only need to
// track MemoryPhis here.
MemoryMemberSet MemoryMembers;
// Number of stores in this congruence class.
// This is used so we can detect store equivalence changes properly.
int StoreCount = 0;
};
} // namespace
} // end anonymous namespace
namespace llvm {
struct ExactEqualsExpression {
const Expression &E;
explicit ExactEqualsExpression(const Expression &E) : E(E) {}
hash_code getComputedHash() const { return E.getComputedHash(); }
bool operator==(const Expression &Other) const {
return E.exactlyEquals(Other);
}
@ -379,17 +444,21 @@ template <> struct DenseMapInfo<const Expression *> {
Val <<= PointerLikeTypeTraits<const Expression *>::NumLowBitsAvailable;
return reinterpret_cast<const Expression *>(Val);
}
static const Expression *getTombstoneKey() {
auto Val = static_cast<uintptr_t>(~1U);
Val <<= PointerLikeTypeTraits<const Expression *>::NumLowBitsAvailable;
return reinterpret_cast<const Expression *>(Val);
}
static unsigned getHashValue(const Expression *E) {
return E->getComputedHash();
}
static unsigned getHashValue(const ExactEqualsExpression &E) {
return E.getComputedHash();
}
static bool isEqual(const ExactEqualsExpression &LHS, const Expression *RHS) {
if (RHS == getTombstoneKey() || RHS == getEmptyKey())
return false;
@ -411,9 +480,11 @@ template <> struct DenseMapInfo<const Expression *> {
return *LHS == *RHS;
}
};
} // end namespace llvm
namespace {
class NewGVN {
Function &F;
DominatorTree *DT;
@ -450,6 +521,7 @@ class NewGVN {
// Value Mappings.
DenseMap<Value *, CongruenceClass *> ValueToClass;
DenseMap<Value *, const Expression *> ValueToExpression;
// Value PHI handling, used to make equivalence between phi(op, op) and
// op(phi, phi).
// These mappings just store various data that would normally be part of the
@ -457,11 +529,14 @@ class NewGVN {
SmallPtrSet<const Instruction *, 8> PHINodeUses;
DenseMap<const Value *, bool> OpSafeForPHIOfOps;
// Map a temporary instruction we created to a parent block.
DenseMap<const Value *, BasicBlock *> TempToBlock;
// Map between the already in-program instructions and the temporary phis we
// created that they are known equivalent to.
DenseMap<const Value *, PHINode *> RealToTemp;
// In order to know when we should re-process instructions that have
// phi-of-ops, we track the set of expressions that they needed as
// leaders. When we discover new leaders for those expressions, we process the
@ -473,13 +548,14 @@ class NewGVN {
mutable DenseMap<const Value *, SmallPtrSet<Value *, 2>> AdditionalUsers;
DenseMap<const Expression *, SmallPtrSet<Instruction *, 2>>
ExpressionToPhiOfOps;
// Map from temporary operation to MemoryAccess.
DenseMap<const Instruction *, MemoryUseOrDef *> TempToMemory;
// Set of all temporary instructions we created.
// Note: This will include instructions that were just created during value
// numbering. The way to test if something is using them is to check
// RealToTemp.
DenseSet<Instruction *> AllTempInstructions;
// This is the set of instructions to revisit on a reachability change. At
@ -497,6 +573,7 @@ class NewGVN {
// propagate the information to the places we used the comparison.
mutable DenseMap<const Value *, SmallPtrSet<Instruction *, 2>>
PredicateToUsers;
// the same reasoning as PredicateToUsers. When we skip MemoryAccesses for
// stores, we no longer can rely solely on the def-use chains of MemorySSA.
mutable DenseMap<const MemoryAccess *, SmallPtrSet<MemoryAccess *, 2>>
@ -524,6 +601,7 @@ class NewGVN {
enum InstCycleState { ICS_Unknown, ICS_CycleFree, ICS_Cycle };
mutable DenseMap<const Instruction *, InstCycleState> InstCycleState;
// Expression to class mapping.
using ExpressionClassMap = DenseMap<const Expression *, CongruenceClass *>;
ExpressionClassMap ExpressionToClass;
@ -580,6 +658,7 @@ public:
: F(F), DT(DT), TLI(TLI), AA(AA), MSSA(MSSA), DL(DL),
PredInfo(make_unique<PredicateInfo>(F, *DT, *AC)), SQ(DL, TLI, DT, AC) {
}
bool runGVN();
private:
@ -587,9 +666,11 @@ private:
const Expression *createExpression(Instruction *) const;
const Expression *createBinaryExpression(unsigned, Type *, Value *, Value *,
Instruction *) const;
// Our canonical form for phi arguments is a pair of incoming value, incoming
// basic block.
typedef std::pair<Value *, BasicBlock *> ValPair;
using ValPair = std::pair<Value *, BasicBlock *>;
PHIExpression *createPHIExpression(ArrayRef<ValPair>, const Instruction *,
BasicBlock *, bool &HasBackEdge,
bool &OriginalOpsConstant) const;
@ -620,6 +701,7 @@ private:
CC->setMemoryLeader(MA);
return CC;
}
CongruenceClass *ensureLeaderOfMemoryClass(MemoryAccess *MA) {
auto *CC = getMemoryClass(MA);
if (CC->getMemoryLeader() != MA)
@ -633,6 +715,7 @@ private:
ValueToClass[Member] = CClass;
return CClass;
}
void initializeCongruenceClasses(Function &F);
const Expression *makePossiblePHIOfOps(Instruction *,
SmallPtrSetImpl<Value *> &);
@ -713,7 +796,7 @@ private:
const BasicBlock *) const;
// New instruction creation.
void handleNewInstruction(Instruction *){};
void handleNewInstruction(Instruction *) {}
// Various instruction touch utilities
template <typename Map, typename KeyType, typename Func>
@ -749,6 +832,7 @@ private:
MemoryAccess *getDefiningAccess(const MemoryAccess *) const;
MemoryPhi *getMemoryAccess(const BasicBlock *) const;
template <class T, class Range> T *getMinDFSOfRange(const Range &) const;
unsigned InstrToDFSNum(const Value *V) const {
assert(isa<Instruction>(V) && "This should not be used for MemoryAccesses");
return InstrDFS.lookup(V);
@ -757,7 +841,9 @@ private:
unsigned InstrToDFSNum(const MemoryAccess *MA) const {
return MemoryToDFSNum(MA);
}
Value *InstrFromDFSNum(unsigned DFSNum) { return DFSToInstr[DFSNum]; }
// Given a MemoryAccess, return the relevant instruction DFS number. Note:
// This deliberately takes a value so it can be used with Use's, which will
// auto-convert to Value's but not to MemoryAccess's.
@ -768,12 +854,15 @@ private:
? InstrToDFSNum(cast<MemoryUseOrDef>(MA)->getMemoryInst())
: InstrDFS.lookup(MA);
}
bool isCycleFree(const Instruction *) const;
bool isBackedge(BasicBlock *From, BasicBlock *To) const;
// Debug counter info. When verifying, we have to reset the value numbering
// debug counter to the same state it started in to get the same results.
std::pair<int, int> StartingVNCounter;
};
} // end anonymous namespace
template <typename T>
@ -1338,7 +1427,6 @@ NewGVN::performSymbolicLoadCoercion(Type *LoadType, Value *LoadPtr,
getConstantStoreValueForLoad(C, Offset, LoadType, DL));
}
}
} else if (auto *DepLI = dyn_cast<LoadInst>(DepInst)) {
// Can't forward from non-atomic to atomic without violating memory model.
if (LI->isAtomic() > DepLI->isAtomic())
@ -1354,7 +1442,6 @@ NewGVN::performSymbolicLoadCoercion(Type *LoadType, Value *LoadPtr,
return createConstantExpression(PossibleConstant);
}
}
} else if (auto *DepMI = dyn_cast<MemIntrinsic>(DepInst)) {
int Offset = analyzeLoadFromClobberingMemInst(LoadType, LoadPtr, DepMI, DL);
if (Offset >= 0) {
@ -1554,7 +1641,6 @@ const Expression *NewGVN::performSymbolicCallEvaluation(Instruction *I) const {
// Retrieve the memory class for a given MemoryAccess.
CongruenceClass *NewGVN::getMemoryClass(const MemoryAccess *MA) const {
auto *Result = MemoryAccessToClass.lookup(MA);
assert(Result && "Should have found memory class");
return Result;
@ -1759,6 +1845,7 @@ NewGVN::performSymbolicAggrValueEvaluation(Instruction *I) const {
return createAggregateValueExpression(I);
}
const Expression *NewGVN::performSymbolicCmpEvaluation(Instruction *I) const {
assert(isa<CmpInst>(I) && "Expected a cmp instruction.");
@ -1856,7 +1943,6 @@ const Expression *NewGVN::performSymbolicCmpEvaluation(Instruction *I) const {
return createConstantExpression(
ConstantInt::getFalse(CI->getType()));
}
} else {
// Just handle the ne and eq cases, where if we have the same
// operands, we may know something.
@ -1917,13 +2003,13 @@ NewGVN::performSymbolicEvaluation(Value *V,
case Instruction::Load:
E = performSymbolicLoadEvaluation(I);
break;
case Instruction::BitCast: {
case Instruction::BitCast:
E = createExpression(I);
} break;
break;
case Instruction::ICmp:
case Instruction::FCmp: {
case Instruction::FCmp:
E = performSymbolicCmpEvaluation(I);
} break;
break;
case Instruction::Add:
case Instruction::FAdd:
case Instruction::Sub:
@ -2914,6 +3000,7 @@ void NewGVN::updateProcessedCount(const Value *V) {
}
#endif
}
// Evaluate MemoryPhi nodes symbolically, just like PHI nodes
void NewGVN::valueNumberMemoryPhi(MemoryPhi *MP) {
// If all the arguments are the same, the MemoryPhi has the same value as the
@ -2991,7 +3078,6 @@ void NewGVN::valueNumberInstruction(Instruction *I) {
removePhiOfOps(I, Op);
}
}
} else {
// Mark the instruction as unused so we don't value number it again.
InstrDFS[I] = 0;
@ -3400,11 +3486,13 @@ struct NewGVN::ValueDFS {
int DFSIn = 0;
int DFSOut = 0;
int LocalNum = 0;
// Only one of Def and U will be set.
// The bool in the Def tells us whether the Def is the stored value of a
// store.
PointerIntPair<Value *, 1, bool> Def;
Use *U = nullptr;
bool operator<(const ValueDFS &Other) const {
// It's not enough that any given field be less than - we have sets
// of fields that need to be evaluated together to give a proper ordering.
@ -3639,7 +3727,6 @@ void NewGVN::markInstructionForDeletion(Instruction *I) {
}
void NewGVN::replaceInstruction(Instruction *I, Value *V) {
DEBUG(dbgs() << "Replacing " << *I << " with " << *V << "\n");
patchAndReplaceAllUsesWith(I, V);
// We save the actual erasing to avoid invalidating memory
@ -3660,7 +3747,9 @@ public:
ValueStack.emplace_back(V);
DFSStack.emplace_back(DFSIn, DFSOut);
}
bool empty() const { return DFSStack.empty(); }
bool isInScope(int DFSIn, int DFSOut) const {
if (empty())
return false;
@ -3684,7 +3773,8 @@ private:
SmallVector<Value *, 8> ValueStack;
SmallVector<std::pair<int, int>, 8> DFSStack;
};
}
} // end anonymous namespace
// Given an expression, get the congruence class for it.
CongruenceClass *NewGVN::getClassForExpression(const Expression *E) const {
@ -4087,12 +4177,16 @@ bool NewGVN::shouldSwapOperands(const Value *A, const Value *B) const {
}
namespace {
class NewGVNLegacyPass : public FunctionPass {
public:
static char ID; // Pass identification, replacement for typeid.
// Pass identification, replacement for typeid.
static char ID;
NewGVNLegacyPass() : FunctionPass(ID) {
initializeNewGVNLegacyPassPass(*PassRegistry::getPassRegistry());
}
bool runOnFunction(Function &F) override;
private:
@ -4106,7 +4200,8 @@ private:
AU.addPreserved<GlobalsAAWrapperPass>();
}
};
} // namespace
} // end anonymous namespace
bool NewGVNLegacyPass::runOnFunction(Function &F) {
if (skipFunction(F))
@ -4120,6 +4215,8 @@ bool NewGVNLegacyPass::runOnFunction(Function &F) {
.runGVN();
}
char NewGVNLegacyPass::ID = 0;
INITIALIZE_PASS_BEGIN(NewGVNLegacyPass, "newgvn", "Global Value Numbering",
false, false)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
@ -4131,8 +4228,6 @@ INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
INITIALIZE_PASS_END(NewGVNLegacyPass, "newgvn", "Global Value Numbering", false,
false)
char NewGVNLegacyPass::ID = 0;
// createGVNPass - The public interface to this file.
FunctionPass *llvm::createNewGVNPass() { return new NewGVNLegacyPass(); }

View File

@ -18,9 +18,12 @@
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/SCCP.h"
#include "llvm/Transforms/Scalar/SCCP.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
@ -28,21 +31,35 @@
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueLatticeUtils.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/SCCP.h"
#include "llvm/Transforms/Utils/Local.h"
#include <algorithm>
#include <cassert>
#include <utility>
#include <vector>
using namespace llvm;
#define DEBUG_TYPE "sccp"
@ -55,6 +72,7 @@ STATISTIC(IPNumArgsElimed ,"Number of arguments constant propagated by IPSCCP");
STATISTIC(IPNumGlobalConst, "Number of globals found to be constant by IPSCCP");
namespace {
/// LatticeVal class - This class represents the different lattice values that
/// an LLVM value may occupy. It is a simple class with value semantics.
///
@ -89,9 +107,11 @@ public:
LatticeVal() : Val(nullptr, unknown) {}
bool isUnknown() const { return getLatticeValue() == unknown; }
bool isConstant() const {
return getLatticeValue() == constant || getLatticeValue() == forcedconstant;
}
bool isOverdefined() const { return getLatticeValue() == overdefined; }
Constant *getConstant() const {
@ -155,10 +175,6 @@ public:
Val.setPointer(V);
}
};
} // end anonymous namespace.
namespace {
//===----------------------------------------------------------------------===//
//
@ -168,37 +184,36 @@ namespace {
class SCCPSolver : public InstVisitor<SCCPSolver> {
const DataLayout &DL;
const TargetLibraryInfo *TLI;
SmallPtrSet<BasicBlock*, 8> BBExecutable; // The BBs that are executable.
DenseMap<Value*, LatticeVal> ValueState; // The state each value is in.
SmallPtrSet<BasicBlock *, 8> BBExecutable; // The BBs that are executable.
DenseMap<Value *, LatticeVal> ValueState; // The state each value is in.
/// StructValueState - This maintains ValueState for values that have
/// StructType, for example for formal arguments, calls, insertelement, etc.
///
DenseMap<std::pair<Value*, unsigned>, LatticeVal> StructValueState;
DenseMap<std::pair<Value *, unsigned>, LatticeVal> StructValueState;
/// GlobalValue - If we are tracking any values for the contents of a global
/// variable, we keep a mapping from the constant accessor to the element of
/// the global, to the currently known value. If the value becomes
/// overdefined, it's entry is simply removed from this map.
DenseMap<GlobalVariable*, LatticeVal> TrackedGlobals;
DenseMap<GlobalVariable *, LatticeVal> TrackedGlobals;
/// TrackedRetVals - If we are tracking arguments into and the return
/// value out of a function, it will have an entry in this map, indicating
/// what the known return value for the function is.
DenseMap<Function*, LatticeVal> TrackedRetVals;
DenseMap<Function *, LatticeVal> TrackedRetVals;
/// TrackedMultipleRetVals - Same as TrackedRetVals, but used for functions
/// that return multiple values.
DenseMap<std::pair<Function*, unsigned>, LatticeVal> TrackedMultipleRetVals;
DenseMap<std::pair<Function *, unsigned>, LatticeVal> TrackedMultipleRetVals;
/// MRVFunctionsTracked - Each function in TrackedMultipleRetVals is
/// represented here for efficient lookup.
SmallPtrSet<Function*, 16> MRVFunctionsTracked;
SmallPtrSet<Function *, 16> MRVFunctionsTracked;
/// TrackingIncomingArguments - This is the set of functions for whose
/// arguments we make optimistic assumptions about and try to prove as
/// constants.
SmallPtrSet<Function*, 16> TrackingIncomingArguments;
SmallPtrSet<Function *, 16> TrackingIncomingArguments;
/// The reason for two worklists is that overdefined is the lowest state
/// on the lattice, and moving things to overdefined as fast as possible
@ -207,16 +222,17 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {
/// By having a separate worklist, we accomplish this because everything
/// possibly overdefined will become overdefined at the soonest possible
/// point.
SmallVector<Value*, 64> OverdefinedInstWorkList;
SmallVector<Value*, 64> InstWorkList;
SmallVector<Value *, 64> OverdefinedInstWorkList;
SmallVector<Value *, 64> InstWorkList;
SmallVector<BasicBlock*, 64> BBWorkList; // The BasicBlock work list
// The BasicBlock work list
SmallVector<BasicBlock *, 64> BBWorkList;
/// KnownFeasibleEdges - Entries in this set are edges which have already had
/// PHI nodes retriggered.
typedef std::pair<BasicBlock*, BasicBlock*> Edge;
using Edge = std::pair<BasicBlock *, BasicBlock *>;
DenseSet<Edge> KnownFeasibleEdges;
public:
SCCPSolver(const DataLayout &DL, const TargetLibraryInfo *tli)
: DL(DL), TLI(tli) {}
@ -271,7 +287,6 @@ public:
}
/// Solve - Solve for constants and executable blocks.
///
void Solve();
/// ResolvedUndefsIn - While solving the dataflow for a function, we assume
@ -304,7 +319,6 @@ public:
}
/// getTrackedRetVals - Get the inferred return value map.
///
const DenseMap<Function*, LatticeVal> &getTrackedRetVals() {
return TrackedRetVals;
}
@ -356,7 +370,6 @@ private:
// markConstant - Make a value be marked as "constant". If the value
// is not already a constant, add it to the instruction work list so that
// the users of the instruction are updated later.
//
void markConstant(LatticeVal &IV, Value *V, Constant *C) {
if (!IV.markConstant(C)) return;
DEBUG(dbgs() << "markConstant: " << *C << ": " << *V << '\n');
@ -376,7 +389,6 @@ private:
pushToWorkList(IV, V);
}
// markOverdefined - Make a value be marked as "overdefined". If the
// value is not already overdefined, add it to the overdefined instruction
// work list so that the users of the instruction are updated later.
@ -409,7 +421,6 @@ private:
mergeInValue(ValueState[V], V, MergeWithV);
}
/// getValueState - Return the LatticeVal object that corresponds to the
/// value. This function handles the case when the value hasn't been seen yet
/// by properly seeding constants etc.
@ -464,7 +475,6 @@ private:
return LV;
}
/// markEdgeExecutable - Mark a basic block as executable, adding it to the BB
/// work list if it is not already executable.
void markEdgeExecutable(BasicBlock *Source, BasicBlock *Dest) {
@ -487,18 +497,15 @@ private:
// getFeasibleSuccessors - Return a vector of booleans to indicate which
// successors are reachable from a given terminator instruction.
//
void getFeasibleSuccessors(TerminatorInst &TI, SmallVectorImpl<bool> &Succs);
// isEdgeFeasible - Return true if the control flow edge from the 'From' basic
// block to the 'To' basic block is currently feasible.
//
bool isEdgeFeasible(BasicBlock *From, BasicBlock *To);
// OperandChangedState - This method is invoked on all of the users of an
// instruction that was just changed state somehow. Based on this
// information, we need to update the specified user of this instruction.
//
void OperandChangedState(Instruction *I) {
if (BBExecutable.count(I->getParent())) // Inst is executable?
visit(*I);
@ -513,6 +520,7 @@ private:
void visitPHINode(PHINode &I);
// Terminators
void visitReturnInst(ReturnInst &I);
void visitTerminatorInst(TerminatorInst &TI);
@ -522,26 +530,32 @@ private:
void visitCmpInst(CmpInst &I);
void visitExtractValueInst(ExtractValueInst &EVI);
void visitInsertValueInst(InsertValueInst &IVI);
void visitCatchSwitchInst(CatchSwitchInst &CPI) {
markOverdefined(&CPI);
visitTerminatorInst(CPI);
}
// Instructions that cannot be folded away.
void visitStoreInst (StoreInst &I);
void visitLoadInst (LoadInst &I);
void visitGetElementPtrInst(GetElementPtrInst &I);
void visitCallInst (CallInst &I) {
visitCallSite(&I);
}
void visitInvokeInst (InvokeInst &II) {
visitCallSite(&II);
visitTerminatorInst(II);
}
void visitCallSite (CallSite CS);
void visitResumeInst (TerminatorInst &I) { /*returns void*/ }
void visitUnreachableInst(TerminatorInst &I) { /*returns void*/ }
void visitFenceInst (FenceInst &I) { /*returns void*/ }
void visitInstruction(Instruction &I) {
// All the instructions we don't do any special handling for just
// go to overdefined.
@ -552,10 +566,8 @@ private:
} // end anonymous namespace
// getFeasibleSuccessors - Return a vector of booleans to indicate which
// successors are reachable from a given terminator instruction.
//
void SCCPSolver::getFeasibleSuccessors(TerminatorInst &TI,
SmallVectorImpl<bool> &Succs) {
Succs.resize(TI.getNumSuccessors());
@ -638,10 +650,8 @@ void SCCPSolver::getFeasibleSuccessors(TerminatorInst &TI,
llvm_unreachable("SCCP: Don't know how to handle this terminator!");
}
// isEdgeFeasible - Return true if the control flow edge from the 'From' basic
// block to the 'To' basic block is currently feasible.
//
bool SCCPSolver::isEdgeFeasible(BasicBlock *From, BasicBlock *To) {
assert(BBExecutable.count(To) && "Dest should always be alive!");
@ -717,7 +727,6 @@ bool SCCPSolver::isEdgeFeasible(BasicBlock *From, BasicBlock *To) {
// destination executable
// 7. If a conditional branch has a value that is overdefined, make all
// successors executable.
//
void SCCPSolver::visitPHINode(PHINode &PN) {
// If this PN returns a struct, just mark the result overdefined.
// TODO: We could do a lot better than this if code actually uses this.
@ -737,7 +746,6 @@ void SCCPSolver::visitPHINode(PHINode &PN) {
// constant, and they agree with each other, the PHI becomes the identical
// constant. If they are constant and don't agree, the PHI is overdefined.
// If there are no executable operands, the PHI remains unknown.
//
Constant *OperandVal = nullptr;
for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) {
LatticeVal IV = getValueState(PN.getIncomingValue(i));
@ -768,7 +776,6 @@ void SCCPSolver::visitPHINode(PHINode &PN) {
// arguments that agree with each other(and OperandVal is the constant) or
// OperandVal is null because there are no defined incoming arguments. If
// this is the case, the PHI remains unknown.
//
if (OperandVal)
markConstant(&PN, OperandVal); // Acquire operand value
}
@ -796,7 +803,6 @@ void SCCPSolver::visitReturnInst(ReturnInst &I) {
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
mergeInValue(TrackedMultipleRetVals[std::make_pair(F, i)], F,
getStructValueState(ResultOp, i));
}
}
@ -827,7 +833,6 @@ void SCCPSolver::visitCastInst(CastInst &I) {
}
}
void SCCPSolver::visitExtractValueInst(ExtractValueInst &EVI) {
// If this returns a struct, mark all elements over defined, we don't track
// structs in structs.
@ -976,7 +981,6 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) {
}
}
markOverdefined(&I);
}
@ -1005,7 +1009,6 @@ void SCCPSolver::visitCmpInst(CmpInst &I) {
// Handle getelementptr instructions. If all operands are constants then we
// can turn this into a getelementptr ConstantExpr.
//
void SCCPSolver::visitGetElementPtrInst(GetElementPtrInst &I) {
if (ValueState[&I].isOverdefined()) return;
@ -1051,7 +1054,6 @@ void SCCPSolver::visitStoreInst(StoreInst &SI) {
TrackedGlobals.erase(I); // No need to keep tracking this!
}
// Handle load instructions. If the operand is a constant pointer to a constant
// global, we can replace the load with the loaded constant value!
void SCCPSolver::visitLoadInst(LoadInst &I) {
@ -1115,7 +1117,6 @@ CallOverdefined:
// a declaration, maybe we can constant fold it.
if (F && F->isDeclaration() && !I->getType()->isStructTy() &&
canConstantFoldCallTo(CS, F)) {
SmallVector<Constant*, 8> Operands;
for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
AI != E; ++AI) {
@ -1367,7 +1368,6 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
// undef & X -> 0. X could be zero.
markForcedConstant(&I, Constant::getNullValue(ITy));
return true;
case Instruction::Or:
// Both operands undef -> undef
if (Op0LV.isUnknown() && Op1LV.isUnknown())
@ -1375,7 +1375,6 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
// undef | X -> -1. X could be -1.
markForcedConstant(&I, Constant::getAllOnesValue(ITy));
return true;
case Instruction::Xor:
// undef ^ undef -> 0; strictly speaking, this is not strictly
// necessary, but we try to be nice to people who expect this
@ -1386,7 +1385,6 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
}
// undef ^ X -> undef
break;
case Instruction::SDiv:
case Instruction::UDiv:
case Instruction::SRem:
@ -1404,7 +1402,6 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
// undef % X -> 0. X could be 1.
markForcedConstant(&I, Constant::getNullValue(ITy));
return true;
case Instruction::AShr:
// X >>a undef -> undef.
if (Op1LV.isUnknown()) break;
@ -1471,7 +1468,7 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
markOverdefined(&I);
return true;
case Instruction::Call:
case Instruction::Invoke: {
case Instruction::Invoke:
// There are two reasons a call can have an undef result
// 1. It could be tracked.
// 2. It could be constant-foldable.
@ -1485,7 +1482,6 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
// we do not know what return values are valid.
markOverdefined(&I);
return true;
}
default:
// If we don't know what should happen here, conservatively mark it
// overdefined.
@ -1568,7 +1564,8 @@ static bool tryToReplaceWithConstant(SCCPSolver &Solver, Value *V) {
Constant *Const = nullptr;
if (V->getType()->isStructTy()) {
std::vector<LatticeVal> IVs = Solver.getStructLatticeValueFor(V);
if (any_of(IVs, [](const LatticeVal &LV) { return LV.isOverdefined(); }))
if (llvm::any_of(IVs,
[](const LatticeVal &LV) { return LV.isOverdefined(); }))
return false;
std::vector<Constant *> ConstVals;
auto *ST = dyn_cast<StructType>(V->getType());
@ -1595,7 +1592,6 @@ static bool tryToReplaceWithConstant(SCCPSolver &Solver, Value *V) {
// runSCCP() - Run the Sparse Conditional Constant Propagation algorithm,
// and return true if the function was modified.
//
static bool runSCCP(Function &F, const DataLayout &DL,
const TargetLibraryInfo *TLI) {
DEBUG(dbgs() << "SCCP on function '" << F.getName() << "'\n");
@ -1635,7 +1631,6 @@ static bool runSCCP(Function &F, const DataLayout &DL,
// Iterate over all of the instructions in a function, replacing them with
// constants if we have found them to be of constant values.
//
for (BasicBlock::iterator BI = BB.begin(), E = BB.end(); BI != E;) {
Instruction *Inst = &*BI++;
if (Inst->getType()->isVoidTy() || isa<TerminatorInst>(Inst))
@ -1666,6 +1661,7 @@ PreservedAnalyses SCCPPass::run(Function &F, FunctionAnalysisManager &AM) {
}
namespace {
//===--------------------------------------------------------------------===//
//
/// SCCP Class - This class uses the SCCPSolver to implement a per-function
@ -1673,18 +1669,20 @@ namespace {
///
class SCCPLegacyPass : public FunctionPass {
public:
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<TargetLibraryInfoWrapperPass>();
AU.addPreserved<GlobalsAAWrapperPass>();
}
static char ID; // Pass identification, replacement for typeid
// Pass identification, replacement for typeid
static char ID;
SCCPLegacyPass() : FunctionPass(ID) {
initializeSCCPLegacyPassPass(*PassRegistry::getPassRegistry());
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<TargetLibraryInfoWrapperPass>();
AU.addPreserved<GlobalsAAWrapperPass>();
}
// runOnFunction - Run the Sparse Conditional Constant Propagation
// algorithm, and return true if the function was modified.
//
bool runOnFunction(Function &F) override {
if (skipFunction(F))
return false;
@ -1694,9 +1692,11 @@ public:
return runSCCP(F, DL, TLI);
}
};
} // end anonymous namespace
char SCCPLegacyPass::ID = 0;
INITIALIZE_PASS_BEGIN(SCCPLegacyPass, "sccp",
"Sparse Conditional Constant Propagation", false, false)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
@ -1725,7 +1725,6 @@ static bool runIPSCCP(Module &M, const DataLayout &DL,
// Loop over all functions, marking arguments to those with their addresses
// taken or that are external as overdefined.
//
for (Function &F : M) {
if (F.isDeclaration())
continue;
@ -1774,7 +1773,6 @@ static bool runIPSCCP(Module &M, const DataLayout &DL,
// Iterate over all of the instructions in the module, replacing them with
// constants if we have found them to be of constant values.
//
SmallVector<BasicBlock*, 512> BlocksToErase;
for (Function &F : M) {
@ -1908,6 +1906,7 @@ PreservedAnalyses IPSCCPPass::run(Module &M, ModuleAnalysisManager &AM) {
}
namespace {
//===--------------------------------------------------------------------===//
//
/// IPSCCP Class - This class implements interprocedural Sparse Conditional
@ -1934,9 +1933,11 @@ public:
AU.addRequired<TargetLibraryInfoWrapperPass>();
}
};
} // end anonymous namespace
char IPSCCPLegacyPass::ID = 0;
INITIALIZE_PASS_BEGIN(IPSCCPLegacyPass, "ipsccp",
"Interprocedural Sparse Conditional Constant Propagation",
false, false)

View File

@ -1,4 +1,4 @@
//===--- Scalarizer.cpp - Scalarize vector operations ---------------------===//
//===- Scalarizer.cpp - Scalarize vector operations -----------------------===//
//
// The LLVM Compiler Infrastructure
//
@ -14,36 +14,59 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Options.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include <cassert>
#include <cstdint>
#include <iterator>
#include <map>
#include <utility>
using namespace llvm;
#define DEBUG_TYPE "scalarizer"
namespace {
// Used to store the scattered form of a vector.
typedef SmallVector<Value *, 8> ValueVector;
using ValueVector = SmallVector<Value *, 8>;
// Used to map a vector Value to its scattered form. We use std::map
// because we want iterators to persist across insertion and because the
// values are relatively large.
typedef std::map<Value *, ValueVector> ScatterMap;
using ScatterMap = std::map<Value *, ValueVector>;
// Lists Instructions that have been replaced with scalar implementations,
// along with a pointer to their scattered forms.
typedef SmallVector<std::pair<Instruction *, ValueVector *>, 16> GatherList;
using GatherList = SmallVector<std::pair<Instruction *, ValueVector *>, 16>;
// Provides a very limited vector-like interface for lazily accessing one
// component of a scattered vector or vector pointer.
class Scatterer {
public:
Scatterer() {}
Scatterer() = default;
// Scatter V into Size components. If new instructions are needed,
// insert them before BBI in BB. If Cache is nonnull, use it to cache
@ -71,10 +94,12 @@ private:
// called Name that compares X and Y in the same way as FCI.
struct FCmpSplitter {
FCmpSplitter(FCmpInst &fci) : FCI(fci) {}
Value *operator()(IRBuilder<> &Builder, Value *Op0, Value *Op1,
const Twine &Name) const {
return Builder.CreateFCmp(FCI.getPredicate(), Op0, Op1, Name);
}
FCmpInst &FCI;
};
@ -82,10 +107,12 @@ struct FCmpSplitter {
// called Name that compares X and Y in the same way as ICI.
struct ICmpSplitter {
ICmpSplitter(ICmpInst &ici) : ICI(ici) {}
Value *operator()(IRBuilder<> &Builder, Value *Op0, Value *Op1,
const Twine &Name) const {
return Builder.CreateICmp(ICI.getPredicate(), Op0, Op1, Name);
}
ICmpInst &ICI;
};
@ -93,16 +120,18 @@ struct ICmpSplitter {
// a binary operator like BO called Name with operands X and Y.
struct BinarySplitter {
BinarySplitter(BinaryOperator &bo) : BO(bo) {}
Value *operator()(IRBuilder<> &Builder, Value *Op0, Value *Op1,
const Twine &Name) const {
return Builder.CreateBinOp(BO.getOpcode(), Op0, Op1, Name);
}
BinaryOperator &BO;
};
// Information about a load or store that we're scalarizing.
struct VectorLayout {
VectorLayout() : VecTy(nullptr), ElemTy(nullptr), VecAlign(0), ElemSize(0) {}
VectorLayout() = default;
// Return the alignment of element I.
uint64_t getElemAlign(unsigned I) {
@ -110,16 +139,16 @@ struct VectorLayout {
}
// The type of the vector.
VectorType *VecTy;
VectorType *VecTy = nullptr;
// The type of each element.
Type *ElemTy;
Type *ElemTy = nullptr;
// The alignment of the vector.
uint64_t VecAlign;
uint64_t VecAlign = 0;
// The size of each element.
uint64_t ElemSize;
uint64_t ElemSize = 0;
};
class Scalarizer : public FunctionPass,
@ -127,8 +156,7 @@ class Scalarizer : public FunctionPass,
public:
static char ID;
Scalarizer() :
FunctionPass(ID) {
Scalarizer() : FunctionPass(ID) {
initializeScalarizerPass(*PassRegistry::getPassRegistry());
}
@ -137,19 +165,19 @@ public:
// InstVisitor methods. They return true if the instruction was scalarized,
// false if nothing changed.
bool visitInstruction(Instruction &) { return false; }
bool visitInstruction(Instruction &I) { return false; }
bool visitSelectInst(SelectInst &SI);
bool visitICmpInst(ICmpInst &);
bool visitFCmpInst(FCmpInst &);
bool visitBinaryOperator(BinaryOperator &);
bool visitGetElementPtrInst(GetElementPtrInst &);
bool visitCastInst(CastInst &);
bool visitBitCastInst(BitCastInst &);
bool visitShuffleVectorInst(ShuffleVectorInst &);
bool visitPHINode(PHINode &);
bool visitLoadInst(LoadInst &);
bool visitStoreInst(StoreInst &);
bool visitCallInst(CallInst &I);
bool visitICmpInst(ICmpInst &ICI);
bool visitFCmpInst(FCmpInst &FCI);
bool visitBinaryOperator(BinaryOperator &BO);
bool visitGetElementPtrInst(GetElementPtrInst &GEPI);
bool visitCastInst(CastInst &CI);
bool visitBitCastInst(BitCastInst &BCI);
bool visitShuffleVectorInst(ShuffleVectorInst &SVI);
bool visitPHINode(PHINode &PHI);
bool visitLoadInst(LoadInst &LI);
bool visitStoreInst(StoreInst &SI);
bool visitCallInst(CallInst &ICI);
static void registerOptions() {
// This is disabled by default because having separate loads and stores
@ -162,11 +190,12 @@ public:
}
private:
Scatterer scatter(Instruction *, Value *);
void gather(Instruction *, const ValueVector &);
Scatterer scatter(Instruction *Point, Value *V);
void gather(Instruction *Op, const ValueVector &CV);
bool canTransferMetadata(unsigned Kind);
void transferMetadata(Instruction *, const ValueVector &);
bool getVectorLayout(Type *, unsigned, VectorLayout &, const DataLayout &);
void transferMetadata(Instruction *Op, const ValueVector &CV);
bool getVectorLayout(Type *Ty, unsigned Alignment, VectorLayout &Layout,
const DataLayout &DL);
bool finish();
template<typename T> bool splitBinary(Instruction &, const T &);
@ -179,9 +208,10 @@ private:
bool ScalarizeLoadStore;
};
char Scalarizer::ID = 0;
} // end anonymous namespace
char Scalarizer::ID = 0;
INITIALIZE_PASS_WITH_OPTIONS(Scalarizer, "scalarizer",
"Scalarize vector operations", false, false)
@ -222,7 +252,7 @@ Value *Scatterer::operator[](unsigned I) {
// Search through a chain of InsertElementInsts looking for element I.
// Record other elements in the cache. The new V is still suitable
// for all uncached indices.
for (;;) {
while (true) {
InsertElementInst *Insert = dyn_cast<InsertElementInst>(V);
if (!Insert)
break;

View File

@ -1,4 +1,4 @@
//===-- StructurizeCFG.cpp ------------------------------------------------===//
//===- StructurizeCFG.cpp -------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@ -7,49 +7,72 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SCCIterator.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/DivergenceAnalysis.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/RegionInfo.h"
#include "llvm/Analysis/RegionIterator.h"
#include "llvm/Analysis/RegionPass.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/SSAUpdater.h"
#include <algorithm>
#include <cassert>
#include <utility>
using namespace llvm;
using namespace llvm::PatternMatch;
#define DEBUG_TYPE "structurizecfg"
// The name for newly created blocks.
static const char *const FlowBlockName = "Flow";
namespace {
// Definition of the complex types used in this pass.
typedef std::pair<BasicBlock *, Value *> BBValuePair;
using BBValuePair = std::pair<BasicBlock *, Value *>;
typedef SmallVector<RegionNode*, 8> RNVector;
typedef SmallVector<BasicBlock*, 8> BBVector;
typedef SmallVector<BranchInst*, 8> BranchVector;
typedef SmallVector<BBValuePair, 2> BBValueVector;
using RNVector = SmallVector<RegionNode *, 8>;
using BBVector = SmallVector<BasicBlock *, 8>;
using BranchVector = SmallVector<BranchInst *, 8>;
using BBValueVector = SmallVector<BBValuePair, 2>;
typedef SmallPtrSet<BasicBlock *, 8> BBSet;
using BBSet = SmallPtrSet<BasicBlock *, 8>;
typedef MapVector<PHINode *, BBValueVector> PhiMap;
typedef MapVector<BasicBlock *, BBVector> BB2BBVecMap;
using PhiMap = MapVector<PHINode *, BBValueVector>;
using BB2BBVecMap = MapVector<BasicBlock *, BBVector>;
typedef DenseMap<BasicBlock *, PhiMap> BBPhiMap;
typedef DenseMap<BasicBlock *, Value *> BBPredicates;
typedef DenseMap<BasicBlock *, BBPredicates> PredMap;
typedef DenseMap<BasicBlock *, BasicBlock*> BB2BBMap;
// The name for newly created blocks.
static const char *const FlowBlockName = "Flow";
using BBPhiMap = DenseMap<BasicBlock *, PhiMap>;
using BBPredicates = DenseMap<BasicBlock *, Value *>;
using PredMap = DenseMap<BasicBlock *, BBPredicates>;
using BB2BBMap = DenseMap<BasicBlock *, BasicBlock *>;
/// Finds the nearest common dominator of a set of BasicBlocks.
///
@ -736,7 +759,6 @@ void StructurizeCFG::wireFlow(bool ExitUseAllowed,
changeExit(PrevNode, Node->getEntry(), true);
}
PrevNode = Node;
} else {
// Insert extra prefix node (or reuse last one)
BasicBlock *Flow = needPrefix(false);