[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
//===---- NewGVN.cpp - Global Value Numbering Pass --------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// 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.
|
|
|
|
/// Values ending up in the same congruence class are guaranteed to be the same
|
|
|
|
/// for every execution of the program. In that respect, congruency is a
|
|
|
|
/// compile-time approximation of equivalence of values at runtime.
|
|
|
|
/// The algorithm implemented here uses a sparse formulation and it's based
|
|
|
|
/// on the ideas described in the paper:
|
|
|
|
/// "A Sparse Algorithm for Predicated Global Value Numbering" from
|
|
|
|
/// Karthik Gargi.
|
|
|
|
///
|
2017-01-27 05:39:49 +08:00
|
|
|
/// A brief overview of the algorithm: The algorithm is essentially the same as
|
|
|
|
/// the standard RPO value numbering algorithm (a good reference is the paper
|
|
|
|
/// "SCC based value numbering" by L. Taylor Simpson) with one major difference:
|
|
|
|
/// The RPO algorithm proceeds, on every iteration, to process every reachable
|
|
|
|
/// block and every instruction in that block. This is because the standard RPO
|
|
|
|
/// algorithm does not track what things have the same value number, it only
|
|
|
|
/// tracks what the value number of a given operation is (the mapping is
|
|
|
|
/// operation -> value number). Thus, when a value number of an operation
|
|
|
|
/// changes, it must reprocess everything to ensure all uses of a value number
|
|
|
|
/// get updated properly. In constrast, the sparse algorithm we use *also*
|
|
|
|
/// tracks what operations have a given value number (IE it also tracks the
|
|
|
|
/// reverse mapping from value number -> operations with that value number), so
|
|
|
|
/// that it only needs to reprocess the instructions that are affected when
|
|
|
|
/// something's value number changes. The rest of the algorithm is devoted to
|
|
|
|
/// performing symbolic evaluation, forward propagation, and simplification of
|
|
|
|
/// operations based on the value numbers deduced so far.
|
|
|
|
///
|
|
|
|
/// We also do not perform elimination by using any published algorithm. All
|
|
|
|
/// 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.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/Transforms/Scalar/NewGVN.h"
|
|
|
|
#include "llvm/ADT/BitVector.h"
|
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
|
|
#include "llvm/ADT/DenseSet.h"
|
|
|
|
#include "llvm/ADT/DepthFirstIterator.h"
|
|
|
|
#include "llvm/ADT/Hashing.h"
|
|
|
|
#include "llvm/ADT/MapVector.h"
|
|
|
|
#include "llvm/ADT/PostOrderIterator.h"
|
2016-12-26 06:23:49 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
|
|
|
#include "llvm/ADT/SmallSet.h"
|
|
|
|
#include "llvm/ADT/SparseBitVector.h"
|
|
|
|
#include "llvm/ADT/Statistic.h"
|
|
|
|
#include "llvm/ADT/TinyPtrVector.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/MemoryLocation.h"
|
2017-04-14 10:53:37 +08:00
|
|
|
#include "llvm/Analysis/MemorySSA.h"
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
|
|
|
#include "llvm/IR/DataLayout.h"
|
|
|
|
#include "llvm/IR/Dominators.h"
|
|
|
|
#include "llvm/IR/GlobalVariable.h"
|
|
|
|
#include "llvm/IR/IRBuilder.h"
|
|
|
|
#include "llvm/IR/IntrinsicInst.h"
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
|
|
|
#include "llvm/IR/Metadata.h"
|
|
|
|
#include "llvm/IR/PatternMatch.h"
|
|
|
|
#include "llvm/IR/Type.h"
|
|
|
|
#include "llvm/Support/Allocator.h"
|
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
2017-03-02 03:59:26 +08:00
|
|
|
#include "llvm/Support/DebugCounter.h"
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
#include "llvm/Transforms/Scalar.h"
|
|
|
|
#include "llvm/Transforms/Scalar/GVNExpression.h"
|
|
|
|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
|
|
|
#include "llvm/Transforms/Utils/Local.h"
|
2017-02-19 07:06:50 +08:00
|
|
|
#include "llvm/Transforms/Utils/PredicateInfo.h"
|
2017-04-02 21:23:44 +08:00
|
|
|
#include "llvm/Transforms/Utils/VNCoercion.h"
|
2017-04-07 02:52:50 +08:00
|
|
|
#include <numeric>
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
#include <unordered_map>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
|
|
|
using namespace llvm;
|
|
|
|
using namespace PatternMatch;
|
|
|
|
using namespace llvm::GVNExpression;
|
2017-04-02 21:23:44 +08:00
|
|
|
using namespace llvm::VNCoercion;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
#define DEBUG_TYPE "newgvn"
|
|
|
|
|
|
|
|
STATISTIC(NumGVNInstrDeleted, "Number of instructions deleted");
|
|
|
|
STATISTIC(NumGVNBlocksDeleted, "Number of blocks deleted");
|
|
|
|
STATISTIC(NumGVNOpsSimplified, "Number of Expressions simplified");
|
|
|
|
STATISTIC(NumGVNPhisAllSame, "Number of PHIs whos arguments are all the same");
|
2017-01-07 11:23:47 +08:00
|
|
|
STATISTIC(NumGVNMaxIterations,
|
|
|
|
"Maximum Number of iterations it took to converge GVN");
|
2017-01-14 06:40:01 +08:00
|
|
|
STATISTIC(NumGVNLeaderChanges, "Number of leader changes");
|
|
|
|
STATISTIC(NumGVNSortedLeaderChanges, "Number of sorted leader changes");
|
|
|
|
STATISTIC(NumGVNAvoidedSortedLeaderChanges,
|
|
|
|
"Number of avoided sorted leader changes");
|
2017-01-20 14:38:41 +08:00
|
|
|
STATISTIC(NumGVNNotMostDominatingLeader,
|
|
|
|
"Number of times a member dominated it's new classes' leader");
|
2017-01-27 10:37:11 +08:00
|
|
|
STATISTIC(NumGVNDeadStores, "Number of redundant/dead stores eliminated");
|
2017-03-02 03:59:26 +08:00
|
|
|
DEBUG_COUNTER(VNCounter, "newgvn-vn",
|
|
|
|
"Controls which instructions are value numbered")
|
2017-04-07 02:52:50 +08:00
|
|
|
|
|
|
|
// Currently store defining access refinement is too slow due to basicaa being
|
|
|
|
// egregiously slow. This flag lets us keep it working while we work on this
|
|
|
|
// issue.
|
|
|
|
static cl::opt<bool> EnableStoreRefinement("enable-store-refinement",
|
|
|
|
cl::init(false), cl::Hidden);
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// GVN Pass
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
// Anchor methods.
|
|
|
|
namespace llvm {
|
|
|
|
namespace GVNExpression {
|
2016-12-27 04:06:58 +08:00
|
|
|
Expression::~Expression() = default;
|
|
|
|
BasicExpression::~BasicExpression() = default;
|
|
|
|
CallExpression::~CallExpression() = default;
|
|
|
|
LoadExpression::~LoadExpression() = default;
|
|
|
|
StoreExpression::~StoreExpression() = default;
|
|
|
|
AggregateValueExpression::~AggregateValueExpression() = default;
|
|
|
|
PHIExpression::~PHIExpression() = default;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-14 10:53:37 +08:00
|
|
|
// 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
|
|
|
|
// about, and have us process them there or risk redoing work.
|
|
|
|
// Graph traits over a filter iterator also doesn't work that well here.
|
2017-04-19 04:15:47 +08:00
|
|
|
// This SCC finder is specialized to walk use-def chains, and only follows
|
|
|
|
// instructions,
|
2017-04-14 10:53:37 +08:00
|
|
|
// not generic values (arguments, etc).
|
|
|
|
struct TarjanSCC {
|
|
|
|
|
|
|
|
TarjanSCC() : Components(1) {}
|
|
|
|
|
|
|
|
void Start(const Instruction *Start) {
|
|
|
|
if (Root.lookup(Start) == 0)
|
|
|
|
FindSCC(Start);
|
|
|
|
}
|
|
|
|
|
|
|
|
const SmallPtrSetImpl<const Value *> &getComponentFor(const Value *V) const {
|
|
|
|
unsigned ComponentID = ValueToComponent.lookup(V);
|
|
|
|
|
|
|
|
assert(ComponentID > 0 &&
|
|
|
|
"Asking for a component for a value we never processed");
|
|
|
|
return Components[ComponentID];
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
void FindSCC(const Instruction *I) {
|
|
|
|
Root[I] = ++DFSNum;
|
|
|
|
// Store the DFS Number we had before it possibly gets incremented.
|
|
|
|
unsigned int OurDFS = DFSNum;
|
|
|
|
for (auto &Op : I->operands()) {
|
|
|
|
if (auto *InstOp = dyn_cast<Instruction>(Op)) {
|
|
|
|
if (Root.lookup(Op) == 0)
|
|
|
|
FindSCC(InstOp);
|
|
|
|
if (!InComponent.count(Op))
|
|
|
|
Root[I] = std::min(Root.lookup(I), Root.lookup(Op));
|
|
|
|
}
|
|
|
|
}
|
2017-04-19 04:15:47 +08:00
|
|
|
// See if we really were the root of a component, by seeing if we still have
|
|
|
|
// our DFSNumber.
|
|
|
|
// If we do, we are the root of the component, and we have completed a
|
|
|
|
// component. If we do not,
|
2017-04-14 10:53:37 +08:00
|
|
|
// we are not the root of a component, and belong on the component stack.
|
|
|
|
if (Root.lookup(I) == OurDFS) {
|
|
|
|
unsigned ComponentID = Components.size();
|
|
|
|
Components.resize(Components.size() + 1);
|
|
|
|
auto &Component = Components.back();
|
|
|
|
Component.insert(I);
|
|
|
|
DEBUG(dbgs() << "Component root is " << *I << "\n");
|
|
|
|
InComponent.insert(I);
|
|
|
|
ValueToComponent[I] = ComponentID;
|
|
|
|
// Pop a component off the stack and label it.
|
|
|
|
while (!Stack.empty() && Root.lookup(Stack.back()) >= OurDFS) {
|
|
|
|
auto *Member = Stack.back();
|
|
|
|
DEBUG(dbgs() << "Component member is " << *Member << "\n");
|
|
|
|
Component.insert(Member);
|
|
|
|
InComponent.insert(Member);
|
|
|
|
ValueToComponent[Member] = ComponentID;
|
|
|
|
Stack.pop_back();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Part of a component, push to stack
|
|
|
|
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;
|
|
|
|
};
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// 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
|
|
|
|
// because of memory value numbering, it is not correct to assume
|
|
|
|
// you can willy-nilly replace any member with any other at any
|
|
|
|
// point in the function.
|
|
|
|
//
|
|
|
|
// For any Value in the Member set, it is valid to replace any dominated member
|
|
|
|
// with that Value.
|
|
|
|
//
|
2017-04-07 02:52:50 +08:00
|
|
|
// Every congruence class has a leader, and the leader is used to symbolize
|
|
|
|
// instructions in a canonical way (IE every operand of an instruction that is a
|
|
|
|
// member of the same congruence class will always be replaced with leader
|
|
|
|
// during symbolization). To simplify symbolization, we keep the leader as a
|
|
|
|
// constant if class can be proved to be a constant value. Otherwise, the
|
|
|
|
// leader is the member of the value set with the smallest DFS number. Each
|
|
|
|
// congruence class also has a defining expression, though the expression may be
|
|
|
|
// null. If it exists, it can be used for forward propagation and reassociation
|
|
|
|
// of values.
|
|
|
|
|
|
|
|
// For memory, we also track a representative MemoryAccess, and a set of memory
|
|
|
|
// members for MemoryPhis (which have no real instructions). Note that for
|
|
|
|
// memory, it seems tempting to try to split the memory members into a
|
|
|
|
// MemoryCongruenceClass or something. Unfortunately, this does not work
|
|
|
|
// easily. The value numbering of a given memory expression depends on the
|
|
|
|
// leader of the memory congruence class, and the leader of memory congruence
|
|
|
|
// class depends on the value numbering of a given memory expression. This
|
|
|
|
// leads to wasted propagation, and in some cases, missed optimization. For
|
|
|
|
// example: If we had value numbered two stores together before, but now do not,
|
|
|
|
// we move them to a new value congruence class. This in turn will move at one
|
|
|
|
// of the memorydefs to a new memory congruence class. Which in turn, affects
|
|
|
|
// the value numbering of the stores we just value numbered (because the memory
|
|
|
|
// congruence class is part of the value number). So while theoretically
|
|
|
|
// possible to split them up, it turns out to be *incredibly* complicated to get
|
|
|
|
// it to work right, because of the interdependency. While structurally
|
|
|
|
// slightly messier, it is algorithmically much simpler and faster to do what we
|
2017-04-08 02:38:09 +08:00
|
|
|
// do here, and track them both at once in the same class.
|
|
|
|
// Note: The default iterators for this class iterate over values
|
|
|
|
class CongruenceClass {
|
|
|
|
public:
|
|
|
|
using MemberType = Value;
|
|
|
|
using MemberSet = SmallPtrSet<MemberType *, 4>;
|
|
|
|
using MemoryMemberType = MemoryPhi;
|
|
|
|
using MemoryMemberSet = SmallPtrSet<const MemoryMemberType *, 2>;
|
|
|
|
|
|
|
|
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 {
|
|
|
|
// If it's both dead from a value perspective, and dead from a memory
|
|
|
|
// perspective, it's really dead.
|
|
|
|
return empty() && memory_empty();
|
|
|
|
}
|
|
|
|
// Leader functions
|
|
|
|
Value *getLeader() const { return RepLeader; }
|
|
|
|
void setLeader(Value *Leader) { RepLeader = Leader; }
|
|
|
|
const std::pair<Value *, unsigned int> &getNextLeader() const {
|
|
|
|
return NextLeader;
|
|
|
|
}
|
|
|
|
void resetNextLeader() { NextLeader = {nullptr, ~0}; }
|
|
|
|
|
|
|
|
void addPossibleNextLeader(std::pair<Value *, unsigned int> LeaderPair) {
|
|
|
|
if (LeaderPair.second < NextLeader.second)
|
|
|
|
NextLeader = LeaderPair;
|
|
|
|
}
|
|
|
|
|
|
|
|
Value *getStoredValue() const { return RepStoredValue; }
|
|
|
|
void setStoredValue(Value *Leader) { RepStoredValue = Leader; }
|
|
|
|
const MemoryAccess *getMemoryLeader() const { return RepMemoryAccess; }
|
|
|
|
void setMemoryLeader(const MemoryAccess *Leader) { RepMemoryAccess = Leader; }
|
|
|
|
|
|
|
|
// Forward propagation info
|
|
|
|
const Expression *getDefiningExpr() const { return DefiningExpr; }
|
|
|
|
|
|
|
|
// Value member set
|
|
|
|
bool empty() const { return Members.empty(); }
|
|
|
|
unsigned size() const { return Members.size(); }
|
|
|
|
MemberSet::const_iterator begin() const { return Members.begin(); }
|
|
|
|
MemberSet::const_iterator end() const { return Members.end(); }
|
|
|
|
void insert(MemberType *M) { Members.insert(M); }
|
|
|
|
void erase(MemberType *M) { Members.erase(M); }
|
|
|
|
void swap(MemberSet &Other) { Members.swap(Other); }
|
|
|
|
|
|
|
|
// Memory member set
|
|
|
|
bool memory_empty() const { return MemoryMembers.empty(); }
|
|
|
|
unsigned memory_size() const { return MemoryMembers.size(); }
|
|
|
|
MemoryMemberSet::const_iterator memory_begin() const {
|
|
|
|
return MemoryMembers.begin();
|
|
|
|
}
|
|
|
|
MemoryMemberSet::const_iterator memory_end() const {
|
|
|
|
return MemoryMembers.end();
|
|
|
|
}
|
|
|
|
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); }
|
|
|
|
|
|
|
|
// Store count
|
|
|
|
unsigned getStoreCount() const { return StoreCount; }
|
|
|
|
void incStoreCount() { ++StoreCount; }
|
|
|
|
void decStoreCount() {
|
|
|
|
assert(StoreCount != 0 && "Store count went negative");
|
|
|
|
--StoreCount;
|
|
|
|
}
|
|
|
|
|
2017-05-11 03:57:43 +08:00
|
|
|
// True if this class has no memory members.
|
|
|
|
bool definesNoMemory() const { return StoreCount == 0 && memory_empty(); }
|
|
|
|
|
2017-04-08 02:38:09 +08:00
|
|
|
// Return true if two congruence classes are equivalent to each other. This
|
|
|
|
// means
|
|
|
|
// that every field but the ID number and the dead field are equivalent.
|
|
|
|
bool isEquivalentTo(const CongruenceClass *Other) const {
|
|
|
|
if (!Other)
|
|
|
|
return false;
|
|
|
|
if (this == Other)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (std::tie(StoreCount, RepLeader, RepStoredValue, RepMemoryAccess) !=
|
|
|
|
std::tie(Other->StoreCount, Other->RepLeader, Other->RepStoredValue,
|
|
|
|
Other->RepMemoryAccess))
|
|
|
|
return false;
|
|
|
|
if (DefiningExpr != Other->DefiningExpr)
|
|
|
|
if (!DefiningExpr || !Other->DefiningExpr ||
|
|
|
|
*DefiningExpr != *Other->DefiningExpr)
|
|
|
|
return false;
|
|
|
|
// We need some ordered set
|
|
|
|
std::set<Value *> AMembers(Members.begin(), Members.end());
|
|
|
|
std::set<Value *> BMembers(Members.begin(), Members.end());
|
|
|
|
return AMembers == BMembers;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
unsigned ID;
|
|
|
|
// Representative leader.
|
2016-12-29 03:17:17 +08:00
|
|
|
Value *RepLeader = nullptr;
|
2017-04-08 02:38:09 +08:00
|
|
|
// 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};
|
2017-04-07 02:52:50 +08:00
|
|
|
// If this is represented by a store, the value of the store.
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
Value *RepStoredValue = nullptr;
|
2017-04-07 02:52:50 +08:00
|
|
|
// If this class contains MemoryDefs or MemoryPhis, this is the leading memory
|
|
|
|
// access.
|
|
|
|
const MemoryAccess *RepMemoryAccess = nullptr;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Defining Expression.
|
2016-12-29 03:17:17 +08:00
|
|
|
const Expression *DefiningExpr = nullptr;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Actual members of this class.
|
|
|
|
MemberSet Members;
|
2017-04-07 02:52:50 +08:00
|
|
|
// 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;
|
2017-01-12 04:22:36 +08:00
|
|
|
// Number of stores in this congruence class.
|
|
|
|
// This is used so we can detect store equivalence changes properly.
|
2017-01-12 07:41:24 +08:00
|
|
|
int StoreCount = 0;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
namespace llvm {
|
2016-12-27 04:06:58 +08:00
|
|
|
template <> struct DenseMapInfo<const Expression *> {
|
|
|
|
static const Expression *getEmptyKey() {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto Val = static_cast<uintptr_t>(-1);
|
2016-12-27 04:06:58 +08:00
|
|
|
Val <<= PointerLikeTypeTraits<const Expression *>::NumLowBitsAvailable;
|
|
|
|
return reinterpret_cast<const Expression *>(Val);
|
|
|
|
}
|
|
|
|
static const Expression *getTombstoneKey() {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto Val = static_cast<uintptr_t>(~1U);
|
2016-12-27 04:06:58 +08:00
|
|
|
Val <<= PointerLikeTypeTraits<const Expression *>::NumLowBitsAvailable;
|
|
|
|
return reinterpret_cast<const Expression *>(Val);
|
|
|
|
}
|
|
|
|
static unsigned getHashValue(const Expression *V) {
|
|
|
|
return static_cast<unsigned>(V->getHashValue());
|
|
|
|
}
|
|
|
|
static bool isEqual(const Expression *LHS, const Expression *RHS) {
|
|
|
|
if (LHS == RHS)
|
|
|
|
return true;
|
|
|
|
if (LHS == getTombstoneKey() || RHS == getTombstoneKey() ||
|
|
|
|
LHS == getEmptyKey() || RHS == getEmptyKey())
|
|
|
|
return false;
|
|
|
|
return *LHS == *RHS;
|
|
|
|
}
|
|
|
|
};
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
} // end namespace llvm
|
|
|
|
|
2017-02-11 19:06:55 +08:00
|
|
|
namespace {
|
2017-03-12 12:46:45 +08:00
|
|
|
class NewGVN {
|
|
|
|
Function &F;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
DominatorTree *DT;
|
2017-03-12 12:46:45 +08:00
|
|
|
const TargetLibraryInfo *TLI;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
AliasAnalysis *AA;
|
|
|
|
MemorySSA *MSSA;
|
|
|
|
MemorySSAWalker *MSSAWalker;
|
2017-03-12 12:46:45 +08:00
|
|
|
const DataLayout &DL;
|
2017-02-19 07:06:50 +08:00
|
|
|
std::unique_ptr<PredicateInfo> PredInfo;
|
2017-05-10 00:40:04 +08:00
|
|
|
|
|
|
|
// These are the only two things the create* functions should have
|
|
|
|
// side-effects on due to allocating memory.
|
|
|
|
mutable BumpPtrAllocator ExpressionAllocator;
|
|
|
|
mutable ArrayRecycler<Value *> ArgRecycler;
|
|
|
|
mutable TarjanSCC SCCFinder;
|
2017-04-27 04:56:14 +08:00
|
|
|
const SimplifyQuery SQ;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2017-02-11 23:07:01 +08:00
|
|
|
// Number of function arguments, used by ranking
|
|
|
|
unsigned int NumFuncArgs;
|
|
|
|
|
2017-04-14 10:53:37 +08:00
|
|
|
// RPOOrdering of basic blocks
|
|
|
|
DenseMap<const DomTreeNode *, unsigned> RPOOrdering;
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Congruence class info.
|
2017-02-11 20:48:50 +08:00
|
|
|
|
|
|
|
// This class is called INITIAL in the paper. It is the class everything
|
|
|
|
// startsout in, and represents any value. Being an optimistic analysis,
|
2017-03-11 03:05:04 +08:00
|
|
|
// anything in the TOP class has the value TOP, which is indeterminate and
|
2017-02-11 20:48:50 +08:00
|
|
|
// equivalent to everything.
|
2017-03-11 03:05:04 +08:00
|
|
|
CongruenceClass *TOPClass;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
std::vector<CongruenceClass *> CongruenceClasses;
|
|
|
|
unsigned NextCongruenceNum;
|
|
|
|
|
|
|
|
// Value Mappings.
|
|
|
|
DenseMap<Value *, CongruenceClass *> ValueToClass;
|
|
|
|
DenseMap<Value *, const Expression *> ValueToExpression;
|
|
|
|
|
2017-02-19 07:06:50 +08:00
|
|
|
// Mapping from predicate info we used to the instructions we used it with.
|
|
|
|
// In order to correctly ensure propagation, we must keep track of what
|
|
|
|
// comparisons we used, so that when the values of the comparisons change, we
|
|
|
|
// propagate the information to the places we used the comparison.
|
2017-05-10 00:40:04 +08:00
|
|
|
mutable DenseMap<const Value *, SmallPtrSet<Instruction *, 2>>
|
|
|
|
PredicateToUsers;
|
2017-04-07 02:52:50 +08:00
|
|
|
// the same reasoning as PredicateToUsers. When we skip MemoryAccesses for
|
|
|
|
// stores, we no longer can rely solely on the def-use chains of MemorySSA.
|
2017-05-10 00:40:04 +08:00
|
|
|
mutable DenseMap<const MemoryAccess *, SmallPtrSet<MemoryAccess *, 2>>
|
|
|
|
MemoryToUsers;
|
2017-02-19 07:06:50 +08:00
|
|
|
|
2016-12-26 06:23:49 +08:00
|
|
|
// A table storing which memorydefs/phis represent a memory state provably
|
|
|
|
// equivalent to another memory state.
|
|
|
|
// We could use the congruence class machinery, but the MemoryAccess's are
|
|
|
|
// abstract memory states, so they can only ever be equivalent to each other,
|
|
|
|
// and not to constants, etc.
|
2017-01-27 06:21:48 +08:00
|
|
|
DenseMap<const MemoryAccess *, CongruenceClass *> MemoryAccessToClass;
|
2016-12-26 06:23:49 +08:00
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
// We could, if we wanted, build MemoryPhiExpressions and
|
|
|
|
// MemoryVariableExpressions, etc, and value number them the same way we value
|
|
|
|
// number phi expressions. For the moment, this seems like overkill. They
|
|
|
|
// can only exist in one of three states: they can be TOP (equal to
|
|
|
|
// everything), Equivalent to something else, or unique. Because we do not
|
|
|
|
// create expressions for them, we need to simulate leader change not just
|
|
|
|
// when they change class, but when they change state. Note: We can do the
|
|
|
|
// same thing for phis, and avoid having phi expressions if we wanted, We
|
|
|
|
// should eventually unify in one direction or the other, so this is a little
|
|
|
|
// bit of an experiment in which turns out easier to maintain.
|
|
|
|
enum MemoryPhiState { MPS_Invalid, MPS_TOP, MPS_Equivalent, MPS_Unique };
|
|
|
|
DenseMap<const MemoryPhi *, MemoryPhiState> MemoryPhiState;
|
|
|
|
|
2017-04-14 10:53:37 +08:00
|
|
|
enum PhiCycleState { PCS_Unknown, PCS_CycleFree, PCS_Cycle };
|
2017-05-10 00:40:04 +08:00
|
|
|
mutable DenseMap<const PHINode *, PhiCycleState> PhiCycleState;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Expression to class mapping.
|
2016-12-29 03:29:26 +08:00
|
|
|
using ExpressionClassMap = DenseMap<const Expression *, CongruenceClass *>;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
ExpressionClassMap ExpressionToClass;
|
|
|
|
|
|
|
|
// Which values have changed as a result of leader changes.
|
2017-01-12 04:22:05 +08:00
|
|
|
SmallPtrSet<Value *, 8> LeaderChanges;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Reachability info.
|
2016-12-29 03:17:17 +08:00
|
|
|
using BlockEdge = BasicBlockEdge;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
DenseSet<BlockEdge> ReachableEdges;
|
|
|
|
SmallPtrSet<const BasicBlock *, 8> ReachableBlocks;
|
|
|
|
|
|
|
|
// This is a bitvector because, on larger functions, we may have
|
|
|
|
// thousands of touched instructions at once (entire blocks,
|
|
|
|
// instructions with hundreds of uses, etc). Even with optimization
|
|
|
|
// for when we mark whole blocks as touched, when this was a
|
|
|
|
// SmallPtrSet or DenseSet, for some functions, we spent >20% of all
|
|
|
|
// the time in GVN just managing this list. The bitvector, on the
|
|
|
|
// other hand, efficiently supports test/set/clear of both
|
|
|
|
// individual and ranges, as well as "find next element" This
|
|
|
|
// enables us to use it as a worklist with essentially 0 cost.
|
|
|
|
BitVector TouchedInstructions;
|
|
|
|
|
|
|
|
DenseMap<const BasicBlock *, std::pair<unsigned, unsigned>> BlockInstRange;
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
// Debugging for how many times each block and instruction got processed.
|
|
|
|
DenseMap<const Value *, unsigned> ProcessedCount;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// DFS info.
|
2017-01-21 07:29:28 +08:00
|
|
|
// This contains a mapping from Instructions to DFS numbers.
|
|
|
|
// The numbering starts at 1. An instruction with DFS number zero
|
|
|
|
// means that the instruction is dead.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
DenseMap<const Value *, unsigned> InstrDFS;
|
2017-01-21 07:29:28 +08:00
|
|
|
|
|
|
|
// This contains the mapping DFS numbers to instructions.
|
2016-12-27 17:20:36 +08:00
|
|
|
SmallVector<Value *, 32> DFSToInstr;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Deletion info.
|
|
|
|
SmallPtrSet<Instruction *, 8> InstructionsToErase;
|
|
|
|
|
|
|
|
public:
|
2017-03-12 12:46:45 +08:00
|
|
|
NewGVN(Function &F, DominatorTree *DT, AssumptionCache *AC,
|
|
|
|
TargetLibraryInfo *TLI, AliasAnalysis *AA, MemorySSA *MSSA,
|
|
|
|
const DataLayout &DL)
|
2017-04-29 03:55:38 +08:00
|
|
|
: F(F), DT(DT), TLI(TLI), AA(AA), MSSA(MSSA), DL(DL),
|
2017-04-27 04:56:14 +08:00
|
|
|
PredInfo(make_unique<PredicateInfo>(F, *DT, *AC)), SQ(DL, TLI, DT, AC) {
|
|
|
|
}
|
2017-03-12 12:46:45 +08:00
|
|
|
bool runGVN();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
// Expression handling.
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *createExpression(Instruction *) const;
|
|
|
|
const Expression *createBinaryExpression(unsigned, Type *, Value *,
|
|
|
|
Value *) const;
|
|
|
|
PHIExpression *createPHIExpression(Instruction *, bool &HasBackEdge,
|
|
|
|
bool &AllConstant) const;
|
|
|
|
const VariableExpression *createVariableExpression(Value *) const;
|
|
|
|
const ConstantExpression *createConstantExpression(Constant *) const;
|
|
|
|
const Expression *createVariableOrConstant(Value *V) const;
|
|
|
|
const UnknownExpression *createUnknownExpression(Instruction *) const;
|
2017-04-07 02:52:50 +08:00
|
|
|
const StoreExpression *createStoreExpression(StoreInst *,
|
2017-05-10 00:40:04 +08:00
|
|
|
const MemoryAccess *) const;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
LoadExpression *createLoadExpression(Type *, Value *, LoadInst *,
|
2017-05-10 00:40:04 +08:00
|
|
|
const MemoryAccess *) const;
|
|
|
|
const CallExpression *createCallExpression(CallInst *,
|
|
|
|
const MemoryAccess *) const;
|
|
|
|
const AggregateValueExpression *
|
|
|
|
createAggregateValueExpression(Instruction *) const;
|
|
|
|
bool setBasicExpressionInfo(Instruction *, BasicExpression *) const;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Congruence class handling.
|
|
|
|
CongruenceClass *createCongruenceClass(Value *Leader, const Expression *E) {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *result = new CongruenceClass(NextCongruenceNum++, Leader, E);
|
2016-12-29 07:24:02 +08:00
|
|
|
CongruenceClasses.emplace_back(result);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
CongruenceClass *createMemoryClass(MemoryAccess *MA) {
|
|
|
|
auto *CC = createCongruenceClass(nullptr, nullptr);
|
2017-04-08 02:38:09 +08:00
|
|
|
CC->setMemoryLeader(MA);
|
2017-04-07 02:52:50 +08:00
|
|
|
return CC;
|
|
|
|
}
|
|
|
|
CongruenceClass *ensureLeaderOfMemoryClass(MemoryAccess *MA) {
|
|
|
|
auto *CC = getMemoryClass(MA);
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC->getMemoryLeader() != MA)
|
2017-04-07 02:52:50 +08:00
|
|
|
CC = createMemoryClass(MA);
|
|
|
|
return CC;
|
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
CongruenceClass *createSingletonCongruenceClass(Value *Member) {
|
2016-12-28 22:00:11 +08:00
|
|
|
CongruenceClass *CClass = createCongruenceClass(Member, nullptr);
|
2017-04-08 02:38:09 +08:00
|
|
|
CClass->insert(Member);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
ValueToClass[Member] = CClass;
|
|
|
|
return CClass;
|
|
|
|
}
|
|
|
|
void initializeCongruenceClasses(Function &F);
|
|
|
|
|
2016-12-26 06:23:49 +08:00
|
|
|
// Value number an Instruction or MemoryPhi.
|
|
|
|
void valueNumberMemoryPhi(MemoryPhi *);
|
|
|
|
void valueNumberInstruction(Instruction *);
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Symbolic evaluation.
|
|
|
|
const Expression *checkSimplificationResults(Expression *, Instruction *,
|
2017-05-10 00:40:04 +08:00
|
|
|
Value *) const;
|
|
|
|
const Expression *performSymbolicEvaluation(Value *) const;
|
2017-04-02 21:23:44 +08:00
|
|
|
const Expression *performSymbolicLoadCoercion(Type *, Value *, LoadInst *,
|
2017-05-10 00:40:04 +08:00
|
|
|
Instruction *,
|
|
|
|
MemoryAccess *) const;
|
|
|
|
const Expression *performSymbolicLoadEvaluation(Instruction *) const;
|
|
|
|
const Expression *performSymbolicStoreEvaluation(Instruction *) const;
|
|
|
|
const Expression *performSymbolicCallEvaluation(Instruction *) const;
|
|
|
|
const Expression *performSymbolicPHIEvaluation(Instruction *) const;
|
|
|
|
const Expression *performSymbolicAggrValueEvaluation(Instruction *) const;
|
|
|
|
const Expression *performSymbolicCmpEvaluation(Instruction *) const;
|
|
|
|
const Expression *performSymbolicPredicateInfoEvaluation(Instruction *) const;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Congruence finding.
|
2017-03-24 13:30:34 +08:00
|
|
|
bool someEquivalentDominates(const Instruction *, const Instruction *) const;
|
2017-02-01 06:31:53 +08:00
|
|
|
Value *lookupOperandLeader(Value *) const;
|
2017-01-14 06:40:01 +08:00
|
|
|
void performCongruenceFinding(Instruction *, const Expression *);
|
2017-04-07 02:52:50 +08:00
|
|
|
void moveValueToNewCongruenceClass(Instruction *, const Expression *,
|
|
|
|
CongruenceClass *, CongruenceClass *);
|
|
|
|
void moveMemoryToNewCongruenceClass(Instruction *, MemoryAccess *,
|
|
|
|
CongruenceClass *, CongruenceClass *);
|
|
|
|
Value *getNextValueLeader(CongruenceClass *) const;
|
|
|
|
const MemoryAccess *getNextMemoryLeader(CongruenceClass *) const;
|
|
|
|
bool setMemoryClass(const MemoryAccess *From, CongruenceClass *To);
|
|
|
|
CongruenceClass *getMemoryClass(const MemoryAccess *MA) const;
|
|
|
|
const MemoryAccess *lookupMemoryLeader(const MemoryAccess *) const;
|
2017-01-27 10:37:11 +08:00
|
|
|
bool isMemoryAccessTop(const MemoryAccess *) const;
|
2017-04-07 02:52:50 +08:00
|
|
|
|
2017-02-11 23:07:01 +08:00
|
|
|
// Ranking
|
|
|
|
unsigned int getRank(const Value *) const;
|
|
|
|
bool shouldSwapOperands(const Value *, const Value *) const;
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Reachability handling.
|
|
|
|
void updateReachableEdge(BasicBlock *, BasicBlock *);
|
|
|
|
void processOutgoingEdges(TerminatorInst *, BasicBlock *);
|
2017-02-01 06:32:03 +08:00
|
|
|
Value *findConditionEquivalence(Value *) const;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Elimination.
|
|
|
|
struct ValueDFS;
|
2017-04-08 02:38:09 +08:00
|
|
|
void convertClassToDFSOrdered(const CongruenceClass &,
|
2017-03-10 08:32:33 +08:00
|
|
|
SmallVectorImpl<ValueDFS> &,
|
|
|
|
DenseMap<const Value *, unsigned int> &,
|
2017-04-08 02:38:09 +08:00
|
|
|
SmallPtrSetImpl<Instruction *> &) const;
|
|
|
|
void convertClassToLoadsAndStores(const CongruenceClass &,
|
|
|
|
SmallVectorImpl<ValueDFS> &) const;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
bool eliminateInstructions(Function &);
|
|
|
|
void replaceInstruction(Instruction *, Value *);
|
|
|
|
void markInstructionForDeletion(Instruction *);
|
|
|
|
void deleteInstructionsInBlock(BasicBlock *);
|
|
|
|
|
|
|
|
// New instruction creation.
|
|
|
|
void handleNewInstruction(Instruction *){};
|
2017-01-08 00:55:14 +08:00
|
|
|
|
|
|
|
// Various instruction touch utilities
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
void markUsersTouched(Value *);
|
2017-04-07 02:52:50 +08:00
|
|
|
void markMemoryUsersTouched(const MemoryAccess *);
|
|
|
|
void markMemoryDefTouched(const MemoryAccess *);
|
2017-02-19 07:06:50 +08:00
|
|
|
void markPredicateUsersTouched(Instruction *);
|
2017-04-07 02:52:50 +08:00
|
|
|
void markValueLeaderChangeTouched(CongruenceClass *CC);
|
|
|
|
void markMemoryLeaderChangeTouched(CongruenceClass *CC);
|
2017-05-10 00:40:04 +08:00
|
|
|
void addPredicateUsers(const PredicateBase *, Instruction *) const;
|
|
|
|
void addMemoryUsers(const MemoryAccess *To, MemoryAccess *U) const;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2017-03-18 23:41:40 +08:00
|
|
|
// Main loop of value numbering
|
|
|
|
void iterateTouchedInstructions();
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Utilities.
|
|
|
|
void cleanupTables();
|
|
|
|
std::pair<unsigned, unsigned> assignDFSNumbers(BasicBlock *, unsigned);
|
|
|
|
void updateProcessedCount(Value *V);
|
2017-01-12 04:22:36 +08:00
|
|
|
void verifyMemoryCongruency() const;
|
2017-03-18 23:41:40 +08:00
|
|
|
void verifyIterationSettled(Function &F);
|
2017-05-17 03:58:47 +08:00
|
|
|
void verifyStoreExpressions() const;
|
2017-05-19 07:22:44 +08:00
|
|
|
bool singleReachablePHIPath(SmallPtrSet<const MemoryAccess *, 8> &,
|
|
|
|
const MemoryAccess *, const MemoryAccess *) const;
|
2017-03-18 23:41:40 +08:00
|
|
|
BasicBlock *getBlockForValue(Value *V) const;
|
2017-05-10 00:40:04 +08:00
|
|
|
void deleteExpression(const Expression *E) const;
|
2017-04-07 02:52:58 +08:00
|
|
|
unsigned InstrToDFSNum(const Value *V) const {
|
2017-04-07 02:52:50 +08:00
|
|
|
assert(isa<Instruction>(V) && "This should not be used for MemoryAccesses");
|
|
|
|
return InstrDFS.lookup(V);
|
|
|
|
}
|
|
|
|
|
2017-04-07 02:52:58 +08:00
|
|
|
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.
|
|
|
|
unsigned MemoryToDFSNum(const Value *MA) const {
|
|
|
|
assert(isa<MemoryAccess>(MA) &&
|
|
|
|
"This should not be used with instructions");
|
|
|
|
return isa<MemoryUseOrDef>(MA)
|
|
|
|
? InstrToDFSNum(cast<MemoryUseOrDef>(MA)->getMemoryInst())
|
|
|
|
: InstrDFS.lookup(MA);
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
2017-05-16 14:06:12 +08:00
|
|
|
bool isCycleFree(const PHINode *PN) const;
|
2017-04-07 02:52:50 +08:00
|
|
|
template <class T, class Range> T *getMinDFSOfRange(const Range &) const;
|
2017-03-18 23:41:40 +08:00
|
|
|
// 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;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
};
|
2017-02-11 19:06:55 +08:00
|
|
|
} // end anonymous namespace
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2016-12-28 21:37:17 +08:00
|
|
|
template <typename T>
|
|
|
|
static bool equalsLoadStoreHelper(const T &LHS, const Expression &RHS) {
|
2017-04-01 17:44:29 +08:00
|
|
|
if (!isa<LoadExpression>(RHS) && !isa<StoreExpression>(RHS))
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return false;
|
2017-04-01 17:44:29 +08:00
|
|
|
return LHS.MemoryExpression::equals(RHS);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
2016-12-28 21:37:17 +08:00
|
|
|
bool LoadExpression::equals(const Expression &Other) const {
|
|
|
|
return equalsLoadStoreHelper(*this, Other);
|
|
|
|
}
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2016-12-28 21:37:17 +08:00
|
|
|
bool StoreExpression::equals(const Expression &Other) const {
|
2017-04-01 17:44:29 +08:00
|
|
|
if (!equalsLoadStoreHelper(*this, Other))
|
|
|
|
return false;
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
// Make sure that store vs store includes the value operand.
|
2017-04-01 17:44:29 +08:00
|
|
|
if (const auto *S = dyn_cast<StoreExpression>(&Other))
|
|
|
|
if (getStoredValue() != S->getStoredValue())
|
|
|
|
return false;
|
|
|
|
return true;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
static std::string getBlockName(const BasicBlock *B) {
|
2016-12-28 22:00:11 +08:00
|
|
|
return DOTGraphTraits<const Function *>::getSimpleNodeLabel(B, nullptr);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-03-18 23:41:40 +08:00
|
|
|
// Get the basic block from an instruction/memory value.
|
|
|
|
BasicBlock *NewGVN::getBlockForValue(Value *V) const {
|
|
|
|
if (auto *I = dyn_cast<Instruction>(V))
|
|
|
|
return I->getParent();
|
|
|
|
else if (auto *MP = dyn_cast<MemoryPhi>(V))
|
|
|
|
return MP->getBlock();
|
|
|
|
llvm_unreachable("Should have been able to figure out a block for our value");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-03-24 14:33:48 +08:00
|
|
|
// Delete a definitely dead expression, so it can be reused by the expression
|
|
|
|
// allocator. Some of these are not in creation functions, so we have to accept
|
|
|
|
// const versions.
|
2017-05-10 00:40:04 +08:00
|
|
|
void NewGVN::deleteExpression(const Expression *E) const {
|
2017-03-24 14:33:48 +08:00
|
|
|
assert(isa<BasicExpression>(E));
|
|
|
|
auto *BE = cast<BasicExpression>(E);
|
|
|
|
const_cast<BasicExpression *>(BE)->deallocateOperands(ArgRecycler);
|
|
|
|
ExpressionAllocator.Deallocate(E);
|
|
|
|
}
|
|
|
|
|
2017-04-14 10:53:37 +08:00
|
|
|
PHIExpression *NewGVN::createPHIExpression(Instruction *I, bool &HasBackedge,
|
2017-05-10 00:40:04 +08:00
|
|
|
bool &AllConstant) const {
|
2017-01-07 08:01:42 +08:00
|
|
|
BasicBlock *PHIBlock = I->getParent();
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *PN = cast<PHINode>(I);
|
2017-01-07 08:01:42 +08:00
|
|
|
auto *E =
|
|
|
|
new (ExpressionAllocator) PHIExpression(PN->getNumOperands(), PHIBlock);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
E->allocateOperands(ArgRecycler, ExpressionAllocator);
|
|
|
|
E->setType(I->getType());
|
|
|
|
E->setOpcode(I->getOpcode());
|
2016-12-27 03:57:25 +08:00
|
|
|
|
2017-04-14 10:53:37 +08:00
|
|
|
unsigned PHIRPO = RPOOrdering.lookup(DT->getNode(PHIBlock));
|
|
|
|
|
2017-05-10 00:58:28 +08:00
|
|
|
// NewGVN assumes the operands of a PHI node are in a consistent order across
|
|
|
|
// PHIs. LLVM doesn't seem to always guarantee this. While we need to fix
|
|
|
|
// this in LLVM at some point we don't want GVN to find wrong congruences.
|
|
|
|
// Therefore, here we sort uses in predecessor order.
|
2017-05-10 02:29:37 +08:00
|
|
|
// We're sorting the values by pointer. In theory this might be cause of
|
|
|
|
// non-determinism, but here we don't rely on the ordering for anything
|
|
|
|
// significant, e.g. we don't create new instructions based on it so we're
|
|
|
|
// fine.
|
2017-05-10 00:58:28 +08:00
|
|
|
SmallVector<const Use *, 4> PHIOperands;
|
|
|
|
for (const Use &U : PN->operands())
|
|
|
|
PHIOperands.push_back(&U);
|
|
|
|
std::sort(PHIOperands.begin(), PHIOperands.end(),
|
|
|
|
[&](const Use *U1, const Use *U2) {
|
|
|
|
return PN->getIncomingBlock(*U1) < PN->getIncomingBlock(*U2);
|
|
|
|
});
|
|
|
|
|
2017-01-26 07:37:49 +08:00
|
|
|
// Filter out unreachable phi operands.
|
2017-05-10 00:58:28 +08:00
|
|
|
auto Filtered = make_filter_range(PHIOperands, [&](const Use *U) {
|
|
|
|
return ReachableEdges.count({PN->getIncomingBlock(*U), PHIBlock});
|
2017-01-26 07:37:49 +08:00
|
|
|
});
|
2016-12-27 03:57:25 +08:00
|
|
|
|
|
|
|
std::transform(Filtered.begin(), Filtered.end(), op_inserter(E),
|
2017-05-10 00:58:28 +08:00
|
|
|
[&](const Use *U) -> Value * {
|
|
|
|
auto *BB = PN->getIncomingBlock(*U);
|
2017-04-14 10:53:37 +08:00
|
|
|
auto *DTN = DT->getNode(BB);
|
|
|
|
if (RPOOrdering.lookup(DTN) >= PHIRPO)
|
|
|
|
HasBackedge = true;
|
2017-05-10 00:58:28 +08:00
|
|
|
AllConstant &= isa<UndefValue>(*U) || isa<Constant>(*U);
|
2017-04-14 10:53:37 +08:00
|
|
|
|
2017-01-07 08:01:42 +08:00
|
|
|
// Don't try to transform self-defined phis.
|
2017-05-10 00:58:28 +08:00
|
|
|
if (*U == PN)
|
2016-12-27 03:57:25 +08:00
|
|
|
return PN;
|
2017-05-10 00:58:28 +08:00
|
|
|
return lookupOperandLeader(*U);
|
2016-12-27 03:57:25 +08:00
|
|
|
});
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set basic expression info (Arguments, type, opcode) for Expression
|
|
|
|
// E from Instruction I in block B.
|
2017-05-10 00:40:04 +08:00
|
|
|
bool NewGVN::setBasicExpressionInfo(Instruction *I, BasicExpression *E) const {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
bool AllConstant = true;
|
|
|
|
if (auto *GEP = dyn_cast<GetElementPtrInst>(I))
|
|
|
|
E->setType(GEP->getSourceElementType());
|
|
|
|
else
|
|
|
|
E->setType(I->getType());
|
|
|
|
E->setOpcode(I->getOpcode());
|
|
|
|
E->allocateOperands(ArgRecycler, ExpressionAllocator);
|
|
|
|
|
2016-12-27 03:57:25 +08:00
|
|
|
// Transform the operand array into an operand leader array, and keep track of
|
|
|
|
// whether all members are constant.
|
|
|
|
std::transform(I->op_begin(), I->op_end(), op_inserter(E), [&](Value *O) {
|
2017-02-01 06:31:53 +08:00
|
|
|
auto Operand = lookupOperandLeader(O);
|
2016-12-27 03:57:25 +08:00
|
|
|
AllConstant &= isa<Constant>(Operand);
|
|
|
|
return Operand;
|
|
|
|
});
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return AllConstant;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Expression *NewGVN::createBinaryExpression(unsigned Opcode, Type *T,
|
2017-05-10 00:40:04 +08:00
|
|
|
Value *Arg1,
|
|
|
|
Value *Arg2) const {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *E = new (ExpressionAllocator) BasicExpression(2);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
E->setType(T);
|
|
|
|
E->setOpcode(Opcode);
|
|
|
|
E->allocateOperands(ArgRecycler, ExpressionAllocator);
|
|
|
|
if (Instruction::isCommutative(Opcode)) {
|
|
|
|
// Ensure that commutative instructions that only differ by a permutation
|
|
|
|
// of their operands get the same value number by sorting the operand value
|
|
|
|
// numbers. Since all commutative instructions have two operands it is more
|
|
|
|
// efficient to sort by hand rather than using, say, std::sort.
|
2017-02-11 23:07:01 +08:00
|
|
|
if (shouldSwapOperands(Arg1, Arg2))
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
std::swap(Arg1, Arg2);
|
|
|
|
}
|
2017-02-01 06:31:53 +08:00
|
|
|
E->op_push_back(lookupOperandLeader(Arg1));
|
|
|
|
E->op_push_back(lookupOperandLeader(Arg2));
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2017-04-27 04:56:14 +08:00
|
|
|
Value *V = SimplifyBinOp(Opcode, E->getOperand(0), E->getOperand(1), SQ);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, nullptr, V))
|
|
|
|
return SimplifiedE;
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Take a Value returned by simplification of Expression E/Instruction
|
|
|
|
// I, and see if it resulted in a simpler expression. If so, return
|
|
|
|
// that expression.
|
|
|
|
// TODO: Once finished, this should not take an Instruction, we only
|
|
|
|
// use it for printing.
|
|
|
|
const Expression *NewGVN::checkSimplificationResults(Expression *E,
|
2017-05-10 00:40:04 +08:00
|
|
|
Instruction *I,
|
|
|
|
Value *V) const {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (!V)
|
|
|
|
return nullptr;
|
|
|
|
if (auto *C = dyn_cast<Constant>(V)) {
|
|
|
|
if (I)
|
|
|
|
DEBUG(dbgs() << "Simplified " << *I << " to "
|
|
|
|
<< " constant " << *C << "\n");
|
|
|
|
NumGVNOpsSimplified++;
|
|
|
|
assert(isa<BasicExpression>(E) &&
|
|
|
|
"We should always have had a basic expression here");
|
2017-03-24 14:33:48 +08:00
|
|
|
deleteExpression(E);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return createConstantExpression(C);
|
|
|
|
} else if (isa<Argument>(V) || isa<GlobalVariable>(V)) {
|
|
|
|
if (I)
|
|
|
|
DEBUG(dbgs() << "Simplified " << *I << " to "
|
|
|
|
<< " variable " << *V << "\n");
|
2017-03-24 14:33:48 +08:00
|
|
|
deleteExpression(E);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return createVariableExpression(V);
|
|
|
|
}
|
|
|
|
|
|
|
|
CongruenceClass *CC = ValueToClass.lookup(V);
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC && CC->getDefiningExpr()) {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (I)
|
|
|
|
DEBUG(dbgs() << "Simplified " << *I << " to "
|
|
|
|
<< " expression " << *V << "\n");
|
|
|
|
NumGVNOpsSimplified++;
|
2017-03-24 14:33:48 +08:00
|
|
|
deleteExpression(E);
|
2017-04-08 02:38:09 +08:00
|
|
|
return CC->getDefiningExpr();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *NewGVN::createExpression(Instruction *I) const {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *E = new (ExpressionAllocator) BasicExpression(I->getNumOperands());
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2017-02-01 06:32:03 +08:00
|
|
|
bool AllConstant = setBasicExpressionInfo(I, E);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
if (I->isCommutative()) {
|
|
|
|
// Ensure that commutative instructions that only differ by a permutation
|
|
|
|
// of their operands get the same value number by sorting the operand value
|
|
|
|
// numbers. Since all commutative instructions have two operands it is more
|
|
|
|
// efficient to sort by hand rather than using, say, std::sort.
|
|
|
|
assert(I->getNumOperands() == 2 && "Unsupported commutative instruction!");
|
2017-02-13 07:24:42 +08:00
|
|
|
if (shouldSwapOperands(E->getOperand(0), E->getOperand(1)))
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
E->swapOperands(0, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Perform simplificaiton
|
|
|
|
// TODO: Right now we only check to see if we get a constant result.
|
|
|
|
// We may get a less than constant, but still better, result for
|
|
|
|
// some operations.
|
|
|
|
// IE
|
|
|
|
// add 0, x -> x
|
|
|
|
// and x, x -> x
|
|
|
|
// We should handle this by simply rewriting the expression.
|
|
|
|
if (auto *CI = dyn_cast<CmpInst>(I)) {
|
|
|
|
// Sort the operand value numbers so x<y and y>x get the same value
|
|
|
|
// number.
|
|
|
|
CmpInst::Predicate Predicate = CI->getPredicate();
|
2017-02-11 23:07:01 +08:00
|
|
|
if (shouldSwapOperands(E->getOperand(0), E->getOperand(1))) {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
E->swapOperands(0, 1);
|
|
|
|
Predicate = CmpInst::getSwappedPredicate(Predicate);
|
|
|
|
}
|
|
|
|
E->setOpcode((CI->getOpcode() << 8) | Predicate);
|
|
|
|
// TODO: 25% of our time is spent in SimplifyCmpInst with pointer operands
|
|
|
|
assert(I->getOperand(0)->getType() == I->getOperand(1)->getType() &&
|
|
|
|
"Wrong types on cmp instruction");
|
2017-02-01 06:32:03 +08:00
|
|
|
assert((E->getOperand(0)->getType() == I->getOperand(0)->getType() &&
|
|
|
|
E->getOperand(1)->getType() == I->getOperand(1)->getType()));
|
2017-04-27 04:56:14 +08:00
|
|
|
Value *V =
|
|
|
|
SimplifyCmpInst(Predicate, E->getOperand(0), E->getOperand(1), SQ);
|
2017-02-01 06:32:01 +08:00
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V))
|
|
|
|
return SimplifiedE;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
} else if (isa<SelectInst>(I)) {
|
|
|
|
if (isa<Constant>(E->getOperand(0)) ||
|
2017-02-01 06:32:03 +08:00
|
|
|
E->getOperand(0) == E->getOperand(1)) {
|
|
|
|
assert(E->getOperand(1)->getType() == I->getOperand(1)->getType() &&
|
|
|
|
E->getOperand(2)->getType() == I->getOperand(2)->getType());
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
Value *V = SimplifySelectInst(E->getOperand(0), E->getOperand(1),
|
2017-04-27 04:56:14 +08:00
|
|
|
E->getOperand(2), SQ);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V))
|
|
|
|
return SimplifiedE;
|
|
|
|
}
|
|
|
|
} else if (I->isBinaryOp()) {
|
2017-04-27 04:56:14 +08:00
|
|
|
Value *V =
|
|
|
|
SimplifyBinOp(E->getOpcode(), E->getOperand(0), E->getOperand(1), SQ);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V))
|
|
|
|
return SimplifiedE;
|
|
|
|
} else if (auto *BI = dyn_cast<BitCastInst>(I)) {
|
2017-04-29 03:55:38 +08:00
|
|
|
Value *V =
|
|
|
|
SimplifyCastInst(BI->getOpcode(), BI->getOperand(0), BI->getType(), SQ);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V))
|
|
|
|
return SimplifiedE;
|
|
|
|
} else if (isa<GetElementPtrInst>(I)) {
|
2017-04-27 04:56:14 +08:00
|
|
|
Value *V = SimplifyGEPInst(
|
|
|
|
E->getType(), ArrayRef<Value *>(E->op_begin(), E->op_end()), SQ);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V))
|
|
|
|
return SimplifiedE;
|
|
|
|
} else if (AllConstant) {
|
|
|
|
// We don't bother trying to simplify unless all of the operands
|
|
|
|
// were constant.
|
|
|
|
// TODO: There are a lot of Simplify*'s we could call here, if we
|
|
|
|
// wanted to. The original motivating case for this code was a
|
|
|
|
// zext i1 false to i8, which we don't have an interface to
|
|
|
|
// simplify (IE there is no SimplifyZExt).
|
|
|
|
|
|
|
|
SmallVector<Constant *, 8> C;
|
|
|
|
for (Value *Arg : E->operands())
|
2016-12-29 07:24:02 +08:00
|
|
|
C.emplace_back(cast<Constant>(Arg));
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2017-03-12 12:46:45 +08:00
|
|
|
if (Value *V = ConstantFoldInstOperands(I, C, DL, TLI))
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V))
|
|
|
|
return SimplifiedE;
|
|
|
|
}
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
|
|
|
const AggregateValueExpression *
|
2017-05-10 00:40:04 +08:00
|
|
|
NewGVN::createAggregateValueExpression(Instruction *I) const {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (auto *II = dyn_cast<InsertValueInst>(I)) {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *E = new (ExpressionAllocator)
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
AggregateValueExpression(I->getNumOperands(), II->getNumIndices());
|
2017-02-01 06:32:03 +08:00
|
|
|
setBasicExpressionInfo(I, E);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
E->allocateIntOperands(ExpressionAllocator);
|
2016-12-27 03:57:25 +08:00
|
|
|
std::copy(II->idx_begin(), II->idx_end(), int_op_inserter(E));
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return E;
|
|
|
|
} else if (auto *EI = dyn_cast<ExtractValueInst>(I)) {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *E = new (ExpressionAllocator)
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
AggregateValueExpression(I->getNumOperands(), EI->getNumIndices());
|
2017-02-01 06:32:03 +08:00
|
|
|
setBasicExpressionInfo(EI, E);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
E->allocateIntOperands(ExpressionAllocator);
|
2016-12-27 03:57:25 +08:00
|
|
|
std::copy(EI->idx_begin(), EI->idx_end(), int_op_inserter(E));
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
llvm_unreachable("Unhandled type of aggregate value operation");
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const VariableExpression *NewGVN::createVariableExpression(Value *V) const {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *E = new (ExpressionAllocator) VariableExpression(V);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
E->setOpcode(V->getValueID());
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *NewGVN::createVariableOrConstant(Value *V) const {
|
2017-02-19 07:06:50 +08:00
|
|
|
if (auto *C = dyn_cast<Constant>(V))
|
|
|
|
return createConstantExpression(C);
|
|
|
|
return createVariableExpression(V);
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const ConstantExpression *NewGVN::createConstantExpression(Constant *C) const {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *E = new (ExpressionAllocator) ConstantExpression(C);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
E->setOpcode(C->getValueID());
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const UnknownExpression *NewGVN::createUnknownExpression(Instruction *I) const {
|
2017-01-03 02:00:53 +08:00
|
|
|
auto *E = new (ExpressionAllocator) UnknownExpression(I);
|
|
|
|
E->setOpcode(I->getOpcode());
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const CallExpression *
|
|
|
|
NewGVN::createCallExpression(CallInst *CI, const MemoryAccess *MA) const {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// FIXME: Add operand bundles for calls.
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *E =
|
2017-04-07 02:52:50 +08:00
|
|
|
new (ExpressionAllocator) CallExpression(CI->getNumOperands(), CI, MA);
|
2017-02-01 06:32:03 +08:00
|
|
|
setBasicExpressionInfo(CI, E);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2017-03-24 13:30:34 +08:00
|
|
|
// Return true if some equivalent of instruction Inst dominates instruction U.
|
|
|
|
bool NewGVN::someEquivalentDominates(const Instruction *Inst,
|
|
|
|
const Instruction *U) const {
|
|
|
|
auto *CC = ValueToClass.lookup(Inst);
|
2017-03-24 14:33:51 +08:00
|
|
|
// This must be an instruction because we are only called from phi nodes
|
|
|
|
// in the case that the value it needs to check against is an instruction.
|
|
|
|
|
|
|
|
// The most likely candiates for dominance are the leader and the next leader.
|
|
|
|
// The leader or nextleader will dominate in all cases where there is an
|
|
|
|
// equivalent that is higher up in the dom tree.
|
|
|
|
// We can't *only* check them, however, because the
|
|
|
|
// dominator tree could have an infinite number of non-dominating siblings
|
|
|
|
// with instructions that are in the right congruence class.
|
|
|
|
// A
|
|
|
|
// B C D E F G
|
|
|
|
// |
|
|
|
|
// H
|
|
|
|
// Instruction U could be in H, with equivalents in every other sibling.
|
|
|
|
// Depending on the rpo order picked, the leader could be the equivalent in
|
|
|
|
// any of these siblings.
|
|
|
|
if (!CC)
|
|
|
|
return false;
|
2017-04-08 02:38:09 +08:00
|
|
|
if (DT->dominates(cast<Instruction>(CC->getLeader()), U))
|
2017-03-24 14:33:51 +08:00
|
|
|
return true;
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC->getNextLeader().first &&
|
|
|
|
DT->dominates(cast<Instruction>(CC->getNextLeader().first), U))
|
2017-03-24 14:33:51 +08:00
|
|
|
return true;
|
2017-04-08 02:38:09 +08:00
|
|
|
return llvm::any_of(*CC, [&](const Value *Member) {
|
|
|
|
return Member != CC->getLeader() &&
|
2017-03-24 14:33:51 +08:00
|
|
|
DT->dominates(cast<Instruction>(Member), U);
|
|
|
|
});
|
2017-03-24 13:30:34 +08:00
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// See if we have a congruence class and leader for this operand, and if so,
|
|
|
|
// return it. Otherwise, return the operand itself.
|
2017-02-01 06:31:53 +08:00
|
|
|
Value *NewGVN::lookupOperandLeader(Value *V) const {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
CongruenceClass *CC = ValueToClass.lookup(V);
|
2017-02-11 20:48:50 +08:00
|
|
|
if (CC) {
|
2017-03-11 03:05:04 +08:00
|
|
|
// Everything in TOP is represneted by undef, as it can be any value.
|
2017-02-11 20:48:50 +08:00
|
|
|
// We do have to make sure we get the type right though, so we can't set the
|
|
|
|
// RepLeader to undef.
|
2017-03-11 03:05:04 +08:00
|
|
|
if (CC == TOPClass)
|
2017-02-11 20:48:50 +08:00
|
|
|
return UndefValue::get(V->getType());
|
2017-04-08 02:38:09 +08:00
|
|
|
return CC->getStoredValue() ? CC->getStoredValue() : CC->getLeader();
|
2017-02-11 20:48:50 +08:00
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return V;
|
|
|
|
}
|
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
const MemoryAccess *NewGVN::lookupMemoryLeader(const MemoryAccess *MA) const {
|
|
|
|
auto *CC = getMemoryClass(MA);
|
2017-04-08 02:38:09 +08:00
|
|
|
assert(CC->getMemoryLeader() &&
|
2017-05-12 23:25:56 +08:00
|
|
|
"Every MemoryAccess should be mapped to a congruence class with a "
|
|
|
|
"representative memory access");
|
2017-04-08 02:38:09 +08:00
|
|
|
return CC->getMemoryLeader();
|
2016-12-26 06:23:49 +08:00
|
|
|
}
|
|
|
|
|
2017-01-27 10:37:11 +08:00
|
|
|
// Return true if the MemoryAccess is really equivalent to everything. This is
|
|
|
|
// equivalent to the lattice value "TOP" in most lattices. This is the initial
|
2017-04-07 02:52:50 +08:00
|
|
|
// state of all MemoryAccesses.
|
2017-01-27 10:37:11 +08:00
|
|
|
bool NewGVN::isMemoryAccessTop(const MemoryAccess *MA) const {
|
2017-04-07 02:52:50 +08:00
|
|
|
return getMemoryClass(MA) == TOPClass;
|
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
LoadExpression *NewGVN::createLoadExpression(Type *LoadType, Value *PointerOp,
|
2017-04-07 02:52:50 +08:00
|
|
|
LoadInst *LI,
|
2017-05-10 00:40:04 +08:00
|
|
|
const MemoryAccess *MA) const {
|
2017-04-07 02:52:50 +08:00
|
|
|
auto *E =
|
|
|
|
new (ExpressionAllocator) LoadExpression(1, LI, lookupMemoryLeader(MA));
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
E->allocateOperands(ArgRecycler, ExpressionAllocator);
|
|
|
|
E->setType(LoadType);
|
|
|
|
|
|
|
|
// Give store and loads same opcode so they value number together.
|
|
|
|
E->setOpcode(0);
|
2017-04-07 02:52:50 +08:00
|
|
|
E->op_push_back(PointerOp);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (LI)
|
|
|
|
E->setAlignment(LI->getAlignment());
|
|
|
|
|
|
|
|
// TODO: Value number heap versions. We may be able to discover
|
|
|
|
// things alias analysis can't on it's own (IE that a store and a
|
|
|
|
// load have the same value, and thus, it isn't clobbering the load).
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const StoreExpression *
|
|
|
|
NewGVN::createStoreExpression(StoreInst *SI, const MemoryAccess *MA) const {
|
2017-02-01 06:31:53 +08:00
|
|
|
auto *StoredValueLeader = lookupOperandLeader(SI->getValueOperand());
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
auto *E = new (ExpressionAllocator)
|
2017-04-07 02:52:50 +08:00
|
|
|
StoreExpression(SI->getNumOperands(), SI, StoredValueLeader, MA);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
E->allocateOperands(ArgRecycler, ExpressionAllocator);
|
|
|
|
E->setType(SI->getValueOperand()->getType());
|
|
|
|
|
|
|
|
// Give store and loads same opcode so they value number together.
|
|
|
|
E->setOpcode(0);
|
2017-02-01 06:31:53 +08:00
|
|
|
E->op_push_back(lookupOperandLeader(SI->getPointerOperand()));
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// TODO: Value number heap versions. We may be able to discover
|
|
|
|
// things alias analysis can't on it's own (IE that a store and a
|
|
|
|
// load have the same value, and thus, it isn't clobbering the load).
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *NewGVN::performSymbolicStoreEvaluation(Instruction *I) const {
|
2017-01-03 02:00:46 +08:00
|
|
|
// Unlike loads, we never try to eliminate stores, so we do not check if they
|
|
|
|
// are simple and avoid value numbering them.
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *SI = cast<StoreInst>(I);
|
2017-04-07 02:52:50 +08:00
|
|
|
auto *StoreAccess = MSSA->getMemoryAccess(SI);
|
2017-01-27 10:37:11 +08:00
|
|
|
// Get the expression, if any, for the RHS of the MemoryDef.
|
2017-04-07 02:52:50 +08:00
|
|
|
const MemoryAccess *StoreRHS = StoreAccess->getDefiningAccess();
|
|
|
|
if (EnableStoreRefinement)
|
|
|
|
StoreRHS = MSSAWalker->getClobberingMemoryAccess(StoreAccess);
|
|
|
|
// If we bypassed the use-def chains, make sure we add a use.
|
|
|
|
if (StoreRHS != StoreAccess->getDefiningAccess())
|
|
|
|
addMemoryUsers(StoreRHS, StoreAccess);
|
|
|
|
|
|
|
|
StoreRHS = lookupMemoryLeader(StoreRHS);
|
2017-01-27 10:37:11 +08:00
|
|
|
// If we are defined by ourselves, use the live on entry def.
|
|
|
|
if (StoreRHS == StoreAccess)
|
|
|
|
StoreRHS = MSSA->getLiveOnEntryDef();
|
|
|
|
|
2017-01-03 02:00:46 +08:00
|
|
|
if (SI->isSimple()) {
|
2017-01-27 10:37:11 +08:00
|
|
|
// See if we are defined by a previous store expression, it already has a
|
|
|
|
// value, and it's the same value as our current store. FIXME: Right now, we
|
|
|
|
// only do this for simple stores, we should expand to cover memcpys, etc.
|
2017-04-07 02:52:50 +08:00
|
|
|
const auto *LastStore = createStoreExpression(SI, StoreRHS);
|
|
|
|
const auto *LastCC = ExpressionToClass.lookup(LastStore);
|
2017-01-09 13:34:29 +08:00
|
|
|
// Basically, check if the congruence class the store is in is defined by a
|
|
|
|
// store that isn't us, and has the same value. MemorySSA takes care of
|
|
|
|
// ensuring the store has the same memory state as us already.
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
// The RepStoredValue gets nulled if all the stores disappear in a class, so
|
|
|
|
// we don't need to check if the class contains a store besides us.
|
2017-04-07 02:52:50 +08:00
|
|
|
if (LastCC &&
|
2017-04-08 02:38:09 +08:00
|
|
|
LastCC->getStoredValue() == lookupOperandLeader(SI->getValueOperand()))
|
2017-04-07 02:52:50 +08:00
|
|
|
return LastStore;
|
|
|
|
deleteExpression(LastStore);
|
2017-01-27 10:37:11 +08:00
|
|
|
// Also check if our value operand is defined by a load of the same memory
|
2017-04-07 02:52:50 +08:00
|
|
|
// location, and the memory state is the same as it was then (otherwise, it
|
|
|
|
// could have been overwritten later. See test32 in
|
|
|
|
// transforms/DeadStoreElimination/simple.ll).
|
|
|
|
if (auto *LI =
|
|
|
|
dyn_cast<LoadInst>(lookupOperandLeader(SI->getValueOperand()))) {
|
2017-02-01 06:31:53 +08:00
|
|
|
if ((lookupOperandLeader(LI->getPointerOperand()) ==
|
|
|
|
lookupOperandLeader(SI->getPointerOperand())) &&
|
2017-04-07 02:52:50 +08:00
|
|
|
(lookupMemoryLeader(MSSA->getMemoryAccess(LI)->getDefiningAccess()) ==
|
|
|
|
StoreRHS))
|
2017-01-27 10:37:11 +08:00
|
|
|
return createVariableExpression(LI);
|
|
|
|
}
|
2016-12-26 06:23:49 +08:00
|
|
|
}
|
2017-04-07 02:52:50 +08:00
|
|
|
|
|
|
|
// If the store is not equivalent to anything, value number it as a store that
|
|
|
|
// produces a unique memory state (instead of using it's MemoryUse, we use
|
|
|
|
// it's MemoryDef).
|
2017-02-01 06:32:03 +08:00
|
|
|
return createStoreExpression(SI, StoreAccess);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
2017-04-02 21:23:44 +08:00
|
|
|
// See if we can extract the value of a loaded pointer from a load, a store, or
|
|
|
|
// a memory instruction.
|
|
|
|
const Expression *
|
|
|
|
NewGVN::performSymbolicLoadCoercion(Type *LoadType, Value *LoadPtr,
|
|
|
|
LoadInst *LI, Instruction *DepInst,
|
2017-05-10 00:40:04 +08:00
|
|
|
MemoryAccess *DefiningAccess) const {
|
2017-04-02 21:23:44 +08:00
|
|
|
assert((!LI || LI->isSimple()) && "Not a simple load");
|
|
|
|
if (auto *DepSI = dyn_cast<StoreInst>(DepInst)) {
|
|
|
|
// Can't forward from non-atomic to atomic without violating memory model.
|
|
|
|
// Also don't need to coerce if they are the same type, we will just
|
|
|
|
// propogate..
|
|
|
|
if (LI->isAtomic() > DepSI->isAtomic() ||
|
|
|
|
LoadType == DepSI->getValueOperand()->getType())
|
|
|
|
return nullptr;
|
|
|
|
int Offset = analyzeLoadFromClobberingStore(LoadType, LoadPtr, DepSI, DL);
|
|
|
|
if (Offset >= 0) {
|
|
|
|
if (auto *C = dyn_cast<Constant>(
|
|
|
|
lookupOperandLeader(DepSI->getValueOperand()))) {
|
|
|
|
DEBUG(dbgs() << "Coercing load from store " << *DepSI << " to constant "
|
|
|
|
<< *C << "\n");
|
|
|
|
return createConstantExpression(
|
|
|
|
getConstantStoreValueForLoad(C, Offset, LoadType, DL));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (LoadInst *DepLI = dyn_cast<LoadInst>(DepInst)) {
|
|
|
|
// Can't forward from non-atomic to atomic without violating memory model.
|
|
|
|
if (LI->isAtomic() > DepLI->isAtomic())
|
|
|
|
return nullptr;
|
|
|
|
int Offset = analyzeLoadFromClobberingLoad(LoadType, LoadPtr, DepLI, DL);
|
|
|
|
if (Offset >= 0) {
|
|
|
|
// We can coerce a constant load into a load
|
|
|
|
if (auto *C = dyn_cast<Constant>(lookupOperandLeader(DepLI)))
|
|
|
|
if (auto *PossibleConstant =
|
|
|
|
getConstantLoadValueForLoad(C, Offset, LoadType, DL)) {
|
|
|
|
DEBUG(dbgs() << "Coercing load from load " << *LI << " to constant "
|
|
|
|
<< *PossibleConstant << "\n");
|
|
|
|
return createConstantExpression(PossibleConstant);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (MemIntrinsic *DepMI = dyn_cast<MemIntrinsic>(DepInst)) {
|
|
|
|
int Offset = analyzeLoadFromClobberingMemInst(LoadType, LoadPtr, DepMI, DL);
|
|
|
|
if (Offset >= 0) {
|
|
|
|
if (auto *PossibleConstant =
|
|
|
|
getConstantMemInstValueForLoad(DepMI, Offset, LoadType, DL)) {
|
|
|
|
DEBUG(dbgs() << "Coercing load from meminst " << *DepMI
|
|
|
|
<< " to constant " << *PossibleConstant << "\n");
|
|
|
|
return createConstantExpression(PossibleConstant);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// All of the below are only true if the loaded pointer is produced
|
|
|
|
// by the dependent instruction.
|
|
|
|
if (LoadPtr != lookupOperandLeader(DepInst) &&
|
|
|
|
!AA->isMustAlias(LoadPtr, DepInst))
|
|
|
|
return nullptr;
|
|
|
|
// If this load really doesn't depend on anything, then we must be loading an
|
|
|
|
// undef value. This can happen when loading for a fresh allocation with no
|
|
|
|
// intervening stores, for example. Note that this is only true in the case
|
|
|
|
// that the result of the allocation is pointer equal to the load ptr.
|
|
|
|
if (isa<AllocaInst>(DepInst) || isMallocLikeFn(DepInst, TLI)) {
|
|
|
|
return createConstantExpression(UndefValue::get(LoadType));
|
|
|
|
}
|
|
|
|
// If this load occurs either right after a lifetime begin,
|
|
|
|
// then the loaded value is undefined.
|
|
|
|
else if (auto *II = dyn_cast<IntrinsicInst>(DepInst)) {
|
|
|
|
if (II->getIntrinsicID() == Intrinsic::lifetime_start)
|
|
|
|
return createConstantExpression(UndefValue::get(LoadType));
|
|
|
|
}
|
|
|
|
// If this load follows a calloc (which zero initializes memory),
|
|
|
|
// then the loaded value is zero
|
|
|
|
else if (isCallocLikeFn(DepInst, TLI)) {
|
|
|
|
return createConstantExpression(Constant::getNullValue(LoadType));
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *NewGVN::performSymbolicLoadEvaluation(Instruction *I) const {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *LI = cast<LoadInst>(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// We can eliminate in favor of non-simple loads, but we won't be able to
|
2017-01-03 02:00:46 +08:00
|
|
|
// eliminate the loads themselves.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (!LI->isSimple())
|
|
|
|
return nullptr;
|
|
|
|
|
2017-02-01 06:31:53 +08:00
|
|
|
Value *LoadAddressLeader = lookupOperandLeader(LI->getPointerOperand());
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Load of undef is undef.
|
|
|
|
if (isa<UndefValue>(LoadAddressLeader))
|
|
|
|
return createConstantExpression(UndefValue::get(LI->getType()));
|
|
|
|
|
|
|
|
MemoryAccess *DefiningAccess = MSSAWalker->getClobberingMemoryAccess(I);
|
|
|
|
|
|
|
|
if (!MSSA->isLiveOnEntryDef(DefiningAccess)) {
|
|
|
|
if (auto *MD = dyn_cast<MemoryDef>(DefiningAccess)) {
|
|
|
|
Instruction *DefiningInst = MD->getMemoryInst();
|
|
|
|
// If the defining instruction is not reachable, replace with undef.
|
|
|
|
if (!ReachableBlocks.count(DefiningInst->getParent()))
|
|
|
|
return createConstantExpression(UndefValue::get(LI->getType()));
|
2017-04-02 21:23:44 +08:00
|
|
|
// This will handle stores and memory insts. We only do if it the
|
|
|
|
// defining access has a different type, or it is a pointer produced by
|
|
|
|
// certain memory operations that cause the memory to have a fixed value
|
|
|
|
// (IE things like calloc).
|
2017-04-07 02:52:53 +08:00
|
|
|
if (const auto *CoercionResult =
|
|
|
|
performSymbolicLoadCoercion(LI->getType(), LoadAddressLeader, LI,
|
|
|
|
DefiningInst, DefiningAccess))
|
2017-04-02 21:23:44 +08:00
|
|
|
return CoercionResult;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
const Expression *E = createLoadExpression(LI->getType(), LoadAddressLeader,
|
|
|
|
LI, DefiningAccess);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2017-02-19 07:06:50 +08:00
|
|
|
const Expression *
|
2017-05-10 00:40:04 +08:00
|
|
|
NewGVN::performSymbolicPredicateInfoEvaluation(Instruction *I) const {
|
2017-02-19 07:06:50 +08:00
|
|
|
auto *PI = PredInfo->getPredicateInfoFor(I);
|
|
|
|
if (!PI)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
DEBUG(dbgs() << "Found predicate info from instruction !\n");
|
2017-02-23 06:20:58 +08:00
|
|
|
|
|
|
|
auto *PWC = dyn_cast<PredicateWithCondition>(PI);
|
|
|
|
if (!PWC)
|
2017-02-19 07:06:50 +08:00
|
|
|
return nullptr;
|
|
|
|
|
2017-02-23 06:20:58 +08:00
|
|
|
auto *CopyOf = I->getOperand(0);
|
|
|
|
auto *Cond = PWC->Condition;
|
|
|
|
|
2017-02-19 07:06:50 +08:00
|
|
|
// If this a copy of the condition, it must be either true or false depending
|
|
|
|
// on the predicate info type and edge
|
|
|
|
if (CopyOf == Cond) {
|
2017-02-23 06:20:58 +08:00
|
|
|
// We should not need to add predicate users because the predicate info is
|
|
|
|
// already a use of this operand.
|
2017-02-19 07:06:50 +08:00
|
|
|
if (isa<PredicateAssume>(PI))
|
|
|
|
return createConstantExpression(ConstantInt::getTrue(Cond->getType()));
|
|
|
|
if (auto *PBranch = dyn_cast<PredicateBranch>(PI)) {
|
|
|
|
if (PBranch->TrueEdge)
|
|
|
|
return createConstantExpression(ConstantInt::getTrue(Cond->getType()));
|
|
|
|
return createConstantExpression(ConstantInt::getFalse(Cond->getType()));
|
|
|
|
}
|
2017-02-23 06:20:58 +08:00
|
|
|
if (auto *PSwitch = dyn_cast<PredicateSwitch>(PI))
|
|
|
|
return createConstantExpression(cast<Constant>(PSwitch->CaseValue));
|
2017-02-19 07:06:50 +08:00
|
|
|
}
|
2017-02-23 06:20:58 +08:00
|
|
|
|
2017-02-19 07:06:50 +08:00
|
|
|
// Not a copy of the condition, so see what the predicates tell us about this
|
|
|
|
// value. First, though, we check to make sure the value is actually a copy
|
|
|
|
// of one of the condition operands. It's possible, in certain cases, for it
|
|
|
|
// to be a copy of a predicateinfo copy. In particular, if two branch
|
|
|
|
// operations use the same condition, and one branch dominates the other, we
|
|
|
|
// will end up with a copy of a copy. This is currently a small deficiency in
|
2017-02-23 06:20:58 +08:00
|
|
|
// predicateinfo. What will end up happening here is that we will value
|
2017-02-19 07:06:50 +08:00
|
|
|
// number both copies the same anyway.
|
2017-02-23 06:20:58 +08:00
|
|
|
|
|
|
|
// Everything below relies on the condition being a comparison.
|
|
|
|
auto *Cmp = dyn_cast<CmpInst>(Cond);
|
|
|
|
if (!Cmp)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if (CopyOf != Cmp->getOperand(0) && CopyOf != Cmp->getOperand(1)) {
|
2017-05-12 23:28:12 +08:00
|
|
|
DEBUG(dbgs() << "Copy is not of any condition operands!\n");
|
2017-02-19 07:06:50 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
2017-02-23 06:20:58 +08:00
|
|
|
Value *FirstOp = lookupOperandLeader(Cmp->getOperand(0));
|
|
|
|
Value *SecondOp = lookupOperandLeader(Cmp->getOperand(1));
|
2017-02-19 07:06:50 +08:00
|
|
|
bool SwappedOps = false;
|
|
|
|
// Sort the ops
|
|
|
|
if (shouldSwapOperands(FirstOp, SecondOp)) {
|
|
|
|
std::swap(FirstOp, SecondOp);
|
|
|
|
SwappedOps = true;
|
|
|
|
}
|
|
|
|
CmpInst::Predicate Predicate =
|
|
|
|
SwappedOps ? Cmp->getSwappedPredicate() : Cmp->getPredicate();
|
|
|
|
|
|
|
|
if (isa<PredicateAssume>(PI)) {
|
|
|
|
// If the comparison is true when the operands are equal, then we know the
|
|
|
|
// operands are equal, because assumes must always be true.
|
|
|
|
if (CmpInst::isTrueWhenEqual(Predicate)) {
|
|
|
|
addPredicateUsers(PI, I);
|
|
|
|
return createVariableOrConstant(FirstOp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (const auto *PBranch = dyn_cast<PredicateBranch>(PI)) {
|
|
|
|
// If we are *not* a copy of the comparison, we may equal to the other
|
|
|
|
// operand when the predicate implies something about equality of
|
|
|
|
// operations. In particular, if the comparison is true/false when the
|
|
|
|
// operands are equal, and we are on the right edge, we know this operation
|
|
|
|
// is equal to something.
|
|
|
|
if ((PBranch->TrueEdge && Predicate == CmpInst::ICMP_EQ) ||
|
|
|
|
(!PBranch->TrueEdge && Predicate == CmpInst::ICMP_NE)) {
|
|
|
|
addPredicateUsers(PI, I);
|
|
|
|
return createVariableOrConstant(FirstOp);
|
|
|
|
}
|
|
|
|
// Handle the special case of floating point.
|
|
|
|
if (((PBranch->TrueEdge && Predicate == CmpInst::FCMP_OEQ) ||
|
|
|
|
(!PBranch->TrueEdge && Predicate == CmpInst::FCMP_UNE)) &&
|
|
|
|
isa<ConstantFP>(FirstOp) && !cast<ConstantFP>(FirstOp)->isZero()) {
|
|
|
|
addPredicateUsers(PI, I);
|
|
|
|
return createConstantExpression(cast<Constant>(FirstOp));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Evaluate read only and pure calls, and create an expression result.
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *NewGVN::performSymbolicCallEvaluation(Instruction *I) const {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *CI = cast<CallInst>(I);
|
2017-02-19 07:06:50 +08:00
|
|
|
if (auto *II = dyn_cast<IntrinsicInst>(I)) {
|
|
|
|
// Instrinsics with the returned attribute are copies of arguments.
|
|
|
|
if (auto *ReturnedValue = II->getReturnedArgOperand()) {
|
|
|
|
if (II->getIntrinsicID() == Intrinsic::ssa_copy)
|
|
|
|
if (const auto *Result = performSymbolicPredicateInfoEvaluation(I))
|
|
|
|
return Result;
|
|
|
|
return createVariableOrConstant(ReturnedValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (AA->doesNotAccessMemory(CI)) {
|
2017-04-08 02:38:09 +08:00
|
|
|
return createCallExpression(CI, TOPClass->getMemoryLeader());
|
2017-02-19 07:06:50 +08:00
|
|
|
} else if (AA->onlyReadsMemory(CI)) {
|
2016-12-27 03:57:25 +08:00
|
|
|
MemoryAccess *DefiningAccess = MSSAWalker->getClobberingMemoryAccess(CI);
|
2017-04-07 02:52:50 +08:00
|
|
|
return createCallExpression(CI, DefiningAccess);
|
2016-12-28 02:15:39 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the MemoryAccess equivalence table to say that From is equal to To,
|
2016-12-26 06:23:49 +08:00
|
|
|
// and return true if this is different from what already existed in the table.
|
2017-04-07 02:52:50 +08:00
|
|
|
bool NewGVN::setMemoryClass(const MemoryAccess *From,
|
|
|
|
CongruenceClass *NewClass) {
|
|
|
|
assert(NewClass &&
|
|
|
|
"Every MemoryAccess should be getting mapped to a non-null class");
|
2017-01-27 06:21:48 +08:00
|
|
|
DEBUG(dbgs() << "Setting " << *From);
|
2017-04-07 02:52:50 +08:00
|
|
|
DEBUG(dbgs() << " equivalent to congruence class ");
|
2017-04-08 02:38:09 +08:00
|
|
|
DEBUG(dbgs() << NewClass->getID() << " with current MemoryAccess leader ");
|
2017-05-10 04:02:48 +08:00
|
|
|
DEBUG(dbgs() << *NewClass->getMemoryLeader() << "\n");
|
2017-01-27 06:21:48 +08:00
|
|
|
|
|
|
|
auto LookupResult = MemoryAccessToClass.find(From);
|
2016-12-26 06:23:49 +08:00
|
|
|
bool Changed = false;
|
|
|
|
// If it's already in the table, see if the value changed.
|
2017-01-27 06:21:48 +08:00
|
|
|
if (LookupResult != MemoryAccessToClass.end()) {
|
2017-04-07 02:52:50 +08:00
|
|
|
auto *OldClass = LookupResult->second;
|
|
|
|
if (OldClass != NewClass) {
|
|
|
|
// If this is a phi, we have to handle memory member updates.
|
|
|
|
if (auto *MP = dyn_cast<MemoryPhi>(From)) {
|
2017-04-08 02:38:09 +08:00
|
|
|
OldClass->memory_erase(MP);
|
|
|
|
NewClass->memory_insert(MP);
|
2017-04-07 02:52:50 +08:00
|
|
|
// This may have killed the class if it had no non-memory members
|
2017-04-08 02:38:09 +08:00
|
|
|
if (OldClass->getMemoryLeader() == From) {
|
2017-05-12 23:22:45 +08:00
|
|
|
if (OldClass->definesNoMemory()) {
|
2017-04-08 02:38:09 +08:00
|
|
|
OldClass->setMemoryLeader(nullptr);
|
2017-04-07 02:52:50 +08:00
|
|
|
} else {
|
2017-04-08 02:38:09 +08:00
|
|
|
OldClass->setMemoryLeader(getNextMemoryLeader(OldClass));
|
2017-04-07 02:52:50 +08:00
|
|
|
DEBUG(dbgs() << "Memory class leader change for class "
|
2017-04-08 02:38:09 +08:00
|
|
|
<< OldClass->getID() << " to "
|
|
|
|
<< *OldClass->getMemoryLeader()
|
2017-04-07 02:52:50 +08:00
|
|
|
<< " due to removal of a memory member " << *From
|
|
|
|
<< "\n");
|
|
|
|
markMemoryLeaderChangeTouched(OldClass);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-12-26 06:23:49 +08:00
|
|
|
// It wasn't equivalent before, and now it is.
|
2017-04-07 02:52:50 +08:00
|
|
|
LookupResult->second = NewClass;
|
2016-12-26 06:23:49 +08:00
|
|
|
Changed = true;
|
|
|
|
}
|
|
|
|
}
|
2017-01-03 02:00:46 +08:00
|
|
|
|
2016-12-26 06:23:49 +08:00
|
|
|
return Changed;
|
|
|
|
}
|
2017-03-24 14:33:48 +08:00
|
|
|
|
2017-04-14 10:53:37 +08:00
|
|
|
// Determine if a phi is cycle-free. That means the values in the phi don't
|
|
|
|
// depend on any expressions that can change value as a result of the phi.
|
|
|
|
// For example, a non-cycle free phi would be v = phi(0, v+1).
|
2017-05-10 00:40:04 +08:00
|
|
|
bool NewGVN::isCycleFree(const PHINode *PN) const {
|
2017-04-14 10:53:37 +08:00
|
|
|
// In order to compute cycle-freeness, we do SCC finding on the phi, and see
|
|
|
|
// what kind of SCC it ends up in. If it is a singleton, it is cycle-free.
|
|
|
|
// If it is not in a singleton, it is only cycle free if the other members are
|
|
|
|
// all phi nodes (as they do not compute anything, they are copies). TODO:
|
|
|
|
// There are likely a few other intrinsics or expressions that could be
|
|
|
|
// included here, but this happens so infrequently already that it is not
|
|
|
|
// likely to be worth it.
|
|
|
|
auto PCS = PhiCycleState.lookup(PN);
|
|
|
|
if (PCS == PCS_Unknown) {
|
|
|
|
SCCFinder.Start(PN);
|
|
|
|
auto &SCC = SCCFinder.getComponentFor(PN);
|
|
|
|
// It's cycle free if it's size 1 or or the SCC is *only* phi nodes.
|
|
|
|
if (SCC.size() == 1)
|
|
|
|
PhiCycleState.insert({PN, PCS_CycleFree});
|
|
|
|
else {
|
|
|
|
bool AllPhis =
|
|
|
|
llvm::all_of(SCC, [](const Value *V) { return isa<PHINode>(V); });
|
|
|
|
PCS = AllPhis ? PCS_CycleFree : PCS_Cycle;
|
|
|
|
for (auto *Member : SCC)
|
|
|
|
if (auto *MemberPhi = dyn_cast<PHINode>(Member))
|
|
|
|
PhiCycleState.insert({MemberPhi, PCS});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (PCS == PCS_Cycle)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Evaluate PHI nodes symbolically, and create an expression result.
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *NewGVN::performSymbolicPHIEvaluation(Instruction *I) const {
|
2017-04-14 10:53:37 +08:00
|
|
|
// True if one of the incoming phi edges is a backedge.
|
|
|
|
bool HasBackedge = false;
|
|
|
|
// All constant tracks the state of whether all the *original* phi operands
|
2017-05-03 05:11:40 +08:00
|
|
|
// were constant. This is really shorthand for "this phi cannot cycle due
|
|
|
|
// to forward propagation", as any change in value of the phi is guaranteed
|
|
|
|
// not to later change the value of the phi.
|
2017-04-14 10:53:37 +08:00
|
|
|
// IE it can't be v = phi(undef, v+1)
|
|
|
|
bool AllConstant = true;
|
2017-05-16 14:06:12 +08:00
|
|
|
auto *E =
|
|
|
|
cast<PHIExpression>(createPHIExpression(I, HasBackedge, AllConstant));
|
2017-01-07 08:01:42 +08:00
|
|
|
// We match the semantics of SimplifyPhiNode from InstructionSimplify here.
|
2017-05-03 05:11:40 +08:00
|
|
|
// See if all arguments are the same.
|
2017-01-07 08:01:42 +08:00
|
|
|
// We track if any were undef because they need special handling.
|
|
|
|
bool HasUndef = false;
|
|
|
|
auto Filtered = make_filter_range(E->operands(), [&](const Value *Arg) {
|
|
|
|
if (Arg == I)
|
|
|
|
return false;
|
|
|
|
if (isa<UndefValue>(Arg)) {
|
|
|
|
HasUndef = true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
// If we are left with no operands, it's undef
|
|
|
|
if (Filtered.begin() == Filtered.end()) {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
DEBUG(dbgs() << "Simplified PHI node " << *I << " to undef"
|
|
|
|
<< "\n");
|
2017-03-24 14:33:48 +08:00
|
|
|
deleteExpression(E);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return createConstantExpression(UndefValue::get(I->getType()));
|
|
|
|
}
|
2017-04-14 10:53:37 +08:00
|
|
|
unsigned NumOps = 0;
|
2017-01-07 08:01:42 +08:00
|
|
|
Value *AllSameValue = *(Filtered.begin());
|
|
|
|
++Filtered.begin();
|
|
|
|
// Can't use std::equal here, sadly, because filter.begin moves.
|
2017-04-14 10:53:37 +08:00
|
|
|
if (llvm::all_of(Filtered, [AllSameValue, &NumOps](const Value *V) {
|
|
|
|
++NumOps;
|
2017-01-07 08:01:42 +08:00
|
|
|
return V == AllSameValue;
|
|
|
|
})) {
|
|
|
|
// In LLVM's non-standard representation of phi nodes, it's possible to have
|
|
|
|
// phi nodes with cycles (IE dependent on other phis that are .... dependent
|
|
|
|
// on the original phi node), especially in weird CFG's where some arguments
|
|
|
|
// are unreachable, or uninitialized along certain paths. This can cause
|
|
|
|
// infinite loops during evaluation. We work around this by not trying to
|
|
|
|
// really evaluate them independently, but instead using a variable
|
|
|
|
// expression to say if one is equivalent to the other.
|
|
|
|
// We also special case undef, so that if we have an undef, we can't use the
|
|
|
|
// common value unless it dominates the phi block.
|
|
|
|
if (HasUndef) {
|
2017-04-14 10:53:37 +08:00
|
|
|
// If we have undef and at least one other value, this is really a
|
|
|
|
// multivalued phi, and we need to know if it's cycle free in order to
|
|
|
|
// evaluate whether we can ignore the undef. The other parts of this are
|
|
|
|
// just shortcuts. If there is no backedge, or all operands are
|
|
|
|
// constants, or all operands are ignored but the undef, it also must be
|
|
|
|
// cycle free.
|
|
|
|
if (!AllConstant && HasBackedge && NumOps > 0 &&
|
|
|
|
!isa<UndefValue>(AllSameValue) && !isCycleFree(cast<PHINode>(I)))
|
|
|
|
return E;
|
|
|
|
|
2017-01-07 08:01:42 +08:00
|
|
|
// Only have to check for instructions
|
2017-01-07 10:05:50 +08:00
|
|
|
if (auto *AllSameInst = dyn_cast<Instruction>(AllSameValue))
|
2017-03-24 13:30:34 +08:00
|
|
|
if (!someEquivalentDominates(AllSameInst, I))
|
2017-01-07 08:01:42 +08:00
|
|
|
return E;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
NumGVNPhisAllSame++;
|
|
|
|
DEBUG(dbgs() << "Simplified PHI node " << *I << " to " << *AllSameValue
|
|
|
|
<< "\n");
|
2017-03-24 14:33:48 +08:00
|
|
|
deleteExpression(E);
|
2017-02-19 07:06:50 +08:00
|
|
|
return createVariableOrConstant(AllSameValue);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *
|
|
|
|
NewGVN::performSymbolicAggrValueEvaluation(Instruction *I) const {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (auto *EI = dyn_cast<ExtractValueInst>(I)) {
|
|
|
|
auto *II = dyn_cast<IntrinsicInst>(EI->getAggregateOperand());
|
|
|
|
if (II && EI->getNumIndices() == 1 && *EI->idx_begin() == 0) {
|
|
|
|
unsigned Opcode = 0;
|
|
|
|
// EI might be an extract from one of our recognised intrinsics. If it
|
|
|
|
// is we'll synthesize a semantically equivalent expression instead on
|
|
|
|
// an extract value expression.
|
|
|
|
switch (II->getIntrinsicID()) {
|
|
|
|
case Intrinsic::sadd_with_overflow:
|
|
|
|
case Intrinsic::uadd_with_overflow:
|
|
|
|
Opcode = Instruction::Add;
|
|
|
|
break;
|
|
|
|
case Intrinsic::ssub_with_overflow:
|
|
|
|
case Intrinsic::usub_with_overflow:
|
|
|
|
Opcode = Instruction::Sub;
|
|
|
|
break;
|
|
|
|
case Intrinsic::smul_with_overflow:
|
|
|
|
case Intrinsic::umul_with_overflow:
|
|
|
|
Opcode = Instruction::Mul;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Opcode != 0) {
|
|
|
|
// Intrinsic recognized. Grab its args to finish building the
|
|
|
|
// expression.
|
|
|
|
assert(II->getNumArgOperands() == 2 &&
|
|
|
|
"Expect two args for recognised intrinsics.");
|
2017-02-11 20:48:50 +08:00
|
|
|
return createBinaryExpression(
|
|
|
|
Opcode, EI->getType(), II->getArgOperand(0), II->getArgOperand(1));
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-01 06:32:03 +08:00
|
|
|
return createAggregateValueExpression(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *NewGVN::performSymbolicCmpEvaluation(Instruction *I) const {
|
2017-02-19 07:06:50 +08:00
|
|
|
auto *CI = dyn_cast<CmpInst>(I);
|
|
|
|
// See if our operands are equal to those of a previous predicate, and if so,
|
|
|
|
// if it implies true or false.
|
2017-02-01 06:31:58 +08:00
|
|
|
auto Op0 = lookupOperandLeader(CI->getOperand(0));
|
|
|
|
auto Op1 = lookupOperandLeader(CI->getOperand(1));
|
2017-02-19 07:06:50 +08:00
|
|
|
auto OurPredicate = CI->getPredicate();
|
2017-03-04 08:44:43 +08:00
|
|
|
if (shouldSwapOperands(Op0, Op1)) {
|
2017-02-19 07:06:50 +08:00
|
|
|
std::swap(Op0, Op1);
|
|
|
|
OurPredicate = CI->getSwappedPredicate();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Avoid processing the same info twice
|
|
|
|
const PredicateBase *LastPredInfo = nullptr;
|
|
|
|
// See if we know something about the comparison itself, like it is the target
|
|
|
|
// of an assume.
|
|
|
|
auto *CmpPI = PredInfo->getPredicateInfoFor(I);
|
|
|
|
if (dyn_cast_or_null<PredicateAssume>(CmpPI))
|
|
|
|
return createConstantExpression(ConstantInt::getTrue(CI->getType()));
|
|
|
|
|
2017-02-01 06:31:58 +08:00
|
|
|
if (Op0 == Op1) {
|
2017-02-19 07:06:50 +08:00
|
|
|
// This condition does not depend on predicates, no need to add users
|
2017-02-01 06:31:58 +08:00
|
|
|
if (CI->isTrueWhenEqual())
|
|
|
|
return createConstantExpression(ConstantInt::getTrue(CI->getType()));
|
|
|
|
else if (CI->isFalseWhenEqual())
|
|
|
|
return createConstantExpression(ConstantInt::getFalse(CI->getType()));
|
|
|
|
}
|
2017-02-19 07:06:50 +08:00
|
|
|
|
|
|
|
// NOTE: Because we are comparing both operands here and below, and using
|
|
|
|
// previous comparisons, we rely on fact that predicateinfo knows to mark
|
|
|
|
// comparisons that use renamed operands as users of the earlier comparisons.
|
|
|
|
// It is *not* enough to just mark predicateinfo renamed operands as users of
|
|
|
|
// the earlier comparisons, because the *other* operand may have changed in a
|
|
|
|
// previous iteration.
|
|
|
|
// Example:
|
|
|
|
// icmp slt %a, %b
|
|
|
|
// %b.0 = ssa.copy(%b)
|
|
|
|
// false branch:
|
|
|
|
// icmp slt %c, %b.0
|
|
|
|
|
|
|
|
// %c and %a may start out equal, and thus, the code below will say the second
|
|
|
|
// %icmp is false. c may become equal to something else, and in that case the
|
|
|
|
// %second icmp *must* be reexamined, but would not if only the renamed
|
|
|
|
// %operands are considered users of the icmp.
|
|
|
|
|
|
|
|
// *Currently* we only check one level of comparisons back, and only mark one
|
|
|
|
// level back as touched when changes appen . If you modify this code to look
|
|
|
|
// back farther through comparisons, you *must* mark the appropriate
|
|
|
|
// comparisons as users in PredicateInfo.cpp, or you will cause bugs. See if
|
|
|
|
// we know something just from the operands themselves
|
|
|
|
|
|
|
|
// See if our operands have predicate info, so that we may be able to derive
|
|
|
|
// something from a previous comparison.
|
|
|
|
for (const auto &Op : CI->operands()) {
|
|
|
|
auto *PI = PredInfo->getPredicateInfoFor(Op);
|
|
|
|
if (const auto *PBranch = dyn_cast_or_null<PredicateBranch>(PI)) {
|
|
|
|
if (PI == LastPredInfo)
|
|
|
|
continue;
|
|
|
|
LastPredInfo = PI;
|
2017-02-23 06:20:58 +08:00
|
|
|
|
2017-02-19 07:06:50 +08:00
|
|
|
// TODO: Along the false edge, we may know more things too, like icmp of
|
|
|
|
// same operands is false.
|
|
|
|
// TODO: We only handle actual comparison conditions below, not and/or.
|
|
|
|
auto *BranchCond = dyn_cast<CmpInst>(PBranch->Condition);
|
|
|
|
if (!BranchCond)
|
|
|
|
continue;
|
|
|
|
auto *BranchOp0 = lookupOperandLeader(BranchCond->getOperand(0));
|
|
|
|
auto *BranchOp1 = lookupOperandLeader(BranchCond->getOperand(1));
|
|
|
|
auto BranchPredicate = BranchCond->getPredicate();
|
2017-03-04 08:44:43 +08:00
|
|
|
if (shouldSwapOperands(BranchOp0, BranchOp1)) {
|
2017-02-19 07:06:50 +08:00
|
|
|
std::swap(BranchOp0, BranchOp1);
|
|
|
|
BranchPredicate = BranchCond->getSwappedPredicate();
|
|
|
|
}
|
|
|
|
if (BranchOp0 == Op0 && BranchOp1 == Op1) {
|
|
|
|
if (PBranch->TrueEdge) {
|
|
|
|
// If we know the previous predicate is true and we are in the true
|
|
|
|
// edge then we may be implied true or false.
|
2017-05-02 06:26:28 +08:00
|
|
|
if (CmpInst::isImpliedTrueByMatchingCmp(BranchPredicate,
|
|
|
|
OurPredicate)) {
|
2017-02-19 07:06:50 +08:00
|
|
|
addPredicateUsers(PI, I);
|
|
|
|
return createConstantExpression(
|
|
|
|
ConstantInt::getTrue(CI->getType()));
|
|
|
|
}
|
|
|
|
|
2017-05-02 06:26:28 +08:00
|
|
|
if (CmpInst::isImpliedFalseByMatchingCmp(BranchPredicate,
|
|
|
|
OurPredicate)) {
|
2017-02-19 07:06:50 +08:00
|
|
|
addPredicateUsers(PI, I);
|
|
|
|
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.
|
|
|
|
if (BranchPredicate == OurPredicate) {
|
|
|
|
addPredicateUsers(PI, I);
|
|
|
|
// Same predicate, same ops,we know it was false, so this is false.
|
|
|
|
return createConstantExpression(
|
|
|
|
ConstantInt::getFalse(CI->getType()));
|
|
|
|
} else if (BranchPredicate ==
|
|
|
|
CmpInst::getInversePredicate(OurPredicate)) {
|
|
|
|
addPredicateUsers(PI, I);
|
|
|
|
// Inverse predicate, we know the other was false, so this is true.
|
|
|
|
return createConstantExpression(
|
|
|
|
ConstantInt::getTrue(CI->getType()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Create expression will take care of simplifyCmpInst
|
2017-02-01 06:32:03 +08:00
|
|
|
return createExpression(I);
|
2017-02-01 06:31:58 +08:00
|
|
|
}
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Substitute and symbolize the value before value numbering.
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *NewGVN::performSymbolicEvaluation(Value *V) const {
|
2016-12-28 22:00:11 +08:00
|
|
|
const Expression *E = nullptr;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (auto *C = dyn_cast<Constant>(V))
|
|
|
|
E = createConstantExpression(C);
|
|
|
|
else if (isa<Argument>(V) || isa<GlobalVariable>(V)) {
|
|
|
|
E = createVariableExpression(V);
|
|
|
|
} else {
|
|
|
|
// TODO: memory intrinsics.
|
|
|
|
// TODO: Some day, we should do the forward propagation and reassociation
|
|
|
|
// parts of the algorithm.
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *I = cast<Instruction>(V);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
switch (I->getOpcode()) {
|
|
|
|
case Instruction::ExtractValue:
|
|
|
|
case Instruction::InsertValue:
|
2017-02-01 06:32:03 +08:00
|
|
|
E = performSymbolicAggrValueEvaluation(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
break;
|
|
|
|
case Instruction::PHI:
|
2017-02-01 06:32:03 +08:00
|
|
|
E = performSymbolicPHIEvaluation(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
break;
|
|
|
|
case Instruction::Call:
|
2017-02-01 06:32:03 +08:00
|
|
|
E = performSymbolicCallEvaluation(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
break;
|
|
|
|
case Instruction::Store:
|
2017-02-01 06:32:03 +08:00
|
|
|
E = performSymbolicStoreEvaluation(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
break;
|
|
|
|
case Instruction::Load:
|
2017-02-01 06:32:03 +08:00
|
|
|
E = performSymbolicLoadEvaluation(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
break;
|
|
|
|
case Instruction::BitCast: {
|
2017-02-01 06:32:03 +08:00
|
|
|
E = createExpression(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
} break;
|
2017-02-01 06:31:58 +08:00
|
|
|
case Instruction::ICmp:
|
|
|
|
case Instruction::FCmp: {
|
2017-02-01 06:32:03 +08:00
|
|
|
E = performSymbolicCmpEvaluation(I);
|
2017-02-01 06:31:58 +08:00
|
|
|
} break;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
case Instruction::Add:
|
|
|
|
case Instruction::FAdd:
|
|
|
|
case Instruction::Sub:
|
|
|
|
case Instruction::FSub:
|
|
|
|
case Instruction::Mul:
|
|
|
|
case Instruction::FMul:
|
|
|
|
case Instruction::UDiv:
|
|
|
|
case Instruction::SDiv:
|
|
|
|
case Instruction::FDiv:
|
|
|
|
case Instruction::URem:
|
|
|
|
case Instruction::SRem:
|
|
|
|
case Instruction::FRem:
|
|
|
|
case Instruction::Shl:
|
|
|
|
case Instruction::LShr:
|
|
|
|
case Instruction::AShr:
|
|
|
|
case Instruction::And:
|
|
|
|
case Instruction::Or:
|
|
|
|
case Instruction::Xor:
|
|
|
|
case Instruction::Trunc:
|
|
|
|
case Instruction::ZExt:
|
|
|
|
case Instruction::SExt:
|
|
|
|
case Instruction::FPToUI:
|
|
|
|
case Instruction::FPToSI:
|
|
|
|
case Instruction::UIToFP:
|
|
|
|
case Instruction::SIToFP:
|
|
|
|
case Instruction::FPTrunc:
|
|
|
|
case Instruction::FPExt:
|
|
|
|
case Instruction::PtrToInt:
|
|
|
|
case Instruction::IntToPtr:
|
|
|
|
case Instruction::Select:
|
|
|
|
case Instruction::ExtractElement:
|
|
|
|
case Instruction::InsertElement:
|
|
|
|
case Instruction::ShuffleVector:
|
|
|
|
case Instruction::GetElementPtr:
|
2017-02-01 06:32:03 +08:00
|
|
|
E = createExpression(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NewGVN::markUsersTouched(Value *V) {
|
|
|
|
// Now mark the users as touched.
|
2016-12-30 06:15:12 +08:00
|
|
|
for (auto *User : V->users()) {
|
|
|
|
assert(isa<Instruction>(User) && "Use of value not within an instruction?");
|
2017-04-07 02:52:58 +08:00
|
|
|
TouchedInstructions.set(InstrToDFSNum(User));
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
void NewGVN::addMemoryUsers(const MemoryAccess *To, MemoryAccess *U) const {
|
2017-04-07 02:52:50 +08:00
|
|
|
DEBUG(dbgs() << "Adding memory user " << *U << " to " << *To << "\n");
|
|
|
|
MemoryToUsers[To].insert(U);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NewGVN::markMemoryDefTouched(const MemoryAccess *MA) {
|
2017-04-07 02:52:58 +08:00
|
|
|
TouchedInstructions.set(MemoryToDFSNum(MA));
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void NewGVN::markMemoryUsersTouched(const MemoryAccess *MA) {
|
|
|
|
if (isa<MemoryUse>(MA))
|
|
|
|
return;
|
|
|
|
for (auto U : MA->users())
|
2017-04-07 02:52:58 +08:00
|
|
|
TouchedInstructions.set(MemoryToDFSNum(U));
|
2017-04-07 02:52:50 +08:00
|
|
|
const auto Result = MemoryToUsers.find(MA);
|
|
|
|
if (Result != MemoryToUsers.end()) {
|
|
|
|
for (auto *User : Result->second)
|
2017-04-07 02:52:58 +08:00
|
|
|
TouchedInstructions.set(MemoryToDFSNum(User));
|
2017-04-07 02:52:50 +08:00
|
|
|
MemoryToUsers.erase(Result);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-19 07:06:50 +08:00
|
|
|
// Add I to the set of users of a given predicate.
|
2017-05-10 00:40:04 +08:00
|
|
|
void NewGVN::addPredicateUsers(const PredicateBase *PB, Instruction *I) const {
|
2017-02-19 07:06:50 +08:00
|
|
|
if (auto *PBranch = dyn_cast<PredicateBranch>(PB))
|
|
|
|
PredicateToUsers[PBranch->Condition].insert(I);
|
|
|
|
else if (auto *PAssume = dyn_cast<PredicateBranch>(PB))
|
|
|
|
PredicateToUsers[PAssume->Condition].insert(I);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Touch all the predicates that depend on this instruction.
|
|
|
|
void NewGVN::markPredicateUsersTouched(Instruction *I) {
|
|
|
|
const auto Result = PredicateToUsers.find(I);
|
2017-03-19 08:07:32 +08:00
|
|
|
if (Result != PredicateToUsers.end()) {
|
2017-02-19 07:06:50 +08:00
|
|
|
for (auto *User : Result->second)
|
2017-04-07 02:52:58 +08:00
|
|
|
TouchedInstructions.set(InstrToDFSNum(User));
|
2017-03-19 08:07:32 +08:00
|
|
|
PredicateToUsers.erase(Result);
|
|
|
|
}
|
2017-02-19 07:06:50 +08:00
|
|
|
}
|
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
// Mark users affected by a memory leader change.
|
|
|
|
void NewGVN::markMemoryLeaderChangeTouched(CongruenceClass *CC) {
|
2017-04-08 02:38:09 +08:00
|
|
|
for (auto M : CC->memory())
|
2017-04-07 02:52:50 +08:00
|
|
|
markMemoryDefTouched(M);
|
|
|
|
}
|
|
|
|
|
2017-01-08 00:55:14 +08:00
|
|
|
// Touch the instructions that need to be updated after a congruence class has a
|
|
|
|
// leader change, and mark changed values.
|
2017-04-07 02:52:50 +08:00
|
|
|
void NewGVN::markValueLeaderChangeTouched(CongruenceClass *CC) {
|
2017-04-08 02:38:09 +08:00
|
|
|
for (auto M : *CC) {
|
2017-01-08 00:55:14 +08:00
|
|
|
if (auto *I = dyn_cast<Instruction>(M))
|
2017-04-07 02:52:58 +08:00
|
|
|
TouchedInstructions.set(InstrToDFSNum(I));
|
2017-01-12 04:22:05 +08:00
|
|
|
LeaderChanges.insert(M);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
// Give a range of things that have instruction DFS numbers, this will return
|
|
|
|
// the member of the range with the smallest dfs number.
|
|
|
|
template <class T, class Range>
|
|
|
|
T *NewGVN::getMinDFSOfRange(const Range &R) const {
|
|
|
|
std::pair<T *, unsigned> MinDFS = {nullptr, ~0U};
|
|
|
|
for (const auto X : R) {
|
2017-04-07 02:52:58 +08:00
|
|
|
auto DFSNum = InstrToDFSNum(X);
|
2017-04-07 02:52:50 +08:00
|
|
|
if (DFSNum < MinDFS.second)
|
|
|
|
MinDFS = {X, DFSNum};
|
|
|
|
}
|
|
|
|
return MinDFS.first;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This function returns the MemoryAccess that should be the next leader of
|
|
|
|
// congruence class CC, under the assumption that the current leader is going to
|
|
|
|
// disappear.
|
|
|
|
const MemoryAccess *NewGVN::getNextMemoryLeader(CongruenceClass *CC) const {
|
|
|
|
// TODO: If this ends up to slow, we can maintain a next memory leader like we
|
|
|
|
// do for regular leaders.
|
|
|
|
// Make sure there will be a leader to find
|
2017-05-11 03:57:43 +08:00
|
|
|
assert(!CC->definesNoMemory() && "Can't get next leader if there is none");
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC->getStoreCount() > 0) {
|
|
|
|
if (auto *NL = dyn_cast_or_null<StoreInst>(CC->getNextLeader().first))
|
2017-04-07 02:52:50 +08:00
|
|
|
return MSSA->getMemoryAccess(NL);
|
|
|
|
// Find the store with the minimum DFS number.
|
|
|
|
auto *V = getMinDFSOfRange<Value>(make_filter_range(
|
2017-04-08 02:38:09 +08:00
|
|
|
*CC, [&](const Value *V) { return isa<StoreInst>(V); }));
|
2017-04-07 02:52:50 +08:00
|
|
|
return MSSA->getMemoryAccess(cast<StoreInst>(V));
|
|
|
|
}
|
2017-04-08 02:38:09 +08:00
|
|
|
assert(CC->getStoreCount() == 0);
|
2017-04-07 02:52:50 +08:00
|
|
|
|
|
|
|
// Given our assertion, hitting this part must mean
|
2017-04-08 02:38:09 +08:00
|
|
|
// !OldClass->memory_empty()
|
|
|
|
if (CC->memory_size() == 1)
|
|
|
|
return *CC->memory_begin();
|
|
|
|
return getMinDFSOfRange<const MemoryPhi>(CC->memory());
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// This function returns the next value leader of a congruence class, under the
|
|
|
|
// assumption that the current leader is going away. This should end up being
|
|
|
|
// the next most dominating member.
|
|
|
|
Value *NewGVN::getNextValueLeader(CongruenceClass *CC) const {
|
|
|
|
// We don't need to sort members if there is only 1, and we don't care about
|
|
|
|
// sorting the TOP class because everything either gets out of it or is
|
|
|
|
// unreachable.
|
|
|
|
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC->size() == 1 || CC == TOPClass) {
|
|
|
|
return *(CC->begin());
|
|
|
|
} else if (CC->getNextLeader().first) {
|
2017-04-07 02:52:50 +08:00
|
|
|
++NumGVNAvoidedSortedLeaderChanges;
|
2017-04-08 02:38:09 +08:00
|
|
|
return CC->getNextLeader().first;
|
2017-04-07 02:52:50 +08:00
|
|
|
} else {
|
|
|
|
++NumGVNSortedLeaderChanges;
|
|
|
|
// NOTE: If this ends up to slow, we can maintain a dual structure for
|
|
|
|
// member testing/insertion, or keep things mostly sorted, and sort only
|
|
|
|
// here, or use SparseBitVector or ....
|
2017-04-08 02:38:09 +08:00
|
|
|
return getMinDFSOfRange<Value>(*CC);
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move a MemoryAccess, currently in OldClass, to NewClass, including updates to
|
|
|
|
// the memory members, etc for the move.
|
|
|
|
//
|
|
|
|
// The invariants of this function are:
|
|
|
|
//
|
|
|
|
// I must be moving to NewClass from OldClass The StoreCount of OldClass and
|
|
|
|
// NewClass is expected to have been updated for I already if it is is a store.
|
|
|
|
// The OldClass memory leader has not been updated yet if I was the leader.
|
|
|
|
void NewGVN::moveMemoryToNewCongruenceClass(Instruction *I,
|
|
|
|
MemoryAccess *InstMA,
|
|
|
|
CongruenceClass *OldClass,
|
|
|
|
CongruenceClass *NewClass) {
|
|
|
|
// If the leader is I, and we had a represenative MemoryAccess, it should
|
|
|
|
// be the MemoryAccess of OldClass.
|
2017-04-11 07:08:35 +08:00
|
|
|
assert((!InstMA || !OldClass->getMemoryLeader() ||
|
|
|
|
OldClass->getLeader() != I ||
|
|
|
|
OldClass->getMemoryLeader() == InstMA) &&
|
|
|
|
"Representative MemoryAccess mismatch");
|
2017-04-07 02:52:50 +08:00
|
|
|
// First, see what happens to the new class
|
2017-04-08 02:38:09 +08:00
|
|
|
if (!NewClass->getMemoryLeader()) {
|
2017-04-07 02:52:50 +08:00
|
|
|
// Should be a new class, or a store becoming a leader of a new class.
|
2017-04-08 02:38:09 +08:00
|
|
|
assert(NewClass->size() == 1 ||
|
|
|
|
(isa<StoreInst>(I) && NewClass->getStoreCount() == 1));
|
|
|
|
NewClass->setMemoryLeader(InstMA);
|
2017-04-07 02:52:50 +08:00
|
|
|
// Mark it touched if we didn't just create a singleton
|
2017-04-08 02:38:09 +08:00
|
|
|
DEBUG(dbgs() << "Memory class leader change for class " << NewClass->getID()
|
2017-04-07 02:52:50 +08:00
|
|
|
<< " due to new memory instruction becoming leader\n");
|
|
|
|
markMemoryLeaderChangeTouched(NewClass);
|
|
|
|
}
|
|
|
|
setMemoryClass(InstMA, NewClass);
|
|
|
|
// Now, fixup the old class if necessary
|
2017-04-08 02:38:09 +08:00
|
|
|
if (OldClass->getMemoryLeader() == InstMA) {
|
2017-05-11 03:57:43 +08:00
|
|
|
if (!OldClass->definesNoMemory()) {
|
2017-04-08 02:38:09 +08:00
|
|
|
OldClass->setMemoryLeader(getNextMemoryLeader(OldClass));
|
|
|
|
DEBUG(dbgs() << "Memory class leader change for class "
|
|
|
|
<< OldClass->getID() << " to "
|
|
|
|
<< *OldClass->getMemoryLeader()
|
2017-04-07 02:52:50 +08:00
|
|
|
<< " due to removal of old leader " << *InstMA << "\n");
|
|
|
|
markMemoryLeaderChangeTouched(OldClass);
|
|
|
|
} else
|
2017-04-08 02:38:09 +08:00
|
|
|
OldClass->setMemoryLeader(nullptr);
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-12 04:22:05 +08:00
|
|
|
// Move a value, currently in OldClass, to be part of NewClass
|
2017-04-07 02:52:50 +08:00
|
|
|
// Update OldClass and NewClass for the move (including changing leaders, etc).
|
|
|
|
void NewGVN::moveValueToNewCongruenceClass(Instruction *I, const Expression *E,
|
2017-01-14 06:40:01 +08:00
|
|
|
CongruenceClass *OldClass,
|
2017-01-12 04:22:05 +08:00
|
|
|
CongruenceClass *NewClass) {
|
2017-04-08 02:38:09 +08:00
|
|
|
if (I == OldClass->getNextLeader().first)
|
|
|
|
OldClass->resetNextLeader();
|
2017-01-14 06:40:01 +08:00
|
|
|
|
2017-01-20 14:38:41 +08:00
|
|
|
// It's possible, though unlikely, for us to discover equivalences such
|
|
|
|
// that the current leader does not dominate the old one.
|
|
|
|
// This statistic tracks how often this happens.
|
|
|
|
// We assert on phi nodes when this happens, currently, for debugging, because
|
|
|
|
// we want to make sure we name phi node cycles properly.
|
2017-04-08 02:38:09 +08:00
|
|
|
if (isa<Instruction>(NewClass->getLeader()) && NewClass->getLeader() &&
|
|
|
|
I != NewClass->getLeader()) {
|
2017-03-24 14:33:51 +08:00
|
|
|
auto *IBB = I->getParent();
|
2017-04-08 02:38:09 +08:00
|
|
|
auto *NCBB = cast<Instruction>(NewClass->getLeader())->getParent();
|
2017-04-07 02:52:58 +08:00
|
|
|
bool Dominated =
|
2017-04-08 02:38:09 +08:00
|
|
|
IBB == NCBB && InstrToDFSNum(I) < InstrToDFSNum(NewClass->getLeader());
|
2017-03-24 14:33:51 +08:00
|
|
|
Dominated = Dominated || DT->properlyDominates(IBB, NCBB);
|
|
|
|
if (Dominated) {
|
|
|
|
++NumGVNNotMostDominatingLeader;
|
|
|
|
assert(
|
|
|
|
!isa<PHINode>(I) &&
|
|
|
|
"New class for instruction should not be dominated by instruction");
|
|
|
|
}
|
2017-01-20 14:38:41 +08:00
|
|
|
}
|
2017-01-14 06:40:01 +08:00
|
|
|
|
2017-04-08 02:38:09 +08:00
|
|
|
if (NewClass->getLeader() != I)
|
|
|
|
NewClass->addPossibleNextLeader({I, InstrToDFSNum(I)});
|
2017-01-14 06:40:01 +08:00
|
|
|
|
2017-04-08 02:38:09 +08:00
|
|
|
OldClass->erase(I);
|
|
|
|
NewClass->insert(I);
|
2017-04-07 02:52:50 +08:00
|
|
|
// Handle our special casing of stores.
|
2017-01-27 06:21:48 +08:00
|
|
|
if (auto *SI = dyn_cast<StoreInst>(I)) {
|
2017-04-08 02:38:09 +08:00
|
|
|
OldClass->decStoreCount();
|
|
|
|
// Okay, so when do we want to make a store a leader of a class?
|
|
|
|
// If we have a store defined by an earlier load, we want the earlier load
|
|
|
|
// to lead the class.
|
|
|
|
// If we have a store defined by something else, we want the store to lead
|
|
|
|
// the class so everything else gets the "something else" as a value.
|
2017-04-07 02:52:50 +08:00
|
|
|
// If we have a store as the single member of the class, we want the store
|
2017-04-08 02:38:09 +08:00
|
|
|
// as the leader
|
|
|
|
if (NewClass->getStoreCount() == 0 && !NewClass->getStoredValue()) {
|
2017-04-07 02:52:50 +08:00
|
|
|
// If it's a store expression we are using, it means we are not equivalent
|
|
|
|
// to something earlier.
|
2017-05-16 14:06:15 +08:00
|
|
|
if (auto *SE = dyn_cast<StoreExpression>(E)) {
|
|
|
|
assert(SE->getStoredValue() != NewClass->getLeader());
|
|
|
|
NewClass->setStoredValue(SE->getStoredValue());
|
2017-04-07 02:52:50 +08:00
|
|
|
markValueLeaderChangeTouched(NewClass);
|
|
|
|
// Shift the new class leader to be the store
|
2017-04-08 02:38:09 +08:00
|
|
|
DEBUG(dbgs() << "Changing leader of congruence class "
|
|
|
|
<< NewClass->getID() << " from " << *NewClass->getLeader()
|
|
|
|
<< " to " << *SI << " because store joined class\n");
|
2017-04-07 02:52:50 +08:00
|
|
|
// If we changed the leader, we have to mark it changed because we don't
|
|
|
|
// know what it will do to symbolic evlauation.
|
2017-04-08 02:38:09 +08:00
|
|
|
NewClass->setLeader(SI);
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
|
|
|
// We rely on the code below handling the MemoryAccess change.
|
|
|
|
}
|
2017-04-08 02:38:09 +08:00
|
|
|
NewClass->incStoreCount();
|
2017-01-12 04:22:05 +08:00
|
|
|
}
|
2017-04-07 02:52:50 +08:00
|
|
|
// True if there is no memory instructions left in a class that had memory
|
|
|
|
// instructions before.
|
2017-01-12 04:22:05 +08:00
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
// If it's not a memory use, set the MemoryAccess equivalence
|
|
|
|
auto *InstMA = dyn_cast_or_null<MemoryDef>(MSSA->getMemoryAccess(I));
|
|
|
|
if (InstMA)
|
|
|
|
moveMemoryToNewCongruenceClass(I, InstMA, OldClass, NewClass);
|
2017-01-14 06:40:01 +08:00
|
|
|
ValueToClass[I] = NewClass;
|
2017-01-12 04:22:05 +08:00
|
|
|
// See if we destroyed the class or need to swap leaders.
|
2017-04-08 02:38:09 +08:00
|
|
|
if (OldClass->empty() && OldClass != TOPClass) {
|
|
|
|
if (OldClass->getDefiningExpr()) {
|
2017-05-16 14:06:15 +08:00
|
|
|
DEBUG(dbgs() << "Erasing expression " << *OldClass->getDefiningExpr()
|
2017-01-12 04:22:05 +08:00
|
|
|
<< " from table\n");
|
2017-04-08 02:38:09 +08:00
|
|
|
ExpressionToClass.erase(OldClass->getDefiningExpr());
|
2017-01-12 04:22:05 +08:00
|
|
|
}
|
2017-04-08 02:38:09 +08:00
|
|
|
} else if (OldClass->getLeader() == I) {
|
2017-01-12 04:22:05 +08:00
|
|
|
// When the leader changes, the value numbering of
|
|
|
|
// everything may change due to symbolization changes, so we need to
|
|
|
|
// reprocess.
|
2017-04-08 02:38:09 +08:00
|
|
|
DEBUG(dbgs() << "Value class leader change for class " << OldClass->getID()
|
2017-04-07 02:52:50 +08:00
|
|
|
<< "\n");
|
2017-01-14 06:40:01 +08:00
|
|
|
++NumGVNLeaderChanges;
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
// Destroy the stored value if there are no more stores to represent it.
|
2017-04-07 02:52:50 +08:00
|
|
|
// Note that this is basically clean up for the expression removal that
|
|
|
|
// happens below. If we remove stores from a class, we may leave it as a
|
|
|
|
// class of equivalent memory phis.
|
2017-04-08 02:38:09 +08:00
|
|
|
if (OldClass->getStoreCount() == 0) {
|
|
|
|
if (OldClass->getStoredValue())
|
|
|
|
OldClass->setStoredValue(nullptr);
|
2017-01-27 06:21:48 +08:00
|
|
|
}
|
2017-04-08 02:38:09 +08:00
|
|
|
OldClass->setLeader(getNextValueLeader(OldClass));
|
|
|
|
OldClass->resetNextLeader();
|
2017-04-07 02:52:50 +08:00
|
|
|
markValueLeaderChangeTouched(OldClass);
|
2017-01-08 00:55:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Perform congruence finding on a given value numbering expression.
|
2017-01-14 06:40:01 +08:00
|
|
|
void NewGVN::performCongruenceFinding(Instruction *I, const Expression *E) {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// This is guaranteed to return something, since it will at least find
|
2017-02-11 20:48:50 +08:00
|
|
|
// TOP.
|
2017-01-08 00:55:14 +08:00
|
|
|
|
2017-01-14 06:40:01 +08:00
|
|
|
CongruenceClass *IClass = ValueToClass[I];
|
|
|
|
assert(IClass && "Should have found a IClass");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Dead classes should have been eliminated from the mapping.
|
2017-04-07 02:52:50 +08:00
|
|
|
assert(!IClass->isDead() && "Found a dead class");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
CongruenceClass *EClass;
|
2017-01-03 02:00:53 +08:00
|
|
|
if (const auto *VE = dyn_cast<VariableExpression>(E)) {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
EClass = ValueToClass[VE->getVariableValue()];
|
|
|
|
} else {
|
|
|
|
auto lookupResult = ExpressionToClass.insert({E, nullptr});
|
|
|
|
|
|
|
|
// If it's not in the value table, create a new congruence class.
|
|
|
|
if (lookupResult.second) {
|
2016-12-28 22:00:11 +08:00
|
|
|
CongruenceClass *NewClass = createCongruenceClass(nullptr, E);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
auto place = lookupResult.first;
|
|
|
|
place->second = NewClass;
|
|
|
|
|
|
|
|
// Constants and variables should always be made the leader.
|
2017-01-08 00:55:14 +08:00
|
|
|
if (const auto *CE = dyn_cast<ConstantExpression>(E)) {
|
2017-04-08 02:38:09 +08:00
|
|
|
NewClass->setLeader(CE->getConstantValue());
|
2017-01-08 00:55:14 +08:00
|
|
|
} else if (const auto *SE = dyn_cast<StoreExpression>(E)) {
|
|
|
|
StoreInst *SI = SE->getStoreInst();
|
2017-04-08 02:38:09 +08:00
|
|
|
NewClass->setLeader(SI);
|
2017-05-16 14:06:15 +08:00
|
|
|
NewClass->setStoredValue(SE->getStoredValue());
|
2017-01-27 06:21:48 +08:00
|
|
|
// The RepMemoryAccess field will be filled in properly by the
|
|
|
|
// moveValueToNewCongruenceClass call.
|
2017-01-08 00:55:14 +08:00
|
|
|
} else {
|
2017-04-08 02:38:09 +08:00
|
|
|
NewClass->setLeader(I);
|
2017-01-08 00:55:14 +08:00
|
|
|
}
|
|
|
|
assert(!isa<VariableExpression>(E) &&
|
|
|
|
"VariableExpression should have been handled already");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
EClass = NewClass;
|
2017-01-14 06:40:01 +08:00
|
|
|
DEBUG(dbgs() << "Created new congruence class for " << *I
|
2017-04-08 02:38:09 +08:00
|
|
|
<< " using expression " << *E << " at " << NewClass->getID()
|
|
|
|
<< " and leader " << *(NewClass->getLeader()));
|
|
|
|
if (NewClass->getStoredValue())
|
|
|
|
DEBUG(dbgs() << " and stored value " << *(NewClass->getStoredValue()));
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
DEBUG(dbgs() << "\n");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
} else {
|
|
|
|
EClass = lookupResult.first->second;
|
2017-01-03 02:00:46 +08:00
|
|
|
if (isa<ConstantExpression>(E))
|
2017-04-11 07:08:35 +08:00
|
|
|
assert((isa<Constant>(EClass->getLeader()) ||
|
|
|
|
(EClass->getStoredValue() &&
|
|
|
|
isa<Constant>(EClass->getStoredValue()))) &&
|
|
|
|
"Any class with a constant expression should have a "
|
|
|
|
"constant leader");
|
2017-01-03 02:00:46 +08:00
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
assert(EClass && "Somehow don't have an eclass");
|
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
assert(!EClass->isDead() && "We accidentally looked up a dead class");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
2017-01-14 06:40:01 +08:00
|
|
|
bool ClassChanged = IClass != EClass;
|
|
|
|
bool LeaderChanged = LeaderChanges.erase(I);
|
2017-01-12 04:22:05 +08:00
|
|
|
if (ClassChanged || LeaderChanged) {
|
2017-04-08 02:38:09 +08:00
|
|
|
DEBUG(dbgs() << "New class " << EClass->getID() << " for expression " << *E
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
<< "\n");
|
2017-01-12 04:22:05 +08:00
|
|
|
if (ClassChanged)
|
2017-04-07 02:52:50 +08:00
|
|
|
moveValueToNewCongruenceClass(I, E, IClass, EClass);
|
2017-01-14 06:40:01 +08:00
|
|
|
markUsersTouched(I);
|
2017-01-27 06:21:48 +08:00
|
|
|
if (MemoryAccess *MA = MSSA->getMemoryAccess(I))
|
2017-01-14 06:40:01 +08:00
|
|
|
markMemoryUsersTouched(MA);
|
2017-02-19 07:06:50 +08:00
|
|
|
if (auto *CI = dyn_cast<CmpInst>(I))
|
|
|
|
markPredicateUsersTouched(CI);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
2017-05-17 03:58:47 +08:00
|
|
|
// If we changed the class of the store, we want to ensure nothing finds the
|
|
|
|
// old store expression. In particular, loads do not compare against stored
|
|
|
|
// value, so they will find old store expressions (and associated class
|
|
|
|
// mappings) if we leave them in the table.
|
2017-05-19 12:06:10 +08:00
|
|
|
if (ClassChanged && isa<StoreInst>(I)) {
|
2017-05-17 03:58:47 +08:00
|
|
|
auto *OldE = ValueToExpression.lookup(I);
|
|
|
|
// It could just be that the old class died. We don't want to erase it if we
|
|
|
|
// just moved classes.
|
2017-05-19 12:06:10 +08:00
|
|
|
if (OldE && isa<StoreExpression>(OldE) && *E != *OldE)
|
2017-05-17 03:58:47 +08:00
|
|
|
ExpressionToClass.erase(OldE);
|
|
|
|
}
|
|
|
|
ValueToExpression[I] = E;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Process the fact that Edge (from, to) is reachable, including marking
|
|
|
|
// any newly reachable blocks and instructions for processing.
|
|
|
|
void NewGVN::updateReachableEdge(BasicBlock *From, BasicBlock *To) {
|
|
|
|
// Check if the Edge was reachable before.
|
|
|
|
if (ReachableEdges.insert({From, To}).second) {
|
|
|
|
// If this block wasn't reachable before, all instructions are touched.
|
|
|
|
if (ReachableBlocks.insert(To).second) {
|
|
|
|
DEBUG(dbgs() << "Block " << getBlockName(To) << " marked reachable\n");
|
|
|
|
const auto &InstRange = BlockInstRange.lookup(To);
|
|
|
|
TouchedInstructions.set(InstRange.first, InstRange.second);
|
|
|
|
} else {
|
|
|
|
DEBUG(dbgs() << "Block " << getBlockName(To)
|
|
|
|
<< " was reachable, but new edge {" << getBlockName(From)
|
|
|
|
<< "," << getBlockName(To) << "} to it found\n");
|
|
|
|
|
|
|
|
// We've made an edge reachable to an existing block, which may
|
|
|
|
// impact predicates. Otherwise, only mark the phi nodes as touched, as
|
|
|
|
// they are the only thing that depend on new edges. Anything using their
|
|
|
|
// values will get propagated to if necessary.
|
2017-01-03 02:00:46 +08:00
|
|
|
if (MemoryAccess *MemPhi = MSSA->getMemoryAccess(To))
|
2017-04-07 02:52:58 +08:00
|
|
|
TouchedInstructions.set(InstrToDFSNum(MemPhi));
|
2017-01-03 02:00:46 +08:00
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
auto BI = To->begin();
|
|
|
|
while (isa<PHINode>(BI)) {
|
2017-04-07 02:52:58 +08:00
|
|
|
TouchedInstructions.set(InstrToDFSNum(&*BI));
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
++BI;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Given a predicate condition (from a switch, cmp, or whatever) and a block,
|
|
|
|
// see if we know some constant value for it already.
|
2017-02-01 06:32:03 +08:00
|
|
|
Value *NewGVN::findConditionEquivalence(Value *Cond) const {
|
2017-02-01 06:31:53 +08:00
|
|
|
auto Result = lookupOperandLeader(Cond);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (isa<Constant>(Result))
|
|
|
|
return Result;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Process the outgoing edges of a block for reachability.
|
|
|
|
void NewGVN::processOutgoingEdges(TerminatorInst *TI, BasicBlock *B) {
|
|
|
|
// Evaluate reachability of terminator instruction.
|
|
|
|
BranchInst *BR;
|
|
|
|
if ((BR = dyn_cast<BranchInst>(TI)) && BR->isConditional()) {
|
|
|
|
Value *Cond = BR->getCondition();
|
2017-02-01 06:32:03 +08:00
|
|
|
Value *CondEvaluated = findConditionEquivalence(Cond);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (!CondEvaluated) {
|
|
|
|
if (auto *I = dyn_cast<Instruction>(Cond)) {
|
2017-02-01 06:32:03 +08:00
|
|
|
const Expression *E = createExpression(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (const auto *CE = dyn_cast<ConstantExpression>(E)) {
|
|
|
|
CondEvaluated = CE->getConstantValue();
|
|
|
|
}
|
|
|
|
} else if (isa<ConstantInt>(Cond)) {
|
|
|
|
CondEvaluated = Cond;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ConstantInt *CI;
|
|
|
|
BasicBlock *TrueSucc = BR->getSuccessor(0);
|
|
|
|
BasicBlock *FalseSucc = BR->getSuccessor(1);
|
|
|
|
if (CondEvaluated && (CI = dyn_cast<ConstantInt>(CondEvaluated))) {
|
|
|
|
if (CI->isOne()) {
|
|
|
|
DEBUG(dbgs() << "Condition for Terminator " << *TI
|
|
|
|
<< " evaluated to true\n");
|
|
|
|
updateReachableEdge(B, TrueSucc);
|
|
|
|
} else if (CI->isZero()) {
|
|
|
|
DEBUG(dbgs() << "Condition for Terminator " << *TI
|
|
|
|
<< " evaluated to false\n");
|
|
|
|
updateReachableEdge(B, FalseSucc);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
updateReachableEdge(B, TrueSucc);
|
|
|
|
updateReachableEdge(B, FalseSucc);
|
|
|
|
}
|
|
|
|
} else if (auto *SI = dyn_cast<SwitchInst>(TI)) {
|
|
|
|
// For switches, propagate the case values into the case
|
|
|
|
// destinations.
|
|
|
|
|
|
|
|
// Remember how many outgoing edges there are to every successor.
|
|
|
|
SmallDenseMap<BasicBlock *, unsigned, 16> SwitchEdges;
|
|
|
|
|
|
|
|
Value *SwitchCond = SI->getCondition();
|
2017-02-01 06:32:03 +08:00
|
|
|
Value *CondEvaluated = findConditionEquivalence(SwitchCond);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// See if we were able to turn this switch statement into a constant.
|
|
|
|
if (CondEvaluated && isa<ConstantInt>(CondEvaluated)) {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *CondVal = cast<ConstantInt>(CondEvaluated);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// We should be able to get case value for this.
|
2017-04-12 15:27:28 +08:00
|
|
|
auto Case = *SI->findCaseValue(CondVal);
|
|
|
|
if (Case.getCaseSuccessor() == SI->getDefaultDest()) {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// We proved the value is outside of the range of the case.
|
|
|
|
// We can't do anything other than mark the default dest as reachable,
|
|
|
|
// and go home.
|
|
|
|
updateReachableEdge(B, SI->getDefaultDest());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Now get where it goes and mark it reachable.
|
2017-04-12 15:27:28 +08:00
|
|
|
BasicBlock *TargetBlock = Case.getCaseSuccessor();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
updateReachableEdge(B, TargetBlock);
|
|
|
|
} else {
|
|
|
|
for (unsigned i = 0, e = SI->getNumSuccessors(); i != e; ++i) {
|
|
|
|
BasicBlock *TargetBlock = SI->getSuccessor(i);
|
|
|
|
++SwitchEdges[TargetBlock];
|
|
|
|
updateReachableEdge(B, TargetBlock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Otherwise this is either unconditional, or a type we have no
|
|
|
|
// idea about. Just mark successors as reachable.
|
|
|
|
for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) {
|
|
|
|
BasicBlock *TargetBlock = TI->getSuccessor(i);
|
|
|
|
updateReachableEdge(B, TargetBlock);
|
|
|
|
}
|
2017-01-03 02:00:46 +08:00
|
|
|
|
|
|
|
// This also may be a memory defining terminator, in which case, set it
|
2017-04-07 02:52:50 +08:00
|
|
|
// equivalent only to itself.
|
|
|
|
//
|
|
|
|
auto *MA = MSSA->getMemoryAccess(TI);
|
|
|
|
if (MA && !isa<MemoryUse>(MA)) {
|
|
|
|
auto *CC = ensureLeaderOfMemoryClass(MA);
|
|
|
|
if (setMemoryClass(MA, CC))
|
|
|
|
markMemoryUsersTouched(MA);
|
|
|
|
}
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-11 03:05:04 +08:00
|
|
|
// The algorithm initially places the values of the routine in the TOP
|
|
|
|
// congruence class. The leader of TOP is the undetermined value `undef`.
|
|
|
|
// When the algorithm has finished, values still in TOP are unreachable.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
void NewGVN::initializeCongruenceClasses(Function &F) {
|
2017-04-07 02:52:50 +08:00
|
|
|
NextCongruenceNum = 0;
|
|
|
|
|
|
|
|
// Note that even though we use the live on entry def as a representative
|
|
|
|
// MemoryAccess, it is *not* the same as the actual live on entry def. We
|
|
|
|
// have no real equivalemnt to undef for MemoryAccesses, and so we really
|
|
|
|
// should be checking whether the MemoryAccess is top if we want to know if it
|
|
|
|
// is equivalent to everything. Otherwise, what this really signifies is that
|
|
|
|
// the access "it reaches all the way back to the beginning of the function"
|
|
|
|
|
2017-03-11 03:05:04 +08:00
|
|
|
// Initialize all other instructions to be in TOP class.
|
|
|
|
TOPClass = createCongruenceClass(nullptr, nullptr);
|
2017-04-08 02:38:09 +08:00
|
|
|
TOPClass->setMemoryLeader(MSSA->getLiveOnEntryDef());
|
2017-04-07 02:52:50 +08:00
|
|
|
// The live on entry def gets put into it's own class
|
|
|
|
MemoryAccessToClass[MSSA->getLiveOnEntryDef()] =
|
|
|
|
createMemoryClass(MSSA->getLiveOnEntryDef());
|
|
|
|
|
2017-04-19 01:06:11 +08:00
|
|
|
for (auto DTN : nodes(DT)) {
|
|
|
|
BasicBlock *BB = DTN->getBlock();
|
2017-04-07 02:52:50 +08:00
|
|
|
// All MemoryAccesses are equivalent to live on entry to start. They must
|
|
|
|
// be initialized to something so that initial changes are noticed. For
|
|
|
|
// the maximal answer, we initialize them all to be the same as
|
|
|
|
// liveOnEntry.
|
2017-04-19 01:06:11 +08:00
|
|
|
auto *MemoryBlockDefs = MSSA->getBlockDefs(BB);
|
2017-04-07 02:52:50 +08:00
|
|
|
if (MemoryBlockDefs)
|
|
|
|
for (const auto &Def : *MemoryBlockDefs) {
|
|
|
|
MemoryAccessToClass[&Def] = TOPClass;
|
|
|
|
auto *MD = dyn_cast<MemoryDef>(&Def);
|
|
|
|
// Insert the memory phis into the member list.
|
|
|
|
if (!MD) {
|
|
|
|
const MemoryPhi *MP = cast<MemoryPhi>(&Def);
|
2017-04-08 02:38:09 +08:00
|
|
|
TOPClass->memory_insert(MP);
|
2017-04-07 02:52:50 +08:00
|
|
|
MemoryPhiState.insert({MP, MPS_TOP});
|
|
|
|
}
|
2017-01-03 02:00:46 +08:00
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
if (MD && isa<StoreInst>(MD->getMemoryInst()))
|
2017-04-08 02:38:09 +08:00
|
|
|
TOPClass->incStoreCount();
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
2017-04-19 01:06:11 +08:00
|
|
|
for (auto &I : *BB) {
|
2017-02-11 23:20:15 +08:00
|
|
|
// Don't insert void terminators into the class. We don't value number
|
2017-03-11 03:05:04 +08:00
|
|
|
// them, and they just end up sitting in TOP.
|
2017-02-11 23:20:15 +08:00
|
|
|
if (isa<TerminatorInst>(I) && I.getType()->isVoidTy())
|
|
|
|
continue;
|
2017-04-08 02:38:09 +08:00
|
|
|
TOPClass->insert(&I);
|
2017-03-11 03:05:04 +08:00
|
|
|
ValueToClass[&I] = TOPClass;
|
2016-12-27 03:57:25 +08:00
|
|
|
}
|
2017-01-03 02:00:46 +08:00
|
|
|
}
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Initialize arguments to be in their own unique congruence classes
|
|
|
|
for (auto &FA : F.args())
|
|
|
|
createSingletonCongruenceClass(&FA);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NewGVN::cleanupTables() {
|
|
|
|
for (unsigned i = 0, e = CongruenceClasses.size(); i != e; ++i) {
|
2017-04-08 02:38:09 +08:00
|
|
|
DEBUG(dbgs() << "Congruence class " << CongruenceClasses[i]->getID()
|
|
|
|
<< " has " << CongruenceClasses[i]->size() << " members\n");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Make sure we delete the congruence class (probably worth switching to
|
|
|
|
// a unique_ptr at some point.
|
|
|
|
delete CongruenceClasses[i];
|
2016-12-28 22:00:11 +08:00
|
|
|
CongruenceClasses[i] = nullptr;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ValueToClass.clear();
|
|
|
|
ArgRecycler.clear(ExpressionAllocator);
|
|
|
|
ExpressionAllocator.Reset();
|
|
|
|
CongruenceClasses.clear();
|
|
|
|
ExpressionToClass.clear();
|
|
|
|
ValueToExpression.clear();
|
|
|
|
ReachableBlocks.clear();
|
|
|
|
ReachableEdges.clear();
|
|
|
|
#ifndef NDEBUG
|
|
|
|
ProcessedCount.clear();
|
|
|
|
#endif
|
|
|
|
InstrDFS.clear();
|
|
|
|
InstructionsToErase.clear();
|
|
|
|
DFSToInstr.clear();
|
|
|
|
BlockInstRange.clear();
|
|
|
|
TouchedInstructions.clear();
|
2017-01-27 06:21:48 +08:00
|
|
|
MemoryAccessToClass.clear();
|
2017-02-19 07:06:50 +08:00
|
|
|
PredicateToUsers.clear();
|
2017-04-07 02:52:50 +08:00
|
|
|
MemoryToUsers.clear();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<unsigned, unsigned> NewGVN::assignDFSNumbers(BasicBlock *B,
|
|
|
|
unsigned Start) {
|
|
|
|
unsigned End = Start;
|
2016-12-26 06:23:49 +08:00
|
|
|
if (MemoryAccess *MemPhi = MSSA->getMemoryAccess(B)) {
|
|
|
|
InstrDFS[MemPhi] = End++;
|
2016-12-29 07:24:02 +08:00
|
|
|
DFSToInstr.emplace_back(MemPhi);
|
2016-12-26 06:23:49 +08:00
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
for (auto &I : *B) {
|
2017-03-07 02:42:27 +08:00
|
|
|
// There's no need to call isInstructionTriviallyDead more than once on
|
|
|
|
// an instruction. Therefore, once we know that an instruction is dead
|
|
|
|
// we change its DFS number so that it doesn't get value numbered.
|
|
|
|
if (isInstructionTriviallyDead(&I, TLI)) {
|
|
|
|
InstrDFS[&I] = 0;
|
|
|
|
DEBUG(dbgs() << "Skipping trivially dead instruction " << I << "\n");
|
|
|
|
markInstructionForDeletion(&I);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
InstrDFS[&I] = End++;
|
2016-12-29 07:24:02 +08:00
|
|
|
DFSToInstr.emplace_back(&I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// All of the range functions taken half-open ranges (open on the end side).
|
|
|
|
// So we do not subtract one from count, because at this point it is one
|
|
|
|
// greater than the last instruction.
|
|
|
|
return std::make_pair(Start, End);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NewGVN::updateProcessedCount(Value *V) {
|
|
|
|
#ifndef NDEBUG
|
|
|
|
if (ProcessedCount.count(V) == 0) {
|
|
|
|
ProcessedCount.insert({V, 1});
|
|
|
|
} else {
|
2017-01-15 04:13:18 +08:00
|
|
|
++ProcessedCount[V];
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
assert(ProcessedCount[V] < 100 &&
|
2016-12-30 23:01:17 +08:00
|
|
|
"Seem to have processed the same Value a lot");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
2016-12-26 06:23:49 +08:00
|
|
|
// 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
|
|
|
|
// argument.
|
2017-01-27 10:37:11 +08:00
|
|
|
// Filter out unreachable blocks and self phis from our operands.
|
2017-03-18 23:41:36 +08:00
|
|
|
const BasicBlock *PHIBlock = MP->getBlock();
|
2016-12-26 06:23:49 +08:00
|
|
|
auto Filtered = make_filter_range(MP->operands(), [&](const Use &U) {
|
2017-04-07 02:52:50 +08:00
|
|
|
return lookupMemoryLeader(cast<MemoryAccess>(U)) != MP &&
|
2017-01-27 10:37:11 +08:00
|
|
|
!isMemoryAccessTop(cast<MemoryAccess>(U)) &&
|
2017-03-18 23:41:36 +08:00
|
|
|
ReachableEdges.count({MP->getIncomingBlock(U), PHIBlock});
|
2016-12-26 06:23:49 +08:00
|
|
|
});
|
2017-01-27 10:37:11 +08:00
|
|
|
// If all that is left is nothing, our memoryphi is undef. We keep it as
|
|
|
|
// InitialClass. Note: The only case this should happen is if we have at
|
|
|
|
// least one self-argument.
|
|
|
|
if (Filtered.begin() == Filtered.end()) {
|
2017-04-07 02:52:50 +08:00
|
|
|
if (setMemoryClass(MP, TOPClass))
|
2017-01-27 10:37:11 +08:00
|
|
|
markMemoryUsersTouched(MP);
|
|
|
|
return;
|
|
|
|
}
|
2016-12-26 06:23:49 +08:00
|
|
|
|
|
|
|
// Transform the remaining operands into operand leaders.
|
|
|
|
// FIXME: mapped_iterator should have a range version.
|
|
|
|
auto LookupFunc = [&](const Use &U) {
|
2017-04-07 02:52:50 +08:00
|
|
|
return lookupMemoryLeader(cast<MemoryAccess>(U));
|
2016-12-26 06:23:49 +08:00
|
|
|
};
|
|
|
|
auto MappedBegin = map_iterator(Filtered.begin(), LookupFunc);
|
|
|
|
auto MappedEnd = map_iterator(Filtered.end(), LookupFunc);
|
|
|
|
|
|
|
|
// and now check if all the elements are equal.
|
|
|
|
// Sadly, we can't use std::equals since these are random access iterators.
|
2017-04-07 02:52:50 +08:00
|
|
|
const auto *AllSameValue = *MappedBegin;
|
2016-12-26 06:23:49 +08:00
|
|
|
++MappedBegin;
|
|
|
|
bool AllEqual = std::all_of(
|
|
|
|
MappedBegin, MappedEnd,
|
|
|
|
[&AllSameValue](const MemoryAccess *V) { return V == AllSameValue; });
|
|
|
|
|
|
|
|
if (AllEqual)
|
|
|
|
DEBUG(dbgs() << "Memory Phi value numbered to " << *AllSameValue << "\n");
|
|
|
|
else
|
|
|
|
DEBUG(dbgs() << "Memory Phi value numbered to itself\n");
|
2017-04-07 02:52:50 +08:00
|
|
|
// If it's equal to something, it's in that class. Otherwise, it has to be in
|
|
|
|
// a class where it is the leader (other things may be equivalent to it, but
|
|
|
|
// it needs to start off in its own class, which means it must have been the
|
|
|
|
// leader, and it can't have stopped being the leader because it was never
|
|
|
|
// removed).
|
|
|
|
CongruenceClass *CC =
|
|
|
|
AllEqual ? getMemoryClass(AllSameValue) : ensureLeaderOfMemoryClass(MP);
|
|
|
|
auto OldState = MemoryPhiState.lookup(MP);
|
|
|
|
assert(OldState != MPS_Invalid && "Invalid memory phi state");
|
|
|
|
auto NewState = AllEqual ? MPS_Equivalent : MPS_Unique;
|
|
|
|
MemoryPhiState[MP] = NewState;
|
|
|
|
if (setMemoryClass(MP, CC) || OldState != NewState)
|
2016-12-26 06:23:49 +08:00
|
|
|
markMemoryUsersTouched(MP);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Value number a single instruction, symbolically evaluating, performing
|
|
|
|
// congruence finding, and updating mappings.
|
|
|
|
void NewGVN::valueNumberInstruction(Instruction *I) {
|
|
|
|
DEBUG(dbgs() << "Processing instruction " << *I << "\n");
|
|
|
|
if (!I->isTerminator()) {
|
2017-03-02 03:59:26 +08:00
|
|
|
const Expression *Symbolized = nullptr;
|
|
|
|
if (DebugCounter::shouldExecute(VNCounter)) {
|
|
|
|
Symbolized = performSymbolicEvaluation(I);
|
|
|
|
} else {
|
2017-03-07 02:42:39 +08:00
|
|
|
// Mark the instruction as unused so we don't value number it again.
|
|
|
|
InstrDFS[I] = 0;
|
2017-03-02 03:59:26 +08:00
|
|
|
}
|
2017-01-03 02:00:53 +08:00
|
|
|
// If we couldn't come up with a symbolic expression, use the unknown
|
|
|
|
// expression
|
2017-04-07 02:52:50 +08:00
|
|
|
if (Symbolized == nullptr) {
|
2017-01-03 02:00:53 +08:00
|
|
|
Symbolized = createUnknownExpression(I);
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
|
|
|
|
2016-12-26 06:23:49 +08:00
|
|
|
performCongruenceFinding(I, Symbolized);
|
|
|
|
} else {
|
2017-01-03 02:00:53 +08:00
|
|
|
// Handle terminators that return values. All of them produce values we
|
2017-02-11 20:48:50 +08:00
|
|
|
// don't currently understand. We don't place non-value producing
|
|
|
|
// terminators in a class.
|
2017-01-03 02:22:38 +08:00
|
|
|
if (!I->getType()->isVoidTy()) {
|
2017-01-03 02:00:53 +08:00
|
|
|
auto *Symbolized = createUnknownExpression(I);
|
|
|
|
performCongruenceFinding(I, Symbolized);
|
|
|
|
}
|
2016-12-26 06:23:49 +08:00
|
|
|
processOutgoingEdges(dyn_cast<TerminatorInst>(I), I->getParent());
|
|
|
|
}
|
|
|
|
}
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2017-01-12 04:22:36 +08:00
|
|
|
// Check if there is a path, using single or equal argument phi nodes, from
|
|
|
|
// First to Second.
|
2017-05-19 07:22:44 +08:00
|
|
|
bool NewGVN::singleReachablePHIPath(
|
|
|
|
SmallPtrSet<const MemoryAccess *, 8> &Visited, const MemoryAccess *First,
|
|
|
|
const MemoryAccess *Second) const {
|
2017-01-12 04:22:36 +08:00
|
|
|
if (First == Second)
|
|
|
|
return true;
|
2017-04-01 17:44:24 +08:00
|
|
|
if (MSSA->isLiveOnEntryDef(First))
|
2017-01-12 04:22:36 +08:00
|
|
|
return false;
|
2017-04-07 02:52:50 +08:00
|
|
|
|
2017-05-19 07:22:44 +08:00
|
|
|
// This is not perfect, but as we're just verifying here, we can live with
|
|
|
|
// the loss of precision. The real solution would be that of doing strongly
|
|
|
|
// connected component finding in this routine, and it's probably not worth
|
|
|
|
// the complexity for the time being. So, we just keep a set of visited
|
|
|
|
// MemoryAccess and return true when we hit a cycle.
|
|
|
|
if (Visited.count(First))
|
|
|
|
return true;
|
|
|
|
Visited.insert(First);
|
|
|
|
|
2017-04-01 17:44:24 +08:00
|
|
|
const auto *EndDef = First;
|
2017-04-06 01:26:25 +08:00
|
|
|
for (auto *ChainDef : optimized_def_chain(First)) {
|
2017-04-01 17:44:24 +08:00
|
|
|
if (ChainDef == Second)
|
|
|
|
return true;
|
|
|
|
if (MSSA->isLiveOnEntryDef(ChainDef))
|
|
|
|
return false;
|
|
|
|
EndDef = ChainDef;
|
2017-01-12 04:22:36 +08:00
|
|
|
}
|
2017-04-01 17:44:24 +08:00
|
|
|
auto *MP = cast<MemoryPhi>(EndDef);
|
|
|
|
auto ReachableOperandPred = [&](const Use &U) {
|
|
|
|
return ReachableEdges.count({MP->getIncomingBlock(U), MP->getBlock()});
|
|
|
|
};
|
|
|
|
auto FilteredPhiArgs =
|
|
|
|
make_filter_range(MP->operands(), ReachableOperandPred);
|
|
|
|
SmallVector<const Value *, 32> OperandList;
|
|
|
|
std::copy(FilteredPhiArgs.begin(), FilteredPhiArgs.end(),
|
|
|
|
std::back_inserter(OperandList));
|
|
|
|
bool Okay = OperandList.size() == 1;
|
|
|
|
if (!Okay)
|
|
|
|
Okay =
|
|
|
|
std::equal(OperandList.begin(), OperandList.end(), OperandList.begin());
|
|
|
|
if (Okay)
|
2017-05-19 07:22:44 +08:00
|
|
|
return singleReachablePHIPath(Visited, cast<MemoryAccess>(OperandList[0]),
|
|
|
|
Second);
|
2017-04-01 17:44:24 +08:00
|
|
|
return false;
|
2017-01-12 04:22:36 +08:00
|
|
|
}
|
|
|
|
|
2017-01-03 02:00:46 +08:00
|
|
|
// Verify the that the memory equivalence table makes sense relative to the
|
2017-01-12 04:22:36 +08:00
|
|
|
// congruence classes. Note that this checking is not perfect, and is currently
|
2017-01-15 04:15:04 +08:00
|
|
|
// subject to very rare false negatives. It is only useful for
|
|
|
|
// testing/debugging.
|
2017-01-12 04:22:36 +08:00
|
|
|
void NewGVN::verifyMemoryCongruency() const {
|
2017-03-25 10:40:02 +08:00
|
|
|
#ifndef NDEBUG
|
2017-04-07 02:52:50 +08:00
|
|
|
// Verify that the memory table equivalence and memory member set match
|
|
|
|
for (const auto *CC : CongruenceClasses) {
|
|
|
|
if (CC == TOPClass || CC->isDead())
|
|
|
|
continue;
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC->getStoreCount() != 0) {
|
2017-04-11 07:08:35 +08:00
|
|
|
assert((CC->getStoredValue() || !isa<StoreInst>(CC->getLeader())) &&
|
2017-05-05 01:26:15 +08:00
|
|
|
"Any class with a store as a leader should have a "
|
|
|
|
"representative stored value");
|
2017-04-08 02:38:09 +08:00
|
|
|
assert(CC->getMemoryLeader() &&
|
2017-05-05 01:26:15 +08:00
|
|
|
"Any congruence class with a store should have a "
|
|
|
|
"representative access");
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
|
|
|
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC->getMemoryLeader())
|
|
|
|
assert(MemoryAccessToClass.lookup(CC->getMemoryLeader()) == CC &&
|
2017-04-07 02:52:50 +08:00
|
|
|
"Representative MemoryAccess does not appear to be reverse "
|
|
|
|
"mapped properly");
|
2017-04-08 02:38:09 +08:00
|
|
|
for (auto M : CC->memory())
|
2017-04-07 02:52:50 +08:00
|
|
|
assert(MemoryAccessToClass.lookup(M) == CC &&
|
|
|
|
"Memory member does not appear to be reverse mapped properly");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Anything equivalent in the MemoryAccess table should be in the same
|
2017-01-03 02:00:46 +08:00
|
|
|
// congruence class.
|
|
|
|
|
|
|
|
// Filter out the unreachable and trivially dead entries, because they may
|
|
|
|
// never have been updated if the instructions were not processed.
|
|
|
|
auto ReachableAccessPred =
|
2017-01-27 06:21:48 +08:00
|
|
|
[&](const std::pair<const MemoryAccess *, CongruenceClass *> Pair) {
|
2017-01-03 02:00:46 +08:00
|
|
|
bool Result = ReachableBlocks.count(Pair.first->getBlock());
|
2017-04-19 04:15:47 +08:00
|
|
|
if (!Result || MSSA->isLiveOnEntryDef(Pair.first) ||
|
|
|
|
MemoryToDFSNum(Pair.first) == 0)
|
2017-01-03 02:00:46 +08:00
|
|
|
return false;
|
|
|
|
if (auto *MemDef = dyn_cast<MemoryDef>(Pair.first))
|
|
|
|
return !isInstructionTriviallyDead(MemDef->getMemoryInst());
|
2017-05-16 02:50:53 +08:00
|
|
|
|
|
|
|
// We could have phi nodes which operands are all trivially dead,
|
|
|
|
// so we don't process them.
|
|
|
|
if (auto *MemPHI = dyn_cast<MemoryPhi>(Pair.first)) {
|
|
|
|
for (auto &U : MemPHI->incoming_values()) {
|
|
|
|
if (Instruction *I = dyn_cast<Instruction>(U.get())) {
|
|
|
|
if (!isInstructionTriviallyDead(I))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-01-03 02:00:46 +08:00
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
2017-01-27 06:21:48 +08:00
|
|
|
auto Filtered = make_filter_range(MemoryAccessToClass, ReachableAccessPred);
|
2017-01-03 02:00:46 +08:00
|
|
|
for (auto KV : Filtered) {
|
2017-04-07 02:52:50 +08:00
|
|
|
assert(KV.second != TOPClass &&
|
|
|
|
"Memory not unreachable but ended up in TOP");
|
2017-01-03 02:00:46 +08:00
|
|
|
if (auto *FirstMUD = dyn_cast<MemoryUseOrDef>(KV.first)) {
|
2017-04-08 02:38:09 +08:00
|
|
|
auto *SecondMUD = dyn_cast<MemoryUseOrDef>(KV.second->getMemoryLeader());
|
2017-05-19 07:22:44 +08:00
|
|
|
if (FirstMUD && SecondMUD) {
|
|
|
|
SmallPtrSet<const MemoryAccess *, 8> VisitedMAS;
|
|
|
|
assert((singleReachablePHIPath(VisitedMAS, FirstMUD, SecondMUD) ||
|
2017-01-15 04:15:04 +08:00
|
|
|
ValueToClass.lookup(FirstMUD->getMemoryInst()) ==
|
|
|
|
ValueToClass.lookup(SecondMUD->getMemoryInst())) &&
|
|
|
|
"The instructions for these memory operations should have "
|
|
|
|
"been in the same congruence class or reachable through"
|
|
|
|
"a single argument phi");
|
2017-05-19 07:22:44 +08:00
|
|
|
}
|
2017-01-03 02:00:46 +08:00
|
|
|
} else if (auto *FirstMP = dyn_cast<MemoryPhi>(KV.first)) {
|
|
|
|
// We can only sanely verify that MemoryDefs in the operand list all have
|
|
|
|
// the same class.
|
|
|
|
auto ReachableOperandPred = [&](const Use &U) {
|
2017-03-18 23:41:36 +08:00
|
|
|
return ReachableEdges.count(
|
|
|
|
{FirstMP->getIncomingBlock(U), FirstMP->getBlock()}) &&
|
2017-01-03 02:00:46 +08:00
|
|
|
isa<MemoryDef>(U);
|
|
|
|
|
|
|
|
};
|
|
|
|
// All arguments should in the same class, ignoring unreachable arguments
|
|
|
|
auto FilteredPhiArgs =
|
|
|
|
make_filter_range(FirstMP->operands(), ReachableOperandPred);
|
|
|
|
SmallVector<const CongruenceClass *, 16> PhiOpClasses;
|
|
|
|
std::transform(FilteredPhiArgs.begin(), FilteredPhiArgs.end(),
|
|
|
|
std::back_inserter(PhiOpClasses), [&](const Use &U) {
|
|
|
|
const MemoryDef *MD = cast<MemoryDef>(U);
|
|
|
|
return ValueToClass.lookup(MD->getMemoryInst());
|
|
|
|
});
|
|
|
|
assert(std::equal(PhiOpClasses.begin(), PhiOpClasses.end(),
|
|
|
|
PhiOpClasses.begin()) &&
|
|
|
|
"All MemoryPhi arguments should be in the same class");
|
|
|
|
}
|
|
|
|
}
|
2017-03-25 10:40:02 +08:00
|
|
|
#endif
|
2017-01-03 02:00:46 +08:00
|
|
|
}
|
|
|
|
|
2017-03-18 23:41:40 +08:00
|
|
|
// Verify that the sparse propagation we did actually found the maximal fixpoint
|
|
|
|
// We do this by storing the value to class mapping, touching all instructions,
|
|
|
|
// and redoing the iteration to see if anything changed.
|
|
|
|
void NewGVN::verifyIterationSettled(Function &F) {
|
2017-02-19 07:06:50 +08:00
|
|
|
#ifndef NDEBUG
|
2017-04-07 02:52:50 +08:00
|
|
|
DEBUG(dbgs() << "Beginning iteration verification\n");
|
2017-03-18 23:41:40 +08:00
|
|
|
if (DebugCounter::isCounterSet(VNCounter))
|
|
|
|
DebugCounter::setCounterValue(VNCounter, StartingVNCounter);
|
|
|
|
|
|
|
|
// Note that we have to store the actual classes, as we may change existing
|
|
|
|
// classes during iteration. This is because our memory iteration propagation
|
|
|
|
// is not perfect, and so may waste a little work. But it should generate
|
|
|
|
// exactly the same congruence classes we have now, with different IDs.
|
|
|
|
std::map<const Value *, CongruenceClass> BeforeIteration;
|
|
|
|
|
|
|
|
for (auto &KV : ValueToClass) {
|
|
|
|
if (auto *I = dyn_cast<Instruction>(KV.first))
|
|
|
|
// Skip unused/dead instructions.
|
2017-04-07 02:52:58 +08:00
|
|
|
if (InstrToDFSNum(I) == 0)
|
2017-02-19 07:06:50 +08:00
|
|
|
continue;
|
2017-03-18 23:41:40 +08:00
|
|
|
BeforeIteration.insert({KV.first, *KV.second});
|
|
|
|
}
|
|
|
|
|
|
|
|
TouchedInstructions.set();
|
|
|
|
TouchedInstructions.reset(0);
|
|
|
|
iterateTouchedInstructions();
|
|
|
|
DenseSet<std::pair<const CongruenceClass *, const CongruenceClass *>>
|
|
|
|
EqualClasses;
|
|
|
|
for (const auto &KV : ValueToClass) {
|
|
|
|
if (auto *I = dyn_cast<Instruction>(KV.first))
|
|
|
|
// Skip unused/dead instructions.
|
2017-04-07 02:52:58 +08:00
|
|
|
if (InstrToDFSNum(I) == 0)
|
2017-03-18 23:41:40 +08:00
|
|
|
continue;
|
|
|
|
// We could sink these uses, but i think this adds a bit of clarity here as
|
|
|
|
// to what we are comparing.
|
|
|
|
auto *BeforeCC = &BeforeIteration.find(KV.first)->second;
|
|
|
|
auto *AfterCC = KV.second;
|
|
|
|
// Note that the classes can't change at this point, so we memoize the set
|
|
|
|
// that are equal.
|
|
|
|
if (!EqualClasses.count({BeforeCC, AfterCC})) {
|
2017-04-08 02:38:09 +08:00
|
|
|
assert(BeforeCC->isEquivalentTo(AfterCC) &&
|
2017-03-18 23:41:40 +08:00
|
|
|
"Value number changed after main loop completed!");
|
|
|
|
EqualClasses.insert({BeforeCC, AfterCC});
|
2017-02-19 07:06:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-05-17 03:58:47 +08:00
|
|
|
// Verify that for each store expression in the expression to class mapping,
|
|
|
|
// only the latest appears, and multiple ones do not appear.
|
|
|
|
// Because loads do not use the stored value when doing equality with stores,
|
|
|
|
// if we don't erase the old store expressions from the table, a load can find
|
|
|
|
// a no-longer valid StoreExpression.
|
|
|
|
void NewGVN::verifyStoreExpressions() const {
|
2017-05-17 04:02:45 +08:00
|
|
|
#ifndef NDEBUG
|
2017-05-17 03:58:47 +08:00
|
|
|
DenseSet<std::pair<const Value *, const Value *>> StoreExpressionSet;
|
|
|
|
for (const auto &KV : ExpressionToClass) {
|
|
|
|
if (auto *SE = dyn_cast<StoreExpression>(KV.first)) {
|
|
|
|
// Make sure a version that will conflict with loads is not already there
|
|
|
|
auto Res =
|
|
|
|
StoreExpressionSet.insert({SE->getOperand(0), SE->getMemoryLeader()});
|
|
|
|
assert(Res.second &&
|
|
|
|
"Stored expression conflict exists in expression table");
|
|
|
|
auto *ValueExpr = ValueToExpression.lookup(SE->getStoreInst());
|
|
|
|
assert(ValueExpr && ValueExpr->equals(*SE) &&
|
|
|
|
"StoreExpression in ExpressionToClass is not latest "
|
|
|
|
"StoreExpression for value");
|
|
|
|
}
|
|
|
|
}
|
2017-05-17 04:02:45 +08:00
|
|
|
#endif
|
2017-05-17 03:58:47 +08:00
|
|
|
}
|
|
|
|
|
2017-03-18 23:41:40 +08:00
|
|
|
// This is the main value numbering loop, it iterates over the initial touched
|
|
|
|
// instruction set, propagating value numbers, marking things touched, etc,
|
|
|
|
// until the set of touched instructions is completely empty.
|
|
|
|
void NewGVN::iterateTouchedInstructions() {
|
|
|
|
unsigned int Iterations = 0;
|
|
|
|
// Figure out where touchedinstructions starts
|
|
|
|
int FirstInstr = TouchedInstructions.find_first();
|
|
|
|
// Nothing set, nothing to iterate, just return.
|
|
|
|
if (FirstInstr == -1)
|
|
|
|
return;
|
2017-04-07 02:52:58 +08:00
|
|
|
BasicBlock *LastBlock = getBlockForValue(InstrFromDFSNum(FirstInstr));
|
2017-03-18 23:41:40 +08:00
|
|
|
while (TouchedInstructions.any()) {
|
|
|
|
++Iterations;
|
|
|
|
// Walk through all the instructions in all the blocks in RPO.
|
|
|
|
// TODO: As we hit a new block, we should push and pop equalities into a
|
|
|
|
// table lookupOperandLeader can use, to catch things PredicateInfo
|
|
|
|
// might miss, like edge-only equivalences.
|
2017-05-17 09:07:53 +08:00
|
|
|
for (unsigned InstrNum : TouchedInstructions.set_bits()) {
|
2017-03-18 23:41:40 +08:00
|
|
|
|
|
|
|
// This instruction was found to be dead. We don't bother looking
|
|
|
|
// at it again.
|
|
|
|
if (InstrNum == 0) {
|
|
|
|
TouchedInstructions.reset(InstrNum);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-04-07 02:52:58 +08:00
|
|
|
Value *V = InstrFromDFSNum(InstrNum);
|
2017-03-18 23:41:40 +08:00
|
|
|
BasicBlock *CurrBlock = getBlockForValue(V);
|
|
|
|
|
|
|
|
// If we hit a new block, do reachability processing.
|
|
|
|
if (CurrBlock != LastBlock) {
|
|
|
|
LastBlock = CurrBlock;
|
|
|
|
bool BlockReachable = ReachableBlocks.count(CurrBlock);
|
|
|
|
const auto &CurrInstRange = BlockInstRange.lookup(CurrBlock);
|
|
|
|
|
|
|
|
// If it's not reachable, erase any touched instructions and move on.
|
|
|
|
if (!BlockReachable) {
|
|
|
|
TouchedInstructions.reset(CurrInstRange.first, CurrInstRange.second);
|
|
|
|
DEBUG(dbgs() << "Skipping instructions in block "
|
|
|
|
<< getBlockName(CurrBlock)
|
|
|
|
<< " because it is unreachable\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
updateProcessedCount(CurrBlock);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (auto *MP = dyn_cast<MemoryPhi>(V)) {
|
|
|
|
DEBUG(dbgs() << "Processing MemoryPhi " << *MP << "\n");
|
|
|
|
valueNumberMemoryPhi(MP);
|
|
|
|
} else if (auto *I = dyn_cast<Instruction>(V)) {
|
|
|
|
valueNumberInstruction(I);
|
|
|
|
} else {
|
|
|
|
llvm_unreachable("Should have been a MemoryPhi or Instruction");
|
|
|
|
}
|
|
|
|
updateProcessedCount(V);
|
|
|
|
// Reset after processing (because we may mark ourselves as touched when
|
|
|
|
// we propagate equalities).
|
|
|
|
TouchedInstructions.reset(InstrNum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NumGVNMaxIterations = std::max(NumGVNMaxIterations.getValue(), Iterations);
|
|
|
|
}
|
|
|
|
|
2016-12-27 04:06:58 +08:00
|
|
|
// This is the main transformation entry point.
|
2017-03-12 12:46:45 +08:00
|
|
|
bool NewGVN::runGVN() {
|
2017-03-18 23:41:40 +08:00
|
|
|
if (DebugCounter::isCounterSet(VNCounter))
|
|
|
|
StartingVNCounter = DebugCounter::getCounterValue(VNCounter);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
bool Changed = false;
|
2017-02-11 23:13:49 +08:00
|
|
|
NumFuncArgs = F.arg_size();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
MSSAWalker = MSSA->getWalker();
|
|
|
|
|
|
|
|
// Count number of instructions for sizing of hash tables, and come
|
|
|
|
// up with a global dfs numbering for instructions.
|
2016-12-30 06:15:12 +08:00
|
|
|
unsigned ICount = 1;
|
|
|
|
// Add an empty instruction to account for the fact that we start at 1
|
|
|
|
DFSToInstr.emplace_back(nullptr);
|
2017-02-19 07:06:50 +08:00
|
|
|
// Note: We want ideal RPO traversal of the blocks, which is not quite the
|
|
|
|
// same as dominator tree order, particularly with regard whether backedges
|
|
|
|
// get visited first or second, given a block with multiple successors.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// If we visit in the wrong order, we will end up performing N times as many
|
|
|
|
// iterations.
|
NewGVN: Sort Dominator Tree in RPO order, and use that for generating order.
Summary:
The optimal iteration order for this problem is RPO order. We want to
process as many preds of a backedge as we can before we process the
backedge.
At the same time, as we add predicate handling, we want to be able to
touch instructions that are dominated by a given block by
ranges (because a change in value numbering a predicate possibly
affects all users we dominate that are using that predicate).
If we don't do it this way, we can't do value inference over
backedges (the paper covers this in depth).
The newgvn branch currently overshoots the last part, and guarantees
that it will touch *at least* the right set of instructions, but it
does touch more. This is because the bitvector instruction ranges are
currently generated in RPO order (so we take the max and the min of
the ranges of dominated blocks, which means there are some in the
middle we didn't have to touch that we did).
We can do better by sorting the dominator tree, and then just using
dominator tree order.
As a preliminary, the dominator tree has some RPO guarantees, but not
enough. It guarantees that for a given node, your idom must come
before you in the RPO ordering. It guarantees no relative RPO ordering
for siblings. We add siblings in whatever order they appear in the module.
So that is what we fix.
We sort the children array of the domtree into RPO order, and then use
the dominator tree for ordering, instead of RPO, since the dominator
tree is now a valid RPO ordering.
Note: This would help any other pass that iterates a forward problem
in dominator tree order. Most of them are single pass. It will still
maximize whatever result they compute. We could also build the
dominator tree in this order, but our incremental updates would still
put it out of sort order, and recomputing the sort order is almost as
hard as general incremental updates of the domtree.
Also note that the sorting does not affect any tests, etc. Nothing
depends on domtree order, including the verifier, the equals
functions for domtree nodes, etc.
How much could this matter, you ask?
Here are the current numbers.
This is generated by running NewGVN over all files in LLVM.
Note that once we propagate equalities, the differences go up by an
order of magnitude or two (IE instead of 29, the max ends up in the
thousands, since the worst case we add a factor of N, where N is the
number of branch predicates). So while it doesn't look that stark for
the default ordering, it gets *much much* worse. There are also
programs in the wild where the difference is already pretty stark
(2 iterations vs hundreds).
RPO ordering:
759040 Number of iterations is 1
112908 Number of iterations is 2
Default dominator tree ordering:
755081 Number of iterations is 1
116234 Number of iterations is 2
603 Number of iterations is 3
27 Number of iterations is 4
2 Number of iterations is 5
1 Number of iterations is 7
Dominator tree sorted:
759040 Number of iterations is 1
112908 Number of iterations is 2
<yay!>
Really bad ordering (sort domtree siblings in postorder. not quite the
worst possible, but yeah):
754008 Number of iterations is 1
21 Number of iterations is 10
8 Number of iterations is 11
6 Number of iterations is 12
5 Number of iterations is 13
2 Number of iterations is 14
2 Number of iterations is 15
3 Number of iterations is 16
1 Number of iterations is 17
2 Number of iterations is 18
96642 Number of iterations is 2
1 Number of iterations is 20
2 Number of iterations is 21
1 Number of iterations is 22
1 Number of iterations is 29
17266 Number of iterations is 3
2598 Number of iterations is 4
798 Number of iterations is 5
273 Number of iterations is 6
186 Number of iterations is 7
80 Number of iterations is 8
42 Number of iterations is 9
Reviewers: chandlerc, davide
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D28129
llvm-svn: 290699
2016-12-29 09:12:36 +08:00
|
|
|
// The dominator tree does guarantee that, for a given dom tree node, it's
|
|
|
|
// parent must occur before it in the RPO ordering. Thus, we only need to sort
|
|
|
|
// the siblings.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
ReversePostOrderTraversal<Function *> RPOT(&F);
|
NewGVN: Sort Dominator Tree in RPO order, and use that for generating order.
Summary:
The optimal iteration order for this problem is RPO order. We want to
process as many preds of a backedge as we can before we process the
backedge.
At the same time, as we add predicate handling, we want to be able to
touch instructions that are dominated by a given block by
ranges (because a change in value numbering a predicate possibly
affects all users we dominate that are using that predicate).
If we don't do it this way, we can't do value inference over
backedges (the paper covers this in depth).
The newgvn branch currently overshoots the last part, and guarantees
that it will touch *at least* the right set of instructions, but it
does touch more. This is because the bitvector instruction ranges are
currently generated in RPO order (so we take the max and the min of
the ranges of dominated blocks, which means there are some in the
middle we didn't have to touch that we did).
We can do better by sorting the dominator tree, and then just using
dominator tree order.
As a preliminary, the dominator tree has some RPO guarantees, but not
enough. It guarantees that for a given node, your idom must come
before you in the RPO ordering. It guarantees no relative RPO ordering
for siblings. We add siblings in whatever order they appear in the module.
So that is what we fix.
We sort the children array of the domtree into RPO order, and then use
the dominator tree for ordering, instead of RPO, since the dominator
tree is now a valid RPO ordering.
Note: This would help any other pass that iterates a forward problem
in dominator tree order. Most of them are single pass. It will still
maximize whatever result they compute. We could also build the
dominator tree in this order, but our incremental updates would still
put it out of sort order, and recomputing the sort order is almost as
hard as general incremental updates of the domtree.
Also note that the sorting does not affect any tests, etc. Nothing
depends on domtree order, including the verifier, the equals
functions for domtree nodes, etc.
How much could this matter, you ask?
Here are the current numbers.
This is generated by running NewGVN over all files in LLVM.
Note that once we propagate equalities, the differences go up by an
order of magnitude or two (IE instead of 29, the max ends up in the
thousands, since the worst case we add a factor of N, where N is the
number of branch predicates). So while it doesn't look that stark for
the default ordering, it gets *much much* worse. There are also
programs in the wild where the difference is already pretty stark
(2 iterations vs hundreds).
RPO ordering:
759040 Number of iterations is 1
112908 Number of iterations is 2
Default dominator tree ordering:
755081 Number of iterations is 1
116234 Number of iterations is 2
603 Number of iterations is 3
27 Number of iterations is 4
2 Number of iterations is 5
1 Number of iterations is 7
Dominator tree sorted:
759040 Number of iterations is 1
112908 Number of iterations is 2
<yay!>
Really bad ordering (sort domtree siblings in postorder. not quite the
worst possible, but yeah):
754008 Number of iterations is 1
21 Number of iterations is 10
8 Number of iterations is 11
6 Number of iterations is 12
5 Number of iterations is 13
2 Number of iterations is 14
2 Number of iterations is 15
3 Number of iterations is 16
1 Number of iterations is 17
2 Number of iterations is 18
96642 Number of iterations is 2
1 Number of iterations is 20
2 Number of iterations is 21
1 Number of iterations is 22
1 Number of iterations is 29
17266 Number of iterations is 3
2598 Number of iterations is 4
798 Number of iterations is 5
273 Number of iterations is 6
186 Number of iterations is 7
80 Number of iterations is 8
42 Number of iterations is 9
Reviewers: chandlerc, davide
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D28129
llvm-svn: 290699
2016-12-29 09:12:36 +08:00
|
|
|
unsigned Counter = 0;
|
|
|
|
for (auto &B : RPOT) {
|
|
|
|
auto *Node = DT->getNode(B);
|
|
|
|
assert(Node && "RPO and Dominator tree should have same reachability");
|
|
|
|
RPOOrdering[Node] = ++Counter;
|
|
|
|
}
|
|
|
|
// Sort dominator tree children arrays into RPO.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
for (auto &B : RPOT) {
|
NewGVN: Sort Dominator Tree in RPO order, and use that for generating order.
Summary:
The optimal iteration order for this problem is RPO order. We want to
process as many preds of a backedge as we can before we process the
backedge.
At the same time, as we add predicate handling, we want to be able to
touch instructions that are dominated by a given block by
ranges (because a change in value numbering a predicate possibly
affects all users we dominate that are using that predicate).
If we don't do it this way, we can't do value inference over
backedges (the paper covers this in depth).
The newgvn branch currently overshoots the last part, and guarantees
that it will touch *at least* the right set of instructions, but it
does touch more. This is because the bitvector instruction ranges are
currently generated in RPO order (so we take the max and the min of
the ranges of dominated blocks, which means there are some in the
middle we didn't have to touch that we did).
We can do better by sorting the dominator tree, and then just using
dominator tree order.
As a preliminary, the dominator tree has some RPO guarantees, but not
enough. It guarantees that for a given node, your idom must come
before you in the RPO ordering. It guarantees no relative RPO ordering
for siblings. We add siblings in whatever order they appear in the module.
So that is what we fix.
We sort the children array of the domtree into RPO order, and then use
the dominator tree for ordering, instead of RPO, since the dominator
tree is now a valid RPO ordering.
Note: This would help any other pass that iterates a forward problem
in dominator tree order. Most of them are single pass. It will still
maximize whatever result they compute. We could also build the
dominator tree in this order, but our incremental updates would still
put it out of sort order, and recomputing the sort order is almost as
hard as general incremental updates of the domtree.
Also note that the sorting does not affect any tests, etc. Nothing
depends on domtree order, including the verifier, the equals
functions for domtree nodes, etc.
How much could this matter, you ask?
Here are the current numbers.
This is generated by running NewGVN over all files in LLVM.
Note that once we propagate equalities, the differences go up by an
order of magnitude or two (IE instead of 29, the max ends up in the
thousands, since the worst case we add a factor of N, where N is the
number of branch predicates). So while it doesn't look that stark for
the default ordering, it gets *much much* worse. There are also
programs in the wild where the difference is already pretty stark
(2 iterations vs hundreds).
RPO ordering:
759040 Number of iterations is 1
112908 Number of iterations is 2
Default dominator tree ordering:
755081 Number of iterations is 1
116234 Number of iterations is 2
603 Number of iterations is 3
27 Number of iterations is 4
2 Number of iterations is 5
1 Number of iterations is 7
Dominator tree sorted:
759040 Number of iterations is 1
112908 Number of iterations is 2
<yay!>
Really bad ordering (sort domtree siblings in postorder. not quite the
worst possible, but yeah):
754008 Number of iterations is 1
21 Number of iterations is 10
8 Number of iterations is 11
6 Number of iterations is 12
5 Number of iterations is 13
2 Number of iterations is 14
2 Number of iterations is 15
3 Number of iterations is 16
1 Number of iterations is 17
2 Number of iterations is 18
96642 Number of iterations is 2
1 Number of iterations is 20
2 Number of iterations is 21
1 Number of iterations is 22
1 Number of iterations is 29
17266 Number of iterations is 3
2598 Number of iterations is 4
798 Number of iterations is 5
273 Number of iterations is 6
186 Number of iterations is 7
80 Number of iterations is 8
42 Number of iterations is 9
Reviewers: chandlerc, davide
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D28129
llvm-svn: 290699
2016-12-29 09:12:36 +08:00
|
|
|
auto *Node = DT->getNode(B);
|
|
|
|
if (Node->getChildren().size() > 1)
|
|
|
|
std::sort(Node->begin(), Node->end(),
|
2017-04-14 10:53:37 +08:00
|
|
|
[&](const DomTreeNode *A, const DomTreeNode *B) {
|
NewGVN: Sort Dominator Tree in RPO order, and use that for generating order.
Summary:
The optimal iteration order for this problem is RPO order. We want to
process as many preds of a backedge as we can before we process the
backedge.
At the same time, as we add predicate handling, we want to be able to
touch instructions that are dominated by a given block by
ranges (because a change in value numbering a predicate possibly
affects all users we dominate that are using that predicate).
If we don't do it this way, we can't do value inference over
backedges (the paper covers this in depth).
The newgvn branch currently overshoots the last part, and guarantees
that it will touch *at least* the right set of instructions, but it
does touch more. This is because the bitvector instruction ranges are
currently generated in RPO order (so we take the max and the min of
the ranges of dominated blocks, which means there are some in the
middle we didn't have to touch that we did).
We can do better by sorting the dominator tree, and then just using
dominator tree order.
As a preliminary, the dominator tree has some RPO guarantees, but not
enough. It guarantees that for a given node, your idom must come
before you in the RPO ordering. It guarantees no relative RPO ordering
for siblings. We add siblings in whatever order they appear in the module.
So that is what we fix.
We sort the children array of the domtree into RPO order, and then use
the dominator tree for ordering, instead of RPO, since the dominator
tree is now a valid RPO ordering.
Note: This would help any other pass that iterates a forward problem
in dominator tree order. Most of them are single pass. It will still
maximize whatever result they compute. We could also build the
dominator tree in this order, but our incremental updates would still
put it out of sort order, and recomputing the sort order is almost as
hard as general incremental updates of the domtree.
Also note that the sorting does not affect any tests, etc. Nothing
depends on domtree order, including the verifier, the equals
functions for domtree nodes, etc.
How much could this matter, you ask?
Here are the current numbers.
This is generated by running NewGVN over all files in LLVM.
Note that once we propagate equalities, the differences go up by an
order of magnitude or two (IE instead of 29, the max ends up in the
thousands, since the worst case we add a factor of N, where N is the
number of branch predicates). So while it doesn't look that stark for
the default ordering, it gets *much much* worse. There are also
programs in the wild where the difference is already pretty stark
(2 iterations vs hundreds).
RPO ordering:
759040 Number of iterations is 1
112908 Number of iterations is 2
Default dominator tree ordering:
755081 Number of iterations is 1
116234 Number of iterations is 2
603 Number of iterations is 3
27 Number of iterations is 4
2 Number of iterations is 5
1 Number of iterations is 7
Dominator tree sorted:
759040 Number of iterations is 1
112908 Number of iterations is 2
<yay!>
Really bad ordering (sort domtree siblings in postorder. not quite the
worst possible, but yeah):
754008 Number of iterations is 1
21 Number of iterations is 10
8 Number of iterations is 11
6 Number of iterations is 12
5 Number of iterations is 13
2 Number of iterations is 14
2 Number of iterations is 15
3 Number of iterations is 16
1 Number of iterations is 17
2 Number of iterations is 18
96642 Number of iterations is 2
1 Number of iterations is 20
2 Number of iterations is 21
1 Number of iterations is 22
1 Number of iterations is 29
17266 Number of iterations is 3
2598 Number of iterations is 4
798 Number of iterations is 5
273 Number of iterations is 6
186 Number of iterations is 7
80 Number of iterations is 8
42 Number of iterations is 9
Reviewers: chandlerc, davide
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D28129
llvm-svn: 290699
2016-12-29 09:12:36 +08:00
|
|
|
return RPOOrdering[A] < RPOOrdering[B];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now a standard depth first ordering of the domtree is equivalent to RPO.
|
2017-04-19 01:06:11 +08:00
|
|
|
for (auto DTN : depth_first(DT->getRootNode())) {
|
|
|
|
BasicBlock *B = DTN->getBlock();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
const auto &BlockRange = assignDFSNumbers(B, ICount);
|
|
|
|
BlockInstRange.insert({B, BlockRange});
|
|
|
|
ICount += BlockRange.second - BlockRange.first;
|
|
|
|
}
|
|
|
|
|
2016-12-30 06:15:12 +08:00
|
|
|
TouchedInstructions.resize(ICount);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Ensure we don't end up resizing the expressionToClass map, as
|
|
|
|
// that can be quite expensive. At most, we have one expression per
|
|
|
|
// instruction.
|
2016-12-30 06:15:12 +08:00
|
|
|
ExpressionToClass.reserve(ICount);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Initialize the touched instructions to include the entry block.
|
|
|
|
const auto &InstRange = BlockInstRange.lookup(&F.getEntryBlock());
|
|
|
|
TouchedInstructions.set(InstRange.first, InstRange.second);
|
|
|
|
ReachableBlocks.insert(&F.getEntryBlock());
|
|
|
|
|
|
|
|
initializeCongruenceClasses(F);
|
2017-03-18 23:41:40 +08:00
|
|
|
iterateTouchedInstructions();
|
2017-01-03 02:00:46 +08:00
|
|
|
verifyMemoryCongruency();
|
2017-03-18 23:41:40 +08:00
|
|
|
verifyIterationSettled(F);
|
2017-05-17 03:58:47 +08:00
|
|
|
verifyStoreExpressions();
|
2017-02-19 07:06:50 +08:00
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
Changed |= eliminateInstructions(F);
|
|
|
|
|
|
|
|
// Delete all instructions marked for deletion.
|
|
|
|
for (Instruction *ToErase : InstructionsToErase) {
|
|
|
|
if (!ToErase->use_empty())
|
|
|
|
ToErase->replaceAllUsesWith(UndefValue::get(ToErase->getType()));
|
|
|
|
|
|
|
|
ToErase->eraseFromParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete all unreachable blocks.
|
2016-12-27 04:06:58 +08:00
|
|
|
auto UnreachableBlockPred = [&](const BasicBlock &BB) {
|
|
|
|
return !ReachableBlocks.count(&BB);
|
|
|
|
};
|
2016-12-27 03:57:25 +08:00
|
|
|
|
|
|
|
for (auto &BB : make_filter_range(F, UnreachableBlockPred)) {
|
|
|
|
DEBUG(dbgs() << "We believe block " << getBlockName(&BB)
|
2016-12-27 04:06:58 +08:00
|
|
|
<< " is unreachable\n");
|
2016-12-27 03:57:25 +08:00
|
|
|
deleteInstructionsInBlock(&BB);
|
|
|
|
Changed = true;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
cleanupTables();
|
|
|
|
return Changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return true if V is a value that will always be available (IE can
|
|
|
|
// be placed anywhere) in the function. We don't do globals here
|
|
|
|
// because they are often worse to put in place.
|
|
|
|
// TODO: Separate cost from availability
|
|
|
|
static bool alwaysAvailable(Value *V) {
|
|
|
|
return isa<Constant>(V) || isa<Argument>(V);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct NewGVN::ValueDFS {
|
2016-12-29 03:17:17 +08:00
|
|
|
int DFSIn = 0;
|
|
|
|
int DFSOut = 0;
|
|
|
|
int LocalNum = 0;
|
2017-03-10 08:32:26 +08:00
|
|
|
// Only one of Def and U will be set.
|
2017-04-01 17:44:33 +08:00
|
|
|
// The bool in the Def tells us whether the Def is the stored value of a
|
|
|
|
// store.
|
|
|
|
PointerIntPair<Value *, 1, bool> Def;
|
2016-12-29 03:17:17 +08:00
|
|
|
Use *U = nullptr;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
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.
|
|
|
|
// For example, if you have;
|
|
|
|
// DFS (1, 3)
|
|
|
|
// Val 0
|
|
|
|
// DFS (1, 2)
|
|
|
|
// Val 50
|
|
|
|
// We want the second to be less than the first, but if we just go field
|
|
|
|
// by field, we will get to Val 0 < Val 50 and say the first is less than
|
|
|
|
// the second. We only want it to be less than if the DFS orders are equal.
|
|
|
|
//
|
|
|
|
// Each LLVM instruction only produces one value, and thus the lowest-level
|
|
|
|
// differentiator that really matters for the stack (and what we use as as a
|
|
|
|
// replacement) is the local dfs number.
|
2016-12-27 04:06:58 +08:00
|
|
|
// Everything else in the structure is instruction level, and only affects
|
|
|
|
// the order in which we will replace operands of a given instruction.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
//
|
|
|
|
// For a given instruction (IE things with equal dfsin, dfsout, localnum),
|
|
|
|
// the order of replacement of uses does not matter.
|
|
|
|
// IE given,
|
|
|
|
// a = 5
|
|
|
|
// b = a + a
|
2016-12-27 04:06:58 +08:00
|
|
|
// When you hit b, you will have two valuedfs with the same dfsin, out, and
|
|
|
|
// localnum.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// The .val will be the same as well.
|
|
|
|
// The .u's will be different.
|
2016-12-27 04:06:58 +08:00
|
|
|
// You will replace both, and it does not matter what order you replace them
|
|
|
|
// in (IE whether you replace operand 2, then operand 1, or operand 1, then
|
|
|
|
// operand 2).
|
|
|
|
// Similarly for the case of same dfsin, dfsout, localnum, but different
|
|
|
|
// .val's
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// a = 5
|
|
|
|
// b = 6
|
|
|
|
// c = a + b
|
2016-12-27 04:06:58 +08:00
|
|
|
// in c, we will a valuedfs for a, and one for b,with everything the same
|
|
|
|
// but .val and .u.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// It does not matter what order we replace these operands in.
|
|
|
|
// You will always end up with the same IR, and this is guaranteed.
|
2017-03-10 08:32:26 +08:00
|
|
|
return std::tie(DFSIn, DFSOut, LocalNum, Def, U) <
|
|
|
|
std::tie(Other.DFSIn, Other.DFSOut, Other.LocalNum, Other.Def,
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
Other.U);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-01-27 10:37:11 +08:00
|
|
|
// This function converts the set of members for a congruence class from values,
|
2017-03-10 08:32:26 +08:00
|
|
|
// to sets of defs and uses with associated DFS info. The total number of
|
2017-03-10 08:32:33 +08:00
|
|
|
// reachable uses for each value is stored in UseCount, and instructions that
|
|
|
|
// seem
|
|
|
|
// dead (have no non-dead uses) are stored in ProbablyDead.
|
|
|
|
void NewGVN::convertClassToDFSOrdered(
|
2017-04-08 02:38:09 +08:00
|
|
|
const CongruenceClass &Dense, SmallVectorImpl<ValueDFS> &DFSOrderedSet,
|
2017-03-10 08:32:33 +08:00
|
|
|
DenseMap<const Value *, unsigned int> &UseCounts,
|
2017-04-08 02:38:09 +08:00
|
|
|
SmallPtrSetImpl<Instruction *> &ProbablyDead) const {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
for (auto D : Dense) {
|
|
|
|
// First add the value.
|
|
|
|
BasicBlock *BB = getBlockForValue(D);
|
|
|
|
// Constants are handled prior to ever calling this function, so
|
|
|
|
// we should only be left with instructions as members.
|
2016-12-23 09:38:06 +08:00
|
|
|
assert(BB && "Should have figured out a basic block for value");
|
2017-03-10 08:32:26 +08:00
|
|
|
ValueDFS VDDef;
|
2017-01-14 08:24:23 +08:00
|
|
|
DomTreeNode *DomNode = DT->getNode(BB);
|
2017-03-10 08:32:26 +08:00
|
|
|
VDDef.DFSIn = DomNode->getDFSNumIn();
|
|
|
|
VDDef.DFSOut = DomNode->getDFSNumOut();
|
2017-04-01 17:44:33 +08:00
|
|
|
// If it's a store, use the leader of the value operand, if it's always
|
|
|
|
// available, or the value operand. TODO: We could do dominance checks to
|
|
|
|
// find a dominating leader, but not worth it ATM.
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
if (auto *SI = dyn_cast<StoreInst>(D)) {
|
2017-02-01 06:31:56 +08:00
|
|
|
auto Leader = lookupOperandLeader(SI->getValueOperand());
|
2017-04-01 17:44:33 +08:00
|
|
|
if (alwaysAvailable(Leader)) {
|
|
|
|
VDDef.Def.setPointer(Leader);
|
|
|
|
} else {
|
|
|
|
VDDef.Def.setPointer(SI->getValueOperand());
|
|
|
|
VDDef.Def.setInt(true);
|
|
|
|
}
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
} else {
|
2017-04-01 17:44:33 +08:00
|
|
|
VDDef.Def.setPointer(D);
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
}
|
2017-03-10 08:32:26 +08:00
|
|
|
assert(isa<Instruction>(D) &&
|
|
|
|
"The dense set member should always be an instruction");
|
2017-04-07 02:52:58 +08:00
|
|
|
VDDef.LocalNum = InstrToDFSNum(D);
|
2017-03-10 08:32:26 +08:00
|
|
|
DFSOrderedSet.emplace_back(VDDef);
|
2017-03-10 08:32:33 +08:00
|
|
|
Instruction *Def = cast<Instruction>(D);
|
|
|
|
unsigned int UseCount = 0;
|
2017-01-14 08:24:23 +08:00
|
|
|
// Now add the uses.
|
2017-03-10 08:32:33 +08:00
|
|
|
for (auto &U : Def->uses()) {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (auto *I = dyn_cast<Instruction>(U.getUser())) {
|
2017-03-10 08:32:33 +08:00
|
|
|
// Don't try to replace into dead uses
|
|
|
|
if (InstructionsToErase.count(I))
|
|
|
|
continue;
|
2017-03-10 08:32:26 +08:00
|
|
|
ValueDFS VDUse;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Put the phi node uses in the incoming block.
|
|
|
|
BasicBlock *IBlock;
|
|
|
|
if (auto *P = dyn_cast<PHINode>(I)) {
|
|
|
|
IBlock = P->getIncomingBlock(U);
|
|
|
|
// Make phi node users appear last in the incoming block
|
|
|
|
// they are from.
|
2017-03-10 08:32:26 +08:00
|
|
|
VDUse.LocalNum = InstrDFS.size() + 1;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
} else {
|
|
|
|
IBlock = I->getParent();
|
2017-04-07 02:52:58 +08:00
|
|
|
VDUse.LocalNum = InstrToDFSNum(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
2017-01-26 08:42:42 +08:00
|
|
|
|
|
|
|
// Skip uses in unreachable blocks, as we're going
|
|
|
|
// to delete them.
|
|
|
|
if (ReachableBlocks.count(IBlock) == 0)
|
|
|
|
continue;
|
|
|
|
|
2017-01-14 08:24:23 +08:00
|
|
|
DomTreeNode *DomNode = DT->getNode(IBlock);
|
2017-03-10 08:32:26 +08:00
|
|
|
VDUse.DFSIn = DomNode->getDFSNumIn();
|
|
|
|
VDUse.DFSOut = DomNode->getDFSNumOut();
|
|
|
|
VDUse.U = &U;
|
2017-03-10 08:32:33 +08:00
|
|
|
++UseCount;
|
2017-03-10 08:32:26 +08:00
|
|
|
DFSOrderedSet.emplace_back(VDUse);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
2017-03-10 08:32:33 +08:00
|
|
|
|
|
|
|
// If there are no uses, it's probably dead (but it may have side-effects,
|
|
|
|
// so not definitely dead. Otherwise, store the number of uses so we can
|
|
|
|
// track if it becomes dead later).
|
|
|
|
if (UseCount == 0)
|
|
|
|
ProbablyDead.insert(Def);
|
|
|
|
else
|
|
|
|
UseCounts[Def] = UseCount;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-27 10:37:11 +08:00
|
|
|
// This function converts the set of members for a congruence class from values,
|
|
|
|
// to the set of defs for loads and stores, with associated DFS info.
|
2017-03-10 08:32:33 +08:00
|
|
|
void NewGVN::convertClassToLoadsAndStores(
|
2017-04-08 02:38:09 +08:00
|
|
|
const CongruenceClass &Dense,
|
|
|
|
SmallVectorImpl<ValueDFS> &LoadsAndStores) const {
|
2017-01-27 10:37:11 +08:00
|
|
|
for (auto D : Dense) {
|
|
|
|
if (!isa<LoadInst>(D) && !isa<StoreInst>(D))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
BasicBlock *BB = getBlockForValue(D);
|
|
|
|
ValueDFS VD;
|
|
|
|
DomTreeNode *DomNode = DT->getNode(BB);
|
|
|
|
VD.DFSIn = DomNode->getDFSNumIn();
|
|
|
|
VD.DFSOut = DomNode->getDFSNumOut();
|
2017-04-01 17:44:33 +08:00
|
|
|
VD.Def.setPointer(D);
|
2017-01-27 10:37:11 +08:00
|
|
|
|
|
|
|
// If it's an instruction, use the real local dfs number.
|
|
|
|
if (auto *I = dyn_cast<Instruction>(D))
|
2017-04-07 02:52:58 +08:00
|
|
|
VD.LocalNum = InstrToDFSNum(I);
|
2017-01-27 10:37:11 +08:00
|
|
|
else
|
|
|
|
llvm_unreachable("Should have been an instruction");
|
|
|
|
|
|
|
|
LoadsAndStores.emplace_back(VD);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
static void patchReplacementInstruction(Instruction *I, Value *Repl) {
|
2017-02-13 07:24:45 +08:00
|
|
|
auto *ReplInst = dyn_cast<Instruction>(Repl);
|
2017-02-13 06:25:20 +08:00
|
|
|
if (!ReplInst)
|
|
|
|
return;
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Patch the replacement so that it is not more restrictive than the value
|
|
|
|
// being replaced.
|
2017-02-13 06:25:20 +08:00
|
|
|
// Note that if 'I' is a load being replaced by some operation,
|
|
|
|
// for example, by an arithmetic operation, then andIRFlags()
|
|
|
|
// would just erase all math flags from the original arithmetic
|
|
|
|
// operation, which is clearly not wanted and not needed.
|
|
|
|
if (!isa<LoadInst>(I))
|
|
|
|
ReplInst->andIRFlags(I);
|
|
|
|
|
|
|
|
// FIXME: If both the original and replacement value are part of the
|
|
|
|
// same control-flow region (meaning that the execution of one
|
|
|
|
// guarantees the execution of the other), then we can combine the
|
|
|
|
// noalias scopes here and do better than the general conservative
|
|
|
|
// answer used in combineMetadata().
|
|
|
|
|
|
|
|
// In general, GVN unifies expressions over different control-flow
|
|
|
|
// regions, and so we need a conservative combination of the noalias
|
|
|
|
// scopes.
|
|
|
|
static const unsigned KnownIDs[] = {
|
|
|
|
LLVMContext::MD_tbaa, LLVMContext::MD_alias_scope,
|
|
|
|
LLVMContext::MD_noalias, LLVMContext::MD_range,
|
|
|
|
LLVMContext::MD_fpmath, LLVMContext::MD_invariant_load,
|
|
|
|
LLVMContext::MD_invariant_group};
|
|
|
|
combineMetadata(ReplInst, I, KnownIDs);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void patchAndReplaceAllUsesWith(Instruction *I, Value *Repl) {
|
|
|
|
patchReplacementInstruction(I, Repl);
|
|
|
|
I->replaceAllUsesWith(Repl);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NewGVN::deleteInstructionsInBlock(BasicBlock *BB) {
|
|
|
|
DEBUG(dbgs() << " BasicBlock Dead:" << *BB);
|
|
|
|
++NumGVNBlocksDeleted;
|
|
|
|
|
2017-01-31 01:06:55 +08:00
|
|
|
// Delete the instructions backwards, as it has a reduced likelihood of having
|
|
|
|
// to update as many def-use and use-def chains. Start after the terminator.
|
|
|
|
auto StartPoint = BB->rbegin();
|
|
|
|
++StartPoint;
|
|
|
|
// Note that we explicitly recalculate BB->rend() on each iteration,
|
|
|
|
// as it may change when we remove the first instruction.
|
|
|
|
for (BasicBlock::reverse_iterator I(StartPoint); I != BB->rend();) {
|
|
|
|
Instruction &Inst = *I++;
|
|
|
|
if (!Inst.use_empty())
|
|
|
|
Inst.replaceAllUsesWith(UndefValue::get(Inst.getType()));
|
|
|
|
if (isa<LandingPadInst>(Inst))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
Inst.eraseFromParent();
|
|
|
|
++NumGVNInstrDeleted;
|
|
|
|
}
|
2017-01-31 02:12:56 +08:00
|
|
|
// Now insert something that simplifycfg will turn into an unreachable.
|
|
|
|
Type *Int8Ty = Type::getInt8Ty(BB->getContext());
|
|
|
|
new StoreInst(UndefValue::get(Int8Ty),
|
|
|
|
Constant::getNullValue(Int8Ty->getPointerTo()),
|
|
|
|
BB->getTerminator());
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void NewGVN::markInstructionForDeletion(Instruction *I) {
|
|
|
|
DEBUG(dbgs() << "Marking " << *I << " for deletion\n");
|
|
|
|
InstructionsToErase.insert(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
|
|
|
|
// dependencies until we are done with everything.
|
|
|
|
markInstructionForDeletion(I);
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
// This is a stack that contains both the value and dfs info of where
|
|
|
|
// that value is valid.
|
|
|
|
class ValueDFSStack {
|
|
|
|
public:
|
|
|
|
Value *back() const { return ValueStack.back(); }
|
|
|
|
std::pair<int, int> dfs_back() const { return DFSStack.back(); }
|
|
|
|
|
|
|
|
void push_back(Value *V, int DFSIn, int DFSOut) {
|
2016-12-29 07:24:02 +08:00
|
|
|
ValueStack.emplace_back(V);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
DFSStack.emplace_back(DFSIn, DFSOut);
|
|
|
|
}
|
|
|
|
bool empty() const { return DFSStack.empty(); }
|
|
|
|
bool isInScope(int DFSIn, int DFSOut) const {
|
|
|
|
if (empty())
|
|
|
|
return false;
|
|
|
|
return DFSIn >= DFSStack.back().first && DFSOut <= DFSStack.back().second;
|
|
|
|
}
|
|
|
|
|
|
|
|
void popUntilDFSScope(int DFSIn, int DFSOut) {
|
|
|
|
|
|
|
|
// These two should always be in sync at this point.
|
|
|
|
assert(ValueStack.size() == DFSStack.size() &&
|
|
|
|
"Mismatch between ValueStack and DFSStack");
|
|
|
|
while (
|
|
|
|
!DFSStack.empty() &&
|
|
|
|
!(DFSIn >= DFSStack.back().first && DFSOut <= DFSStack.back().second)) {
|
|
|
|
DFSStack.pop_back();
|
|
|
|
ValueStack.pop_back();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
SmallVector<Value *, 8> ValueStack;
|
|
|
|
SmallVector<std::pair<int, int>, 8> DFSStack;
|
|
|
|
};
|
|
|
|
}
|
2017-01-07 11:23:47 +08:00
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
bool NewGVN::eliminateInstructions(Function &F) {
|
|
|
|
// This is a non-standard eliminator. The normal way to eliminate is
|
|
|
|
// to walk the dominator tree in order, keeping track of available
|
|
|
|
// values, and eliminating them. However, this is mildly
|
|
|
|
// pointless. It requires doing lookups on every instruction,
|
|
|
|
// regardless of whether we will ever eliminate it. For
|
2016-12-27 03:57:25 +08:00
|
|
|
// instructions part of most singleton congruence classes, we know we
|
|
|
|
// will never eliminate them.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Instead, this eliminator looks at the congruence classes directly, sorts
|
|
|
|
// them into a DFS ordering of the dominator tree, and then we just
|
2016-12-27 03:57:25 +08:00
|
|
|
// perform elimination straight on the sets by walking the congruence
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// class member uses in order, and eliminate the ones dominated by the
|
2016-12-27 03:57:25 +08:00
|
|
|
// last member. This is worst case O(E log E) where E = number of
|
|
|
|
// instructions in a single congruence class. In theory, this is all
|
|
|
|
// instructions. In practice, it is much faster, as most instructions are
|
|
|
|
// either in singleton congruence classes or can't possibly be eliminated
|
|
|
|
// anyway (if there are no overlapping DFS ranges in class).
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// When we find something not dominated, it becomes the new leader
|
2016-12-27 03:57:25 +08:00
|
|
|
// for elimination purposes.
|
|
|
|
// TODO: If we wanted to be faster, We could remove any members with no
|
|
|
|
// overlapping ranges while sorting, as we will never eliminate anything
|
|
|
|
// with those members, as they don't dominate anything else in our set.
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
bool AnythingReplaced = false;
|
|
|
|
|
|
|
|
// Since we are going to walk the domtree anyway, and we can't guarantee the
|
|
|
|
// DFS numbers are updated, we compute some ourselves.
|
|
|
|
DT->updateDFSNumbers();
|
|
|
|
|
|
|
|
for (auto &B : F) {
|
|
|
|
if (!ReachableBlocks.count(&B)) {
|
|
|
|
for (const auto S : successors(&B)) {
|
|
|
|
for (auto II = S->begin(); isa<PHINode>(II); ++II) {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto &Phi = cast<PHINode>(*II);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
DEBUG(dbgs() << "Replacing incoming value of " << *II << " for block "
|
|
|
|
<< getBlockName(&B)
|
|
|
|
<< " with undef due to it being unreachable\n");
|
|
|
|
for (auto &Operand : Phi.incoming_values())
|
|
|
|
if (Phi.getIncomingBlock(Operand) == &B)
|
|
|
|
Operand.set(UndefValue::get(Phi.getType()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-10 08:32:33 +08:00
|
|
|
// Map to store the use counts
|
|
|
|
DenseMap<const Value *, unsigned int> UseCounts;
|
2017-02-13 07:24:45 +08:00
|
|
|
for (CongruenceClass *CC : reverse(CongruenceClasses)) {
|
2017-01-27 10:37:11 +08:00
|
|
|
// Track the equivalent store info so we can decide whether to try
|
|
|
|
// dead store elimination.
|
|
|
|
SmallVector<ValueDFS, 8> PossibleDeadStores;
|
2017-03-10 08:32:33 +08:00
|
|
|
SmallPtrSet<Instruction *, 8> ProbablyDead;
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC->isDead() || CC->empty())
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
continue;
|
2017-03-11 03:05:04 +08:00
|
|
|
// Everything still in the TOP class is unreachable or dead.
|
|
|
|
if (CC == TOPClass) {
|
2017-02-11 20:48:50 +08:00
|
|
|
#ifndef NDEBUG
|
2017-04-08 02:38:09 +08:00
|
|
|
for (auto M : *CC)
|
2017-02-11 20:48:50 +08:00
|
|
|
assert((!ReachableBlocks.count(cast<Instruction>(M)->getParent()) ||
|
|
|
|
InstructionsToErase.count(cast<Instruction>(M))) &&
|
2017-03-11 03:05:04 +08:00
|
|
|
"Everything in TOP should be unreachable or dead at this "
|
2017-02-11 20:48:50 +08:00
|
|
|
"point");
|
|
|
|
#endif
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-04-08 02:38:09 +08:00
|
|
|
assert(CC->getLeader() && "We should have had a leader");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// If this is a leader that is always available, and it's a
|
|
|
|
// constant or has no equivalences, just replace everything with
|
|
|
|
// it. We then update the congruence class with whatever members
|
|
|
|
// are left.
|
2017-04-08 02:38:09 +08:00
|
|
|
Value *Leader =
|
|
|
|
CC->getStoredValue() ? CC->getStoredValue() : CC->getLeader();
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
if (alwaysAvailable(Leader)) {
|
2017-04-07 02:52:55 +08:00
|
|
|
CongruenceClass::MemberSet MembersLeft;
|
2017-04-08 02:38:09 +08:00
|
|
|
for (auto M : *CC) {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
Value *Member = M;
|
|
|
|
// Void things have no uses we can replace.
|
2017-04-07 02:52:55 +08:00
|
|
|
if (Member == Leader || !isa<Instruction>(Member) ||
|
|
|
|
Member->getType()->isVoidTy()) {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
MembersLeft.insert(Member);
|
|
|
|
continue;
|
|
|
|
}
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
DEBUG(dbgs() << "Found replacement " << *(Leader) << " for " << *Member
|
|
|
|
<< "\n");
|
2017-04-07 02:52:55 +08:00
|
|
|
auto *I = cast<Instruction>(Member);
|
|
|
|
assert(Leader != I && "About to accidentally remove our leader");
|
|
|
|
replaceInstruction(I, Leader);
|
|
|
|
AnythingReplaced = true;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
2017-04-08 02:38:09 +08:00
|
|
|
CC->swap(MembersLeft);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
} else {
|
2017-04-08 02:38:09 +08:00
|
|
|
DEBUG(dbgs() << "Eliminating in congruence class " << CC->getID()
|
|
|
|
<< "\n");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// If this is a singleton, we can skip it.
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC->size() != 1) {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// This is a stack because equality replacement/etc may place
|
|
|
|
// constants in the middle of the member list, and we want to use
|
|
|
|
// those constant values in preference to the current leader, over
|
|
|
|
// the scope of those constants.
|
|
|
|
ValueDFSStack EliminationStack;
|
|
|
|
|
|
|
|
// Convert the members to DFS ordered sets and then merge them.
|
2017-01-09 13:34:19 +08:00
|
|
|
SmallVector<ValueDFS, 8> DFSOrderedSet;
|
2017-04-08 02:38:09 +08:00
|
|
|
convertClassToDFSOrdered(*CC, DFSOrderedSet, UseCounts, ProbablyDead);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Sort the whole thing.
|
2017-01-09 13:34:19 +08:00
|
|
|
std::sort(DFSOrderedSet.begin(), DFSOrderedSet.end());
|
|
|
|
for (auto &VD : DFSOrderedSet) {
|
|
|
|
int MemberDFSIn = VD.DFSIn;
|
|
|
|
int MemberDFSOut = VD.DFSOut;
|
2017-04-01 17:44:33 +08:00
|
|
|
Value *Def = VD.Def.getPointer();
|
|
|
|
bool FromStore = VD.Def.getInt();
|
2017-03-10 08:32:33 +08:00
|
|
|
Use *U = VD.U;
|
2017-01-27 10:37:11 +08:00
|
|
|
// We ignore void things because we can't get a value from them.
|
2017-03-10 08:32:33 +08:00
|
|
|
if (Def && Def->getType()->isVoidTy())
|
2017-01-27 10:37:11 +08:00
|
|
|
continue;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
if (EliminationStack.empty()) {
|
|
|
|
DEBUG(dbgs() << "Elimination Stack is empty\n");
|
|
|
|
} else {
|
|
|
|
DEBUG(dbgs() << "Elimination Stack Top DFS numbers are ("
|
|
|
|
<< EliminationStack.dfs_back().first << ","
|
|
|
|
<< EliminationStack.dfs_back().second << ")\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG(dbgs() << "Current DFS numbers are (" << MemberDFSIn << ","
|
|
|
|
<< MemberDFSOut << ")\n");
|
|
|
|
// First, we see if we are out of scope or empty. If so,
|
|
|
|
// and there equivalences, we try to replace the top of
|
|
|
|
// stack with equivalences (if it's on the stack, it must
|
|
|
|
// not have been eliminated yet).
|
|
|
|
// Then we synchronize to our current scope, by
|
|
|
|
// popping until we are back within a DFS scope that
|
|
|
|
// dominates the current member.
|
|
|
|
// Then, what happens depends on a few factors
|
|
|
|
// If the stack is now empty, we need to push
|
|
|
|
// If we have a constant or a local equivalence we want to
|
|
|
|
// start using, we also push.
|
|
|
|
// Otherwise, we walk along, processing members who are
|
|
|
|
// dominated by this scope, and eliminate them.
|
2017-03-10 08:32:33 +08:00
|
|
|
bool ShouldPush = Def && EliminationStack.empty();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
bool OutOfScope =
|
|
|
|
!EliminationStack.isInScope(MemberDFSIn, MemberDFSOut);
|
|
|
|
|
|
|
|
if (OutOfScope || ShouldPush) {
|
|
|
|
// Sync to our current scope.
|
|
|
|
EliminationStack.popUntilDFSScope(MemberDFSIn, MemberDFSOut);
|
2017-03-10 08:32:33 +08:00
|
|
|
bool ShouldPush = Def && EliminationStack.empty();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (ShouldPush) {
|
2017-03-10 08:32:33 +08:00
|
|
|
EliminationStack.push_back(Def, MemberDFSIn, MemberDFSOut);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-10 08:32:33 +08:00
|
|
|
// Skip the Def's, we only want to eliminate on their uses. But mark
|
|
|
|
// dominated defs as dead.
|
|
|
|
if (Def) {
|
|
|
|
// For anything in this case, what and how we value number
|
|
|
|
// guarantees that any side-effets that would have occurred (ie
|
|
|
|
// throwing, etc) can be proven to either still occur (because it's
|
|
|
|
// dominated by something that has the same side-effects), or never
|
|
|
|
// occur. Otherwise, we would not have been able to prove it value
|
|
|
|
// equivalent to something else. For these things, we can just mark
|
|
|
|
// it all dead. Note that this is different from the "ProbablyDead"
|
|
|
|
// set, which may not be dominated by anything, and thus, are only
|
2017-04-01 17:44:33 +08:00
|
|
|
// easy to prove dead if they are also side-effect free. Note that
|
|
|
|
// because stores are put in terms of the stored value, we skip
|
|
|
|
// stored values here. If the stored value is really dead, it will
|
|
|
|
// still be marked for deletion when we process it in its own class.
|
2017-03-10 08:32:33 +08:00
|
|
|
if (!EliminationStack.empty() && Def != EliminationStack.back() &&
|
2017-04-01 17:44:33 +08:00
|
|
|
isa<Instruction>(Def) && !FromStore)
|
2017-03-10 08:32:33 +08:00
|
|
|
markInstructionForDeletion(cast<Instruction>(Def));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// At this point, we know it is a Use we are trying to possibly
|
|
|
|
// replace.
|
|
|
|
|
|
|
|
assert(isa<Instruction>(U->get()) &&
|
|
|
|
"Current def should have been an instruction");
|
|
|
|
assert(isa<Instruction>(U->getUser()) &&
|
|
|
|
"Current user should have been an instruction");
|
|
|
|
|
|
|
|
// If the thing we are replacing into is already marked to be dead,
|
|
|
|
// this use is dead. Note that this is true regardless of whether
|
|
|
|
// we have anything dominating the use or not. We do this here
|
|
|
|
// because we are already walking all the uses anyway.
|
|
|
|
Instruction *InstUse = cast<Instruction>(U->getUser());
|
|
|
|
if (InstructionsToErase.count(InstUse)) {
|
|
|
|
auto &UseCount = UseCounts[U->get()];
|
|
|
|
if (--UseCount == 0) {
|
|
|
|
ProbablyDead.insert(cast<Instruction>(U->get()));
|
|
|
|
}
|
2017-03-10 08:32:26 +08:00
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// If we get to this point, and the stack is empty we must have a use
|
2017-03-10 08:32:33 +08:00
|
|
|
// with nothing we can use to eliminate this use, so just skip it.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (EliminationStack.empty())
|
|
|
|
continue;
|
|
|
|
|
2017-03-10 08:32:26 +08:00
|
|
|
Value *DominatingLeader = EliminationStack.back();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2017-05-19 05:43:23 +08:00
|
|
|
auto *II = dyn_cast<IntrinsicInst>(DominatingLeader);
|
|
|
|
if (II && II->getIntrinsicID() == Intrinsic::ssa_copy)
|
|
|
|
DominatingLeader = II->getOperand(0);
|
|
|
|
|
2017-01-07 08:01:42 +08:00
|
|
|
// Don't replace our existing users with ourselves.
|
2017-03-10 08:32:33 +08:00
|
|
|
if (U->get() == DominatingLeader)
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
continue;
|
2017-03-10 08:32:26 +08:00
|
|
|
DEBUG(dbgs() << "Found replacement " << *DominatingLeader << " for "
|
2017-03-10 08:32:33 +08:00
|
|
|
<< *U->get() << " in " << *(U->getUser()) << "\n");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// If we replaced something in an instruction, handle the patching of
|
2017-03-10 08:32:33 +08:00
|
|
|
// metadata. Skip this if we are replacing predicateinfo with its
|
|
|
|
// original operand, as we already know we can just drop it.
|
|
|
|
auto *ReplacedInst = cast<Instruction>(U->get());
|
2017-03-10 08:32:26 +08:00
|
|
|
auto *PI = PredInfo->getPredicateInfoFor(ReplacedInst);
|
|
|
|
if (!PI || DominatingLeader != PI->OriginalOp)
|
|
|
|
patchReplacementInstruction(ReplacedInst, DominatingLeader);
|
2017-03-10 08:32:33 +08:00
|
|
|
U->set(DominatingLeader);
|
|
|
|
// This is now a use of the dominating leader, which means if the
|
|
|
|
// dominating leader was dead, it's now live!
|
|
|
|
auto &LeaderUseCount = UseCounts[DominatingLeader];
|
|
|
|
// It's about to be alive again.
|
|
|
|
if (LeaderUseCount == 0 && isa<Instruction>(DominatingLeader))
|
|
|
|
ProbablyDead.erase(cast<Instruction>(DominatingLeader));
|
2017-05-19 05:43:23 +08:00
|
|
|
if (LeaderUseCount == 0 && II)
|
|
|
|
ProbablyDead.insert(II);
|
2017-03-10 08:32:33 +08:00
|
|
|
++LeaderUseCount;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
AnythingReplaced = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-10 08:32:33 +08:00
|
|
|
// At this point, anything still in the ProbablyDead set is actually dead if
|
|
|
|
// would be trivially dead.
|
|
|
|
for (auto *I : ProbablyDead)
|
|
|
|
if (wouldInstructionBeTriviallyDead(I))
|
|
|
|
markInstructionForDeletion(I);
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Cleanup the congruence class.
|
2017-04-07 02:52:55 +08:00
|
|
|
CongruenceClass::MemberSet MembersLeft;
|
2017-04-08 02:38:09 +08:00
|
|
|
for (auto *Member : *CC)
|
2017-04-07 02:52:55 +08:00
|
|
|
if (!isa<Instruction>(Member) ||
|
|
|
|
!InstructionsToErase.count(cast<Instruction>(Member)))
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
MembersLeft.insert(Member);
|
2017-04-08 02:38:09 +08:00
|
|
|
CC->swap(MembersLeft);
|
2017-01-27 10:37:11 +08:00
|
|
|
|
|
|
|
// If we have possible dead stores to look at, try to eliminate them.
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC->getStoreCount() > 0) {
|
|
|
|
convertClassToLoadsAndStores(*CC, PossibleDeadStores);
|
2017-01-27 10:37:11 +08:00
|
|
|
std::sort(PossibleDeadStores.begin(), PossibleDeadStores.end());
|
|
|
|
ValueDFSStack EliminationStack;
|
|
|
|
for (auto &VD : PossibleDeadStores) {
|
|
|
|
int MemberDFSIn = VD.DFSIn;
|
|
|
|
int MemberDFSOut = VD.DFSOut;
|
2017-04-01 17:44:33 +08:00
|
|
|
Instruction *Member = cast<Instruction>(VD.Def.getPointer());
|
2017-01-27 10:37:11 +08:00
|
|
|
if (EliminationStack.empty() ||
|
|
|
|
!EliminationStack.isInScope(MemberDFSIn, MemberDFSOut)) {
|
|
|
|
// Sync to our current scope.
|
|
|
|
EliminationStack.popUntilDFSScope(MemberDFSIn, MemberDFSOut);
|
|
|
|
if (EliminationStack.empty()) {
|
|
|
|
EliminationStack.push_back(Member, MemberDFSIn, MemberDFSOut);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// We already did load elimination, so nothing to do here.
|
|
|
|
if (isa<LoadInst>(Member))
|
|
|
|
continue;
|
|
|
|
assert(!EliminationStack.empty());
|
|
|
|
Instruction *Leader = cast<Instruction>(EliminationStack.back());
|
2017-01-27 14:06:05 +08:00
|
|
|
(void)Leader;
|
2017-01-27 10:37:11 +08:00
|
|
|
assert(DT->dominates(Leader->getParent(), Member->getParent()));
|
|
|
|
// Member is dominater by Leader, and thus dead
|
|
|
|
DEBUG(dbgs() << "Marking dead store " << *Member
|
|
|
|
<< " that is dominated by " << *Leader << "\n");
|
|
|
|
markInstructionForDeletion(Member);
|
2017-04-08 02:38:09 +08:00
|
|
|
CC->erase(Member);
|
2017-01-27 10:37:11 +08:00
|
|
|
++NumGVNDeadStores;
|
|
|
|
}
|
|
|
|
}
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return AnythingReplaced;
|
|
|
|
}
|
2017-02-11 23:07:01 +08:00
|
|
|
|
|
|
|
// This function provides global ranking of operations so that we can place them
|
|
|
|
// in a canonical order. Note that rank alone is not necessarily enough for a
|
|
|
|
// complete ordering, as constants all have the same rank. However, generally,
|
|
|
|
// we will simplify an operation with all constants so that it doesn't matter
|
|
|
|
// what order they appear in.
|
|
|
|
unsigned int NewGVN::getRank(const Value *V) const {
|
2017-02-19 07:06:47 +08:00
|
|
|
// Prefer undef to anything else
|
|
|
|
if (isa<UndefValue>(V))
|
2017-02-11 23:07:01 +08:00
|
|
|
return 0;
|
2017-02-19 07:06:47 +08:00
|
|
|
if (isa<Constant>(V))
|
|
|
|
return 1;
|
2017-02-11 23:07:01 +08:00
|
|
|
else if (auto *A = dyn_cast<Argument>(V))
|
2017-02-19 07:06:47 +08:00
|
|
|
return 2 + A->getArgNo();
|
2017-02-11 23:07:01 +08:00
|
|
|
|
2017-02-19 07:06:47 +08:00
|
|
|
// Need to shift the instruction DFS by number of arguments + 3 to account for
|
2017-02-11 23:07:01 +08:00
|
|
|
// the constant and argument ranking above.
|
2017-04-07 02:52:58 +08:00
|
|
|
unsigned Result = InstrToDFSNum(V);
|
2017-02-11 23:07:01 +08:00
|
|
|
if (Result > 0)
|
2017-02-19 07:06:47 +08:00
|
|
|
return 3 + NumFuncArgs + Result;
|
2017-02-11 23:07:01 +08:00
|
|
|
// Unreachable or something else, just return a really large number.
|
|
|
|
return ~0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is a function that says whether two commutative operations should
|
|
|
|
// have their order swapped when canonicalizing.
|
|
|
|
bool NewGVN::shouldSwapOperands(const Value *A, const Value *B) const {
|
|
|
|
// Because we only care about a total ordering, and don't rewrite expressions
|
|
|
|
// in this order, we order by rank, which will give a strict weak ordering to
|
2017-02-19 07:06:47 +08:00
|
|
|
// everything but constants, and then we order by pointer address.
|
2017-02-19 07:06:50 +08:00
|
|
|
return std::make_pair(getRank(A), A) > std::make_pair(getRank(B), B);
|
2017-02-11 23:07:01 +08:00
|
|
|
}
|
2017-03-12 12:46:45 +08:00
|
|
|
|
|
|
|
class NewGVNLegacyPass : public FunctionPass {
|
|
|
|
public:
|
|
|
|
static char ID; // Pass identification, replacement for typeid.
|
|
|
|
NewGVNLegacyPass() : FunctionPass(ID) {
|
|
|
|
initializeNewGVNLegacyPassPass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
|
|
|
bool runOnFunction(Function &F) override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
|
|
|
AU.addRequired<AssumptionCacheTracker>();
|
|
|
|
AU.addRequired<DominatorTreeWrapperPass>();
|
|
|
|
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
|
|
|
AU.addRequired<MemorySSAWrapperPass>();
|
|
|
|
AU.addRequired<AAResultsWrapperPass>();
|
|
|
|
AU.addPreserved<DominatorTreeWrapperPass>();
|
|
|
|
AU.addPreserved<GlobalsAAWrapperPass>();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
bool NewGVNLegacyPass::runOnFunction(Function &F) {
|
|
|
|
if (skipFunction(F))
|
|
|
|
return false;
|
|
|
|
return NewGVN(F, &getAnalysis<DominatorTreeWrapperPass>().getDomTree(),
|
|
|
|
&getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F),
|
|
|
|
&getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(),
|
|
|
|
&getAnalysis<AAResultsWrapperPass>().getAAResults(),
|
|
|
|
&getAnalysis<MemorySSAWrapperPass>().getMSSA(),
|
|
|
|
F.getParent()->getDataLayout())
|
|
|
|
.runGVN();
|
|
|
|
}
|
|
|
|
|
|
|
|
INITIALIZE_PASS_BEGIN(NewGVNLegacyPass, "newgvn", "Global Value Numbering",
|
|
|
|
false, false)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
|
|
|
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(); }
|
|
|
|
|
|
|
|
PreservedAnalyses NewGVNPass::run(Function &F, AnalysisManager<Function> &AM) {
|
|
|
|
// Apparently the order in which we get these results matter for
|
|
|
|
// the old GVN (see Chandler's comment in GVN.cpp). I'll keep
|
|
|
|
// the same order here, just in case.
|
|
|
|
auto &AC = AM.getResult<AssumptionAnalysis>(F);
|
|
|
|
auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
|
|
|
|
auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
|
|
|
|
auto &AA = AM.getResult<AAManager>(F);
|
|
|
|
auto &MSSA = AM.getResult<MemorySSAAnalysis>(F).getMSSA();
|
|
|
|
bool Changed =
|
|
|
|
NewGVN(F, &DT, &AC, &TLI, &AA, &MSSA, F.getParent()->getDataLayout())
|
|
|
|
.runGVN();
|
|
|
|
if (!Changed)
|
|
|
|
return PreservedAnalyses::all();
|
|
|
|
PreservedAnalyses PA;
|
|
|
|
PA.preserve<DominatorTreeAnalysis>();
|
|
|
|
PA.preserve<GlobalsAA>();
|
|
|
|
return PA;
|
|
|
|
}
|