[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/Loads.h"
|
|
|
|
#include "llvm/Analysis/MemoryBuiltins.h"
|
|
|
|
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
|
|
|
|
#include "llvm/Analysis/MemoryLocation.h"
|
|
|
|
#include "llvm/Analysis/PHITransAddr.h"
|
|
|
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
|
|
|
#include "llvm/Analysis/ValueTracking.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/PredIteratorCache.h"
|
|
|
|
#include "llvm/IR/Type.h"
|
|
|
|
#include "llvm/Support/Allocator.h"
|
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Transforms/Scalar.h"
|
|
|
|
#include "llvm/Transforms/Scalar/GVNExpression.h"
|
|
|
|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
|
|
|
#include "llvm/Transforms/Utils/Local.h"
|
|
|
|
#include "llvm/Transforms/Utils/MemorySSA.h"
|
|
|
|
#include <unordered_map>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
|
|
|
using namespace llvm;
|
|
|
|
using namespace PatternMatch;
|
|
|
|
using namespace llvm::GVNExpression;
|
|
|
|
|
|
|
|
#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");
|
[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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
// 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 a randomly chosen member of the value set, it does
|
|
|
|
// not matter which one is chosen.
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
struct CongruenceClass {
|
2016-12-29 03:29:26 +08:00
|
|
|
using MemberSet = SmallPtrSet<Value *, 4>;
|
[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;
|
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 this is represented by a store, the value.
|
|
|
|
Value *RepStoredValue = nullptr;
|
2017-01-27 06:21:48 +08:00
|
|
|
// If this class contains MemoryDefs, what is the represented memory state.
|
|
|
|
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;
|
|
|
|
|
|
|
|
// True if this class has no members left. This is mainly used for assertion
|
|
|
|
// purposes, and for skipping empty classes.
|
2016-12-29 03:17:17 +08:00
|
|
|
bool Dead = false;
|
[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
|
|
|
// 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;
|
2017-01-12 04:22:36 +08:00
|
|
|
|
2017-01-14 06:40:01 +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};
|
|
|
|
|
2016-12-29 03:17:17 +08:00
|
|
|
explicit CongruenceClass(unsigned ID) : ID(ID) {}
|
[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(unsigned ID, Value *Leader, const Expression *E)
|
2016-12-29 03:17:17 +08:00
|
|
|
: ID(ID), RepLeader(Leader), DefiningExpr(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
|
|
|
};
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
class NewGVN : public FunctionPass {
|
|
|
|
DominatorTree *DT;
|
|
|
|
const DataLayout *DL;
|
|
|
|
const TargetLibraryInfo *TLI;
|
|
|
|
AssumptionCache *AC;
|
|
|
|
AliasAnalysis *AA;
|
|
|
|
MemorySSA *MSSA;
|
|
|
|
MemorySSAWalker *MSSAWalker;
|
|
|
|
BumpPtrAllocator ExpressionAllocator;
|
|
|
|
ArrayRecycler<Value *> ArgRecycler;
|
|
|
|
|
|
|
|
// Congruence class info.
|
|
|
|
CongruenceClass *InitialClass;
|
|
|
|
std::vector<CongruenceClass *> CongruenceClasses;
|
|
|
|
unsigned NextCongruenceNum;
|
|
|
|
|
|
|
|
// Value Mappings.
|
|
|
|
DenseMap<Value *, CongruenceClass *> ValueToClass;
|
|
|
|
DenseMap<Value *, const Expression *> ValueToExpression;
|
|
|
|
|
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
|
|
|
|
[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;
|
|
|
|
DenseMap<const DomTreeNode *, std::pair<unsigned, unsigned>>
|
|
|
|
DominatedInstRange;
|
|
|
|
|
|
|
|
#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:
|
|
|
|
static char ID; // Pass identification, replacement for typeid.
|
|
|
|
NewGVN() : FunctionPass(ID) {
|
|
|
|
initializeNewGVNPass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool runOnFunction(Function &F) override;
|
|
|
|
bool runGVN(Function &F, DominatorTree *DT, AssumptionCache *AC,
|
2016-12-27 04:06:58 +08:00
|
|
|
TargetLibraryInfo *TLI, AliasAnalysis *AA, MemorySSA *MSSA);
|
[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:
|
|
|
|
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>();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Expression handling.
|
|
|
|
const Expression *createExpression(Instruction *, const BasicBlock *);
|
|
|
|
const Expression *createBinaryExpression(unsigned, Type *, Value *, Value *,
|
|
|
|
const BasicBlock *);
|
|
|
|
PHIExpression *createPHIExpression(Instruction *);
|
|
|
|
const VariableExpression *createVariableExpression(Value *);
|
|
|
|
const ConstantExpression *createConstantExpression(Constant *);
|
|
|
|
const Expression *createVariableOrConstant(Value *V, const BasicBlock *B);
|
2017-01-03 02:00:53 +08:00
|
|
|
const UnknownExpression *createUnknownExpression(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
|
|
|
const StoreExpression *createStoreExpression(StoreInst *, MemoryAccess *,
|
|
|
|
const BasicBlock *);
|
|
|
|
LoadExpression *createLoadExpression(Type *, Value *, LoadInst *,
|
|
|
|
MemoryAccess *, const BasicBlock *);
|
|
|
|
|
|
|
|
const CallExpression *createCallExpression(CallInst *, MemoryAccess *,
|
|
|
|
const BasicBlock *);
|
|
|
|
const AggregateValueExpression *
|
|
|
|
createAggregateValueExpression(Instruction *, const BasicBlock *);
|
|
|
|
bool setBasicExpressionInfo(Instruction *, BasicExpression *,
|
|
|
|
const BasicBlock *);
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
CongruenceClass *createSingletonCongruenceClass(Value *Member) {
|
2016-12-28 22:00:11 +08:00
|
|
|
CongruenceClass *CClass = createCongruenceClass(Member, 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
|
|
|
CClass->Members.insert(Member);
|
|
|
|
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 *,
|
|
|
|
Value *);
|
|
|
|
const Expression *performSymbolicEvaluation(Value *, const BasicBlock *);
|
|
|
|
const Expression *performSymbolicLoadEvaluation(Instruction *,
|
|
|
|
const BasicBlock *);
|
|
|
|
const Expression *performSymbolicStoreEvaluation(Instruction *,
|
|
|
|
const BasicBlock *);
|
|
|
|
const Expression *performSymbolicCallEvaluation(Instruction *,
|
|
|
|
const BasicBlock *);
|
|
|
|
const Expression *performSymbolicPHIEvaluation(Instruction *,
|
|
|
|
const BasicBlock *);
|
|
|
|
const Expression *performSymbolicAggrValueEvaluation(Instruction *,
|
|
|
|
const BasicBlock *);
|
|
|
|
|
|
|
|
// Congruence finding.
|
|
|
|
// Templated to allow them to work both on BB's and BB-edges.
|
|
|
|
template <class T>
|
|
|
|
Value *lookupOperandLeader(Value *, const User *, const T &) const;
|
2017-01-14 06:40:01 +08:00
|
|
|
void performCongruenceFinding(Instruction *, const Expression *);
|
|
|
|
void moveValueToNewCongruenceClass(Instruction *, CongruenceClass *,
|
2017-01-12 04:22:05 +08:00
|
|
|
CongruenceClass *);
|
2017-01-27 06:21:48 +08:00
|
|
|
bool setMemoryAccessEquivTo(MemoryAccess *From, CongruenceClass *To);
|
|
|
|
MemoryAccess *lookupMemoryAccessEquiv(MemoryAccess *) const;
|
2017-01-27 10:37:11 +08:00
|
|
|
bool isMemoryAccessTop(const MemoryAccess *) const;
|
2017-01-27 06:21:48 +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
|
|
|
// Reachability handling.
|
|
|
|
void updateReachableEdge(BasicBlock *, BasicBlock *);
|
|
|
|
void processOutgoingEdges(TerminatorInst *, BasicBlock *);
|
2016-12-24 08:04:07 +08:00
|
|
|
bool isOnlyReachableViaThisEdge(const BasicBlockEdge &) 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
|
|
|
Value *findConditionEquivalence(Value *, BasicBlock *) const;
|
|
|
|
|
|
|
|
// Elimination.
|
|
|
|
struct ValueDFS;
|
2017-01-27 10:37:11 +08:00
|
|
|
void convertDenseToDFSOrdered(const CongruenceClass::MemberSet &,
|
2017-01-09 13:34:19 +08:00
|
|
|
SmallVectorImpl<ValueDFS> &);
|
2017-01-27 10:37:11 +08:00
|
|
|
void convertDenseToLoadsAndStores(const CongruenceClass::MemberSet &,
|
|
|
|
SmallVectorImpl<ValueDFS> &);
|
[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 *);
|
|
|
|
void markMemoryUsersTouched(MemoryAccess *);
|
2017-01-08 00:55:14 +08:00
|
|
|
void markLeaderChangeTouched(CongruenceClass *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
|
|
|
|
|
|
|
// 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;
|
|
|
|
bool singleReachablePHIPath(const MemoryAccess *, 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
|
|
|
};
|
|
|
|
|
|
|
|
char NewGVN::ID = 0;
|
|
|
|
|
|
|
|
// createGVNPass - The public interface to this file.
|
|
|
|
FunctionPass *llvm::createNewGVNPass() { return new NewGVN(); }
|
|
|
|
|
2016-12-28 21:37:17 +08:00
|
|
|
template <typename T>
|
|
|
|
static bool equalsLoadStoreHelper(const T &LHS, const Expression &RHS) {
|
|
|
|
if ((!isa<LoadExpression>(RHS) && !isa<StoreExpression>(RHS)) ||
|
2016-12-29 08:49:32 +08:00
|
|
|
!LHS.BasicExpression::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
|
|
|
return false;
|
2016-12-29 08:49:32 +08:00
|
|
|
} else if (const auto *L = dyn_cast<LoadExpression>(&RHS)) {
|
2016-12-28 21:37:17 +08:00
|
|
|
if (LHS.getDefiningAccess() != L->getDefiningAccess())
|
[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;
|
2016-12-29 08:49:32 +08:00
|
|
|
} else if (const auto *S = dyn_cast<StoreExpression>(&RHS)) {
|
2016-12-28 21:37:17 +08:00
|
|
|
if (LHS.getDefiningAccess() != S->getDefiningAccess())
|
[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;
|
2016-12-29 08:49:32 +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 true;
|
|
|
|
}
|
|
|
|
|
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 {
|
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
|
|
|
bool Result = equalsLoadStoreHelper(*this, Other);
|
|
|
|
// Make sure that store vs store includes the value operand.
|
|
|
|
if (Result)
|
|
|
|
if (const auto *S = dyn_cast<StoreExpression>(&Other))
|
|
|
|
if (getStoredValue() != S->getStoredValue())
|
|
|
|
return false;
|
|
|
|
return 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
|
|
|
}
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
|
|
|
INITIALIZE_PASS_BEGIN(NewGVN, "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(NewGVN, "newgvn", "Global Value Numbering", false, false)
|
|
|
|
|
|
|
|
PHIExpression *NewGVN::createPHIExpression(Instruction *I) {
|
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-01-26 07:37:49 +08:00
|
|
|
// Filter out unreachable phi operands.
|
|
|
|
auto Filtered = make_filter_range(PN->operands(), [&](const Use &U) {
|
2016-12-27 03:57:25 +08:00
|
|
|
return ReachableBlocks.count(PN->getIncomingBlock(U));
|
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),
|
|
|
|
[&](const Use &U) -> Value * {
|
2017-01-07 08:01:42 +08:00
|
|
|
// Don't try to transform self-defined phis.
|
2016-12-27 03:57:25 +08:00
|
|
|
if (U == PN)
|
|
|
|
return PN;
|
2017-01-07 08:01:42 +08:00
|
|
|
const BasicBlockEdge BBE(PN->getIncomingBlock(U), PHIBlock);
|
2016-12-27 03:57:25 +08:00
|
|
|
return lookupOperandLeader(U, I, BBE);
|
|
|
|
});
|
[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.
|
|
|
|
bool NewGVN::setBasicExpressionInfo(Instruction *I, BasicExpression *E,
|
|
|
|
const BasicBlock *B) {
|
|
|
|
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) {
|
[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 Operand = lookupOperandLeader(O, I, B);
|
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,
|
|
|
|
Value *Arg1, Value *Arg2,
|
|
|
|
const BasicBlock *B) {
|
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.
|
|
|
|
if (Arg1 > Arg2)
|
|
|
|
std::swap(Arg1, Arg2);
|
|
|
|
}
|
2016-12-26 06:10:37 +08:00
|
|
|
E->op_push_back(lookupOperandLeader(Arg1, nullptr, B));
|
|
|
|
E->op_push_back(lookupOperandLeader(Arg2, nullptr, B));
|
[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 = SimplifyBinOp(Opcode, E->getOperand(0), E->getOperand(1), *DL, TLI,
|
|
|
|
DT, AC);
|
|
|
|
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,
|
|
|
|
Instruction *I, Value *V) {
|
|
|
|
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");
|
|
|
|
|
|
|
|
cast<BasicExpression>(E)->deallocateOperands(ArgRecycler);
|
|
|
|
ExpressionAllocator.Deallocate(E);
|
|
|
|
return createConstantExpression(C);
|
|
|
|
} else if (isa<Argument>(V) || isa<GlobalVariable>(V)) {
|
|
|
|
if (I)
|
|
|
|
DEBUG(dbgs() << "Simplified " << *I << " to "
|
|
|
|
<< " variable " << *V << "\n");
|
|
|
|
cast<BasicExpression>(E)->deallocateOperands(ArgRecycler);
|
|
|
|
ExpressionAllocator.Deallocate(E);
|
|
|
|
return createVariableExpression(V);
|
|
|
|
}
|
|
|
|
|
|
|
|
CongruenceClass *CC = ValueToClass.lookup(V);
|
|
|
|
if (CC && CC->DefiningExpr) {
|
|
|
|
if (I)
|
|
|
|
DEBUG(dbgs() << "Simplified " << *I << " to "
|
|
|
|
<< " expression " << *V << "\n");
|
|
|
|
NumGVNOpsSimplified++;
|
|
|
|
assert(isa<BasicExpression>(E) &&
|
|
|
|
"We should always have had a basic expression here");
|
|
|
|
cast<BasicExpression>(E)->deallocateOperands(ArgRecycler);
|
|
|
|
ExpressionAllocator.Deallocate(E);
|
|
|
|
return CC->DefiningExpr;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Expression *NewGVN::createExpression(Instruction *I,
|
|
|
|
const BasicBlock *B) {
|
|
|
|
|
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
|
|
|
|
|
|
|
bool AllConstant = setBasicExpressionInfo(I, E, B);
|
|
|
|
|
|
|
|
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!");
|
|
|
|
if (E->getOperand(0) > E->getOperand(1))
|
|
|
|
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();
|
|
|
|
if (E->getOperand(0) > E->getOperand(1)) {
|
|
|
|
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
|
|
|
|
// TODO: Since we noop bitcasts, we may need to check types before
|
|
|
|
// simplifying, so that we don't end up simplifying based on a wrong
|
|
|
|
// type assumption. We should clean this up so we can use constants of the
|
|
|
|
// wrong type
|
|
|
|
|
|
|
|
assert(I->getOperand(0)->getType() == I->getOperand(1)->getType() &&
|
|
|
|
"Wrong types on cmp instruction");
|
|
|
|
if ((E->getOperand(0)->getType() == I->getOperand(0)->getType() &&
|
|
|
|
E->getOperand(1)->getType() == I->getOperand(1)->getType())) {
|
|
|
|
Value *V = SimplifyCmpInst(Predicate, E->getOperand(0), E->getOperand(1),
|
|
|
|
*DL, TLI, DT, AC);
|
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V))
|
|
|
|
return SimplifiedE;
|
|
|
|
}
|
|
|
|
} else if (isa<SelectInst>(I)) {
|
|
|
|
if (isa<Constant>(E->getOperand(0)) ||
|
|
|
|
(E->getOperand(1)->getType() == I->getOperand(1)->getType() &&
|
|
|
|
E->getOperand(2)->getType() == I->getOperand(2)->getType())) {
|
|
|
|
Value *V = SimplifySelectInst(E->getOperand(0), E->getOperand(1),
|
|
|
|
E->getOperand(2), *DL, TLI, DT, AC);
|
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V))
|
|
|
|
return SimplifiedE;
|
|
|
|
}
|
|
|
|
} else if (I->isBinaryOp()) {
|
|
|
|
Value *V = SimplifyBinOp(E->getOpcode(), E->getOperand(0), E->getOperand(1),
|
|
|
|
*DL, TLI, DT, AC);
|
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V))
|
|
|
|
return SimplifiedE;
|
|
|
|
} else if (auto *BI = dyn_cast<BitCastInst>(I)) {
|
|
|
|
Value *V = SimplifyInstruction(BI, *DL, TLI, DT, AC);
|
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V))
|
|
|
|
return SimplifiedE;
|
|
|
|
} else if (isa<GetElementPtrInst>(I)) {
|
|
|
|
Value *V = SimplifyGEPInst(E->getType(),
|
2016-12-26 06:10:37 +08:00
|
|
|
ArrayRef<Value *>(E->op_begin(), E->op_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
|
|
|
*DL, TLI, DT, AC);
|
|
|
|
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
|
|
|
|
|
|
|
if (Value *V = ConstantFoldInstOperands(I, C, *DL, TLI))
|
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V))
|
|
|
|
return SimplifiedE;
|
|
|
|
}
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
|
|
|
const AggregateValueExpression *
|
|
|
|
NewGVN::createAggregateValueExpression(Instruction *I, const BasicBlock *B) {
|
|
|
|
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());
|
|
|
|
setBasicExpressionInfo(I, E, B);
|
|
|
|
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());
|
|
|
|
setBasicExpressionInfo(EI, E, B);
|
|
|
|
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");
|
|
|
|
}
|
|
|
|
|
2016-12-27 04:06:58 +08:00
|
|
|
const VariableExpression *NewGVN::createVariableExpression(Value *V) {
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Expression *NewGVN::createVariableOrConstant(Value *V,
|
|
|
|
const BasicBlock *B) {
|
|
|
|
auto Leader = lookupOperandLeader(V, nullptr, B);
|
|
|
|
if (auto *C = dyn_cast<Constant>(Leader))
|
|
|
|
return createConstantExpression(C);
|
|
|
|
return createVariableExpression(Leader);
|
|
|
|
}
|
|
|
|
|
2016-12-27 04:06:58 +08:00
|
|
|
const ConstantExpression *NewGVN::createConstantExpression(Constant *C) {
|
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-01-03 02:00:53 +08:00
|
|
|
const UnknownExpression *NewGVN::createUnknownExpression(Instruction *I) {
|
|
|
|
auto *E = new (ExpressionAllocator) UnknownExpression(I);
|
|
|
|
E->setOpcode(I->getOpcode());
|
|
|
|
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
|
|
|
const CallExpression *NewGVN::createCallExpression(CallInst *CI,
|
|
|
|
MemoryAccess *HV,
|
|
|
|
const BasicBlock *B) {
|
|
|
|
// FIXME: Add operand bundles for calls.
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *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
|
|
|
new (ExpressionAllocator) CallExpression(CI->getNumOperands(), CI, HV);
|
|
|
|
setBasicExpressionInfo(CI, E, B);
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
|
|
|
// See if we have a congruence class and leader for this operand, and if so,
|
|
|
|
// return it. Otherwise, return the operand itself.
|
|
|
|
template <class T>
|
2016-12-27 04:06:58 +08:00
|
|
|
Value *NewGVN::lookupOperandLeader(Value *V, const User *U, const T &B) 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);
|
|
|
|
if (CC && (CC != InitialClass))
|
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
|
|
|
return CC->RepStoredValue ? CC->RepStoredValue : CC->RepLeader;
|
[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;
|
|
|
|
}
|
|
|
|
|
2016-12-26 06:23:49 +08:00
|
|
|
MemoryAccess *NewGVN::lookupMemoryAccessEquiv(MemoryAccess *MA) const {
|
2017-01-27 06:21:48 +08:00
|
|
|
auto *CC = MemoryAccessToClass.lookup(MA);
|
|
|
|
if (CC && CC->RepMemoryAccess)
|
|
|
|
return CC->RepMemoryAccess;
|
|
|
|
// FIXME: We need to audit all the places that current set a nullptr To, and
|
|
|
|
// fix them. There should always be *some* congruence class, even if it is
|
|
|
|
// singular. Right now, we don't bother setting congruence classes for
|
|
|
|
// anything but stores, which means we have to return the original access
|
|
|
|
// here. Otherwise, this should be unreachable.
|
|
|
|
return MA;
|
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
|
|
|
|
// state of all memory accesses.
|
|
|
|
bool NewGVN::isMemoryAccessTop(const MemoryAccess *MA) const {
|
|
|
|
return MemoryAccessToClass.lookup(MA) == InitialClass;
|
|
|
|
}
|
|
|
|
|
[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,
|
|
|
|
LoadInst *LI, MemoryAccess *DA,
|
|
|
|
const BasicBlock *B) {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *E = new (ExpressionAllocator) LoadExpression(1, LI, DA);
|
[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);
|
2016-12-27 00:19:34 +08:00
|
|
|
E->op_push_back(lookupOperandLeader(PointerOp, LI, B));
|
[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;
|
|
|
|
}
|
|
|
|
|
|
|
|
const StoreExpression *NewGVN::createStoreExpression(StoreInst *SI,
|
|
|
|
MemoryAccess *DA,
|
|
|
|
const BasicBlock *B) {
|
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 *StoredValueLeader = lookupOperandLeader(SI->getValueOperand(), SI, B);
|
|
|
|
auto *E = new (ExpressionAllocator)
|
|
|
|
StoreExpression(SI->getNumOperands(), SI, StoredValueLeader, DA);
|
[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);
|
2016-12-26 06:10:37 +08:00
|
|
|
E->op_push_back(lookupOperandLeader(SI->getPointerOperand(), SI, B));
|
[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-01-09 13:34:29 +08:00
|
|
|
// Utility function to check whether the congruence class has a member other
|
|
|
|
// than the given instruction.
|
|
|
|
bool hasMemberOtherThanUs(const CongruenceClass *CC, Instruction *I) {
|
2017-01-12 04:22:36 +08:00
|
|
|
// Either it has more than one store, in which case it must contain something
|
|
|
|
// other than us (because it's indexed by value), or if it only has one store
|
2017-01-09 13:34:29 +08:00
|
|
|
// right now, that member should not be us.
|
2017-01-12 04:22:36 +08:00
|
|
|
return CC->StoreCount > 1 || CC->Members.count(I) == 0;
|
2017-01-09 13:34:29 +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
|
|
|
const Expression *NewGVN::performSymbolicStoreEvaluation(Instruction *I,
|
|
|
|
const BasicBlock *B) {
|
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);
|
2016-12-26 06:23:49 +08:00
|
|
|
MemoryAccess *StoreAccess = MSSA->getMemoryAccess(SI);
|
2017-01-27 10:37:11 +08:00
|
|
|
// Get the expression, if any, for the RHS of the MemoryDef.
|
|
|
|
MemoryAccess *StoreRHS = lookupMemoryAccessEquiv(
|
|
|
|
cast<MemoryDef>(StoreAccess)->getDefiningAccess());
|
|
|
|
// 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-01-03 03:49:17 +08:00
|
|
|
const Expression *OldStore = createStoreExpression(SI, StoreRHS, B);
|
2017-01-03 02:00:46 +08:00
|
|
|
CongruenceClass *CC = ExpressionToClass.lookup(OldStore);
|
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-01-27 06:21:48 +08:00
|
|
|
if (CC &&
|
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
|
|
|
CC->RepStoredValue == lookupOperandLeader(SI->getValueOperand(), SI, B))
|
2017-01-03 02:00:46 +08:00
|
|
|
return createStoreExpression(SI, StoreRHS, B);
|
2017-01-27 10:37:11 +08:00
|
|
|
// Also check if our value operand is defined by a load of the same memory
|
|
|
|
// 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 (LoadInst *LI = dyn_cast<LoadInst>(SI->getValueOperand())) {
|
|
|
|
if ((lookupOperandLeader(LI->getPointerOperand(), LI, LI->getParent()) ==
|
|
|
|
lookupOperandLeader(SI->getPointerOperand(), SI, B)) &&
|
|
|
|
(lookupMemoryAccessEquiv(
|
|
|
|
MSSA->getMemoryAccess(LI)->getDefiningAccess()) == StoreRHS))
|
|
|
|
return createVariableExpression(LI);
|
|
|
|
}
|
2016-12-26 06:23:49 +08:00
|
|
|
}
|
|
|
|
return createStoreExpression(SI, StoreAccess, B);
|
[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 Expression *NewGVN::performSymbolicLoadEvaluation(Instruction *I,
|
|
|
|
const BasicBlock *B) {
|
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;
|
|
|
|
|
2016-12-27 04:06:58 +08:00
|
|
|
Value *LoadAddressLeader = lookupOperandLeader(LI->getPointerOperand(), I, B);
|
[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()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-26 06:23:49 +08:00
|
|
|
const Expression *E =
|
|
|
|
createLoadExpression(LI->getType(), LI->getPointerOperand(), LI,
|
|
|
|
lookupMemoryAccessEquiv(DefiningAccess), B);
|
[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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Evaluate read only and pure calls, and create an expression result.
|
|
|
|
const Expression *NewGVN::performSymbolicCallEvaluation(Instruction *I,
|
|
|
|
const BasicBlock *B) {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *CI = cast<CallInst>(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 (AA->doesNotAccessMemory(CI))
|
|
|
|
return createCallExpression(CI, nullptr, B);
|
2016-12-28 02:15:39 +08:00
|
|
|
if (AA->onlyReadsMemory(CI)) {
|
2016-12-27 03:57:25 +08:00
|
|
|
MemoryAccess *DefiningAccess = MSSAWalker->getClobberingMemoryAccess(CI);
|
2016-12-27 04:06:58 +08:00
|
|
|
return createCallExpression(CI, lookupMemoryAccessEquiv(DefiningAccess), B);
|
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
|
|
|
}
|
|
|
|
|
2016-12-26 06:23:49 +08:00
|
|
|
// Update the memory access equivalence table to say that From is equal to To,
|
|
|
|
// and return true if this is different from what already existed in the table.
|
2017-01-27 06:21:48 +08:00
|
|
|
// FIXME: We need to audit all the places that current set a nullptr To, and fix
|
|
|
|
// them. There should always be *some* congruence class, even if it is singular.
|
|
|
|
bool NewGVN::setMemoryAccessEquivTo(MemoryAccess *From, CongruenceClass *To) {
|
|
|
|
DEBUG(dbgs() << "Setting " << *From);
|
|
|
|
if (To) {
|
|
|
|
DEBUG(dbgs() << " equivalent to congruence class ");
|
|
|
|
DEBUG(dbgs() << To->ID << " with current memory access leader ");
|
|
|
|
DEBUG(dbgs() << *To->RepMemoryAccess);
|
|
|
|
} else {
|
|
|
|
DEBUG(dbgs() << " equivalent to itself");
|
|
|
|
}
|
2017-01-29 18:26:03 +08:00
|
|
|
DEBUG(dbgs() << "\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-01-03 02:00:46 +08:00
|
|
|
if (To && LookupResult->second != To) {
|
2016-12-26 06:23:49 +08:00
|
|
|
// It wasn't equivalent before, and now it is.
|
2017-01-03 02:00:46 +08:00
|
|
|
LookupResult->second = To;
|
2016-12-26 06:23:49 +08:00
|
|
|
Changed = true;
|
|
|
|
} else if (!To) {
|
|
|
|
// It used to be equivalent to something, and now it's not.
|
2017-01-27 06:21:48 +08:00
|
|
|
MemoryAccessToClass.erase(LookupResult);
|
2016-12-26 06:23:49 +08:00
|
|
|
Changed = true;
|
|
|
|
}
|
2017-01-03 02:00:46 +08:00
|
|
|
} else {
|
|
|
|
assert(!To &&
|
|
|
|
"Memory equivalence should never change from nothing to something");
|
2016-12-26 06:23:49 +08:00
|
|
|
}
|
2017-01-03 02:00:46 +08:00
|
|
|
|
2016-12-26 06:23:49 +08:00
|
|
|
return Changed;
|
|
|
|
}
|
[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.
|
|
|
|
const Expression *NewGVN::performSymbolicPHIEvaluation(Instruction *I,
|
|
|
|
const BasicBlock *B) {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *E = cast<PHIExpression>(createPHIExpression(I));
|
2017-01-07 08:01:42 +08:00
|
|
|
// We match the semantics of SimplifyPhiNode from InstructionSimplify here.
|
|
|
|
|
|
|
|
// See if all arguaments are the same.
|
|
|
|
// 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");
|
|
|
|
E->deallocateOperands(ArgRecycler);
|
|
|
|
ExpressionAllocator.Deallocate(E);
|
|
|
|
return createConstantExpression(UndefValue::get(I->getType()));
|
|
|
|
}
|
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.
|
|
|
|
if (llvm::all_of(Filtered, [AllSameValue](const Value *V) {
|
|
|
|
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) {
|
|
|
|
// Only have to check for instructions
|
2017-01-07 10:05:50 +08:00
|
|
|
if (auto *AllSameInst = dyn_cast<Instruction>(AllSameValue))
|
2017-01-07 08:01:42 +08:00
|
|
|
if (!DT->dominates(AllSameInst, I))
|
|
|
|
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");
|
|
|
|
E->deallocateOperands(ArgRecycler);
|
|
|
|
ExpressionAllocator.Deallocate(E);
|
|
|
|
if (auto *C = dyn_cast<Constant>(AllSameValue))
|
|
|
|
return createConstantExpression(C);
|
|
|
|
return createVariableExpression(AllSameValue);
|
|
|
|
}
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Expression *
|
|
|
|
NewGVN::performSymbolicAggrValueEvaluation(Instruction *I,
|
|
|
|
const BasicBlock *B) {
|
|
|
|
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.");
|
|
|
|
return createBinaryExpression(Opcode, EI->getType(),
|
|
|
|
II->getArgOperand(0),
|
|
|
|
II->getArgOperand(1), B);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return createAggregateValueExpression(I, B);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Substitute and symbolize the value before value numbering.
|
|
|
|
const Expression *NewGVN::performSymbolicEvaluation(Value *V,
|
|
|
|
const BasicBlock *B) {
|
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:
|
|
|
|
E = performSymbolicAggrValueEvaluation(I, B);
|
|
|
|
break;
|
|
|
|
case Instruction::PHI:
|
|
|
|
E = performSymbolicPHIEvaluation(I, B);
|
|
|
|
break;
|
|
|
|
case Instruction::Call:
|
|
|
|
E = performSymbolicCallEvaluation(I, B);
|
|
|
|
break;
|
|
|
|
case Instruction::Store:
|
|
|
|
E = performSymbolicStoreEvaluation(I, B);
|
|
|
|
break;
|
|
|
|
case Instruction::Load:
|
|
|
|
E = performSymbolicLoadEvaluation(I, B);
|
|
|
|
break;
|
|
|
|
case Instruction::BitCast: {
|
|
|
|
E = createExpression(I, B);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
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::ICmp:
|
|
|
|
case Instruction::FCmp:
|
|
|
|
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:
|
|
|
|
E = createExpression(I, B);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
|
|
|
// There is an edge from 'Src' to 'Dst'. Return true if every path from
|
|
|
|
// the entry block to 'Dst' passes via this edge. In particular 'Dst'
|
|
|
|
// must not be reachable via another edge from 'Src'.
|
2016-12-24 08:04:07 +08:00
|
|
|
bool NewGVN::isOnlyReachableViaThisEdge(const BasicBlockEdge &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
|
|
|
|
|
|
|
// While in theory it is interesting to consider the case in which Dst has
|
|
|
|
// more than one predecessor, because Dst might be part of a loop which is
|
|
|
|
// only reachable from Src, in practice it is pointless since at the time
|
|
|
|
// GVN runs all such loops have preheaders, which means that Dst will have
|
|
|
|
// been changed to have only one predecessor, namely Src.
|
|
|
|
const BasicBlock *Pred = E.getEnd()->getSinglePredecessor();
|
|
|
|
const BasicBlock *Src = E.getStart();
|
|
|
|
assert((!Pred || Pred == Src) && "No edge between these basic blocks!");
|
|
|
|
(void)Src;
|
|
|
|
return Pred != nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
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-01-15 17:18:41 +08:00
|
|
|
TouchedInstructions.set(InstrDFS.lookup(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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void NewGVN::markMemoryUsersTouched(MemoryAccess *MA) {
|
|
|
|
for (auto U : MA->users()) {
|
|
|
|
if (auto *MUD = dyn_cast<MemoryUseOrDef>(U))
|
2017-01-15 17:18:41 +08:00
|
|
|
TouchedInstructions.set(InstrDFS.lookup(MUD->getMemoryInst()));
|
[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-01-15 17:18:41 +08:00
|
|
|
TouchedInstructions.set(InstrDFS.lookup(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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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.
|
|
|
|
void NewGVN::markLeaderChangeTouched(CongruenceClass *CC) {
|
|
|
|
for (auto M : CC->Members) {
|
|
|
|
if (auto *I = dyn_cast<Instruction>(M))
|
2017-01-15 17:18:41 +08:00
|
|
|
TouchedInstructions.set(InstrDFS.lookup(I));
|
2017-01-12 04:22:05 +08:00
|
|
|
LeaderChanges.insert(M);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move a value, currently in OldClass, to be part of NewClass
|
|
|
|
// Update OldClass for the move (including changing leaders, etc)
|
2017-01-14 06:40:01 +08:00
|
|
|
void NewGVN::moveValueToNewCongruenceClass(Instruction *I,
|
|
|
|
CongruenceClass *OldClass,
|
2017-01-12 04:22:05 +08:00
|
|
|
CongruenceClass *NewClass) {
|
2017-01-14 06:40:01 +08:00
|
|
|
DEBUG(dbgs() << "New congruence class for " << I << " is " << NewClass->ID
|
2017-01-12 04:22:05 +08:00
|
|
|
<< "\n");
|
2017-01-14 06:40:01 +08:00
|
|
|
|
|
|
|
if (I == OldClass->NextLeader.first)
|
|
|
|
OldClass->NextLeader = {nullptr, ~0U};
|
|
|
|
|
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.
|
|
|
|
if (isa<Instruction>(NewClass->RepLeader) && NewClass->RepLeader &&
|
|
|
|
I != NewClass->RepLeader &&
|
|
|
|
DT->properlyDominates(
|
|
|
|
I->getParent(),
|
|
|
|
cast<Instruction>(NewClass->RepLeader)->getParent())) {
|
|
|
|
++NumGVNNotMostDominatingLeader;
|
|
|
|
assert(!isa<PHINode>(I) &&
|
|
|
|
"New class for instruction should not be dominated by instruction");
|
|
|
|
}
|
2017-01-14 06:40:01 +08:00
|
|
|
|
|
|
|
if (NewClass->RepLeader != I) {
|
|
|
|
auto DFSNum = InstrDFS.lookup(I);
|
|
|
|
if (DFSNum < NewClass->NextLeader.second)
|
|
|
|
NewClass->NextLeader = {I, DFSNum};
|
|
|
|
}
|
|
|
|
|
|
|
|
OldClass->Members.erase(I);
|
|
|
|
NewClass->Members.insert(I);
|
2017-01-27 06:21:48 +08:00
|
|
|
MemoryAccess *StoreAccess = nullptr;
|
|
|
|
if (auto *SI = dyn_cast<StoreInst>(I)) {
|
|
|
|
StoreAccess = MSSA->getMemoryAccess(SI);
|
2017-01-12 04:22:05 +08:00
|
|
|
--OldClass->StoreCount;
|
2017-01-12 06:00:29 +08:00
|
|
|
assert(OldClass->StoreCount >= 0);
|
2017-01-12 04:22:05 +08:00
|
|
|
++NewClass->StoreCount;
|
2017-01-12 07:41:24 +08:00
|
|
|
assert(NewClass->StoreCount > 0);
|
2017-01-27 06:21:48 +08:00
|
|
|
if (!NewClass->RepMemoryAccess) {
|
|
|
|
// If we don't have a representative memory access, it better be the only
|
|
|
|
// store in there.
|
|
|
|
assert(NewClass->StoreCount == 1);
|
|
|
|
NewClass->RepMemoryAccess = StoreAccess;
|
|
|
|
}
|
|
|
|
setMemoryAccessEquivTo(StoreAccess, NewClass);
|
2017-01-12 04:22:05 +08:00
|
|
|
}
|
|
|
|
|
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.
|
|
|
|
if (OldClass->Members.empty() && OldClass != InitialClass) {
|
|
|
|
if (OldClass->DefiningExpr) {
|
|
|
|
OldClass->Dead = true;
|
|
|
|
DEBUG(dbgs() << "Erasing expression " << OldClass->DefiningExpr
|
|
|
|
<< " from table\n");
|
|
|
|
ExpressionToClass.erase(OldClass->DefiningExpr);
|
|
|
|
}
|
2017-01-14 06:40:01 +08:00
|
|
|
} else if (OldClass->RepLeader == 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-01-14 06:40:01 +08:00
|
|
|
DEBUG(dbgs() << "Leader change!\n");
|
|
|
|
++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-01-27 06:21:48 +08:00
|
|
|
if (OldClass->StoreCount == 0) {
|
|
|
|
if (OldClass->RepStoredValue != nullptr)
|
|
|
|
OldClass->RepStoredValue = nullptr;
|
|
|
|
if (OldClass->RepMemoryAccess != nullptr)
|
|
|
|
OldClass->RepMemoryAccess = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we destroy the old access leader, we have to effectively destroy the
|
|
|
|
// congruence class. When it comes to scalars, anything with the same value
|
|
|
|
// is as good as any other. That means that one leader is as good as
|
|
|
|
// another, and as long as you have some leader for the value, you are
|
|
|
|
// good.. When it comes to *memory states*, only one particular thing really
|
|
|
|
// represents the definition of a given memory state. Once it goes away, we
|
|
|
|
// need to re-evaluate which pieces of memory are really still
|
|
|
|
// equivalent. The best way to do this is to re-value number things. The
|
|
|
|
// only way to really make that happen is to destroy the rest of the class.
|
|
|
|
// In order to effectively destroy the class, we reset ExpressionToClass for
|
|
|
|
// each by using the ValueToExpression mapping. The members later get
|
|
|
|
// marked as touched due to the leader change. We will create new
|
|
|
|
// congruence classes, and the pieces that are still equivalent will end
|
|
|
|
// back together in a new class. If this becomes too expensive, it is
|
|
|
|
// possible to use a versioning scheme for the congruence classes to avoid
|
|
|
|
// the expressions finding this old class.
|
|
|
|
if (OldClass->StoreCount > 0 && OldClass->RepMemoryAccess == StoreAccess) {
|
|
|
|
DEBUG(dbgs() << "Kicking everything out of class " << OldClass->ID
|
|
|
|
<< " because memory access leader changed");
|
|
|
|
for (auto Member : OldClass->Members)
|
|
|
|
ExpressionToClass.erase(ValueToExpression.lookup(Member));
|
|
|
|
}
|
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-01-14 06:40:01 +08:00
|
|
|
// We don't need to sort members if there is only 1, and we don't care about
|
|
|
|
// sorting the initial class because everything either gets out of it or is
|
|
|
|
// unreachable.
|
|
|
|
if (OldClass->Members.size() == 1 || OldClass == InitialClass) {
|
|
|
|
OldClass->RepLeader = *(OldClass->Members.begin());
|
|
|
|
} else if (OldClass->NextLeader.first) {
|
|
|
|
++NumGVNAvoidedSortedLeaderChanges;
|
|
|
|
OldClass->RepLeader = OldClass->NextLeader.first;
|
|
|
|
OldClass->NextLeader = {nullptr, ~0U};
|
|
|
|
} else {
|
|
|
|
++NumGVNSortedLeaderChanges;
|
|
|
|
// TODO: 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 ....
|
|
|
|
std::pair<Value *, unsigned> MinDFS = {nullptr, ~0U};
|
|
|
|
for (const auto X : OldClass->Members) {
|
|
|
|
auto DFSNum = InstrDFS.lookup(X);
|
|
|
|
if (DFSNum < MinDFS.second)
|
|
|
|
MinDFS = {X, DFSNum};
|
|
|
|
}
|
|
|
|
OldClass->RepLeader = MinDFS.first;
|
|
|
|
}
|
2017-01-12 04:22:05 +08:00
|
|
|
markLeaderChangeTouched(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) {
|
|
|
|
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
|
|
|
// This is guaranteed to return something, since it will at least find
|
|
|
|
// INITIAL.
|
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-01-14 06:40:01 +08:00
|
|
|
assert(!IClass->Dead && "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)) {
|
[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
|
|
|
NewClass->RepLeader = CE->getConstantValue();
|
2017-01-08 00:55:14 +08:00
|
|
|
} else if (const auto *SE = dyn_cast<StoreExpression>(E)) {
|
|
|
|
StoreInst *SI = SE->getStoreInst();
|
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
|
|
|
NewClass->RepLeader = SI;
|
|
|
|
NewClass->RepStoredValue =
|
2017-01-08 00:55:14 +08:00
|
|
|
lookupOperandLeader(SI->getValueOperand(), SI, SI->getParent());
|
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-01-14 06:40:01 +08:00
|
|
|
NewClass->RepLeader = 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
|
[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
|
|
|
<< " using expression " << *E << " at " << NewClass->ID
|
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
|
|
|
<< " and leader " << *(NewClass->RepLeader));
|
|
|
|
if (NewClass->RepStoredValue)
|
|
|
|
DEBUG(dbgs() << " and stored value " << *(NewClass->RepStoredValue));
|
|
|
|
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
|
|
|
DEBUG(dbgs() << "Hash value was " << E->getHashValue() << "\n");
|
|
|
|
} else {
|
|
|
|
EClass = lookupResult.first->second;
|
2017-01-03 02:00:46 +08:00
|
|
|
if (isa<ConstantExpression>(E))
|
|
|
|
assert(isa<Constant>(EClass->RepLeader) &&
|
|
|
|
"Any class with a constant expression should have a "
|
|
|
|
"constant 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
|
|
|
assert(EClass && "Somehow don't have an eclass");
|
|
|
|
|
|
|
|
assert(!EClass->Dead && "We accidentally looked up a dead class");
|
|
|
|
}
|
|
|
|
}
|
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) {
|
[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() << "Found class " << EClass->ID << " for expression " << E
|
|
|
|
<< "\n");
|
|
|
|
|
2017-01-12 04:22:05 +08:00
|
|
|
if (ClassChanged)
|
2017-01-14 06:40:01 +08:00
|
|
|
moveValueToNewCongruenceClass(I, IClass, EClass);
|
|
|
|
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);
|
[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-01-15 17:18:41 +08:00
|
|
|
TouchedInstructions.set(InstrDFS.lookup(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-01-15 17:18:41 +08:00
|
|
|
TouchedInstructions.set(InstrDFS.lookup(&*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.
|
|
|
|
Value *NewGVN::findConditionEquivalence(Value *Cond, BasicBlock *B) const {
|
|
|
|
auto Result = lookupOperandLeader(Cond, nullptr, B);
|
|
|
|
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();
|
|
|
|
Value *CondEvaluated = findConditionEquivalence(Cond, B);
|
|
|
|
if (!CondEvaluated) {
|
|
|
|
if (auto *I = dyn_cast<Instruction>(Cond)) {
|
|
|
|
const Expression *E = createExpression(I, B);
|
|
|
|
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();
|
|
|
|
Value *CondEvaluated = findConditionEquivalence(SwitchCond, B);
|
|
|
|
// 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.
|
|
|
|
auto CaseVal = SI->findCaseValue(CondVal);
|
|
|
|
if (CaseVal.getCaseSuccessor() == SI->getDefaultDest()) {
|
|
|
|
// 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.
|
|
|
|
BasicBlock *TargetBlock = CaseVal.getCaseSuccessor();
|
|
|
|
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
|
|
|
|
// equivalent to nothing.
|
|
|
|
if (MemoryAccess *MA = MSSA->getMemoryAccess(TI))
|
|
|
|
setMemoryAccessEquivTo(MA, 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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-27 04:06:58 +08:00
|
|
|
// The algorithm initially places the values of the routine in the INITIAL
|
|
|
|
// 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. The leader of INITIAL is the undetermined value `TOP`.
|
|
|
|
// When the algorithm has finished, values still in INITIAL are unreachable.
|
|
|
|
void NewGVN::initializeCongruenceClasses(Function &F) {
|
|
|
|
// FIXME now i can't remember why this is 2
|
|
|
|
NextCongruenceNum = 2;
|
|
|
|
// Initialize all other instructions to be in INITIAL class.
|
|
|
|
CongruenceClass::MemberSet InitialValues;
|
2016-12-28 22:00:11 +08:00
|
|
|
InitialClass = createCongruenceClass(nullptr, nullptr);
|
2017-01-27 06:21:48 +08:00
|
|
|
InitialClass->RepMemoryAccess = MSSA->getLiveOnEntryDef();
|
2017-01-03 02:00:46 +08:00
|
|
|
for (auto &B : F) {
|
|
|
|
if (auto *MP = MSSA->getMemoryAccess(&B))
|
2017-01-27 06:21:48 +08:00
|
|
|
MemoryAccessToClass[MP] = InitialClass;
|
2017-01-03 02:00:46 +08:00
|
|
|
|
2016-12-27 03:57:25 +08:00
|
|
|
for (auto &I : B) {
|
[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
|
|
|
InitialValues.insert(&I);
|
2016-12-27 03:57:25 +08:00
|
|
|
ValueToClass[&I] = InitialClass;
|
2017-01-03 02:00:46 +08:00
|
|
|
// All memory accesses 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. Note that to save time, we only initialize the
|
|
|
|
// MemoryDef's for stores and all MemoryPhis to be equal. Right now, no
|
|
|
|
// other expression can generate a memory equivalence. If we start
|
|
|
|
// handling memcpy/etc, we can expand this.
|
2017-01-12 07:41:24 +08:00
|
|
|
if (isa<StoreInst>(&I)) {
|
2017-01-27 06:21:48 +08:00
|
|
|
MemoryAccessToClass[MSSA->getMemoryAccess(&I)] = InitialClass;
|
2017-01-12 07:41:24 +08:00
|
|
|
++InitialClass->StoreCount;
|
|
|
|
assert(InitialClass->StoreCount > 0);
|
|
|
|
}
|
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
|
|
|
InitialClass->Members.swap(InitialValues);
|
|
|
|
|
|
|
|
// 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) {
|
|
|
|
DEBUG(dbgs() << "Congruence class " << CongruenceClasses[i]->ID << " has "
|
|
|
|
<< CongruenceClasses[i]->Members.size() << " members\n");
|
|
|
|
// 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();
|
|
|
|
DominatedInstRange.clear();
|
2017-01-27 06:21:48 +08:00
|
|
|
MemoryAccessToClass.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) {
|
|
|
|
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.
|
2016-12-26 06:23:49 +08:00
|
|
|
auto Filtered = make_filter_range(MP->operands(), [&](const Use &U) {
|
2017-01-27 10:37:11 +08:00
|
|
|
return lookupMemoryAccessEquiv(cast<MemoryAccess>(U)) != MP &&
|
|
|
|
!isMemoryAccessTop(cast<MemoryAccess>(U)) &&
|
|
|
|
ReachableBlocks.count(MP->getIncomingBlock(U));
|
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()) {
|
|
|
|
if (setMemoryAccessEquivTo(MP, InitialClass))
|
|
|
|
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) {
|
|
|
|
return lookupMemoryAccessEquiv(cast<MemoryAccess>(U));
|
|
|
|
};
|
|
|
|
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.
|
|
|
|
MemoryAccess *AllSameValue = *MappedBegin;
|
|
|
|
++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-01-27 06:21:48 +08:00
|
|
|
if (setMemoryAccessEquivTo(
|
|
|
|
MP, AllEqual ? MemoryAccessToClass.lookup(AllSameValue) : nullptr))
|
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");
|
2017-01-21 07:29:28 +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 numbered again.
|
|
|
|
if (InstrDFS[I] != 0 && isInstructionTriviallyDead(I, TLI)) {
|
|
|
|
InstrDFS[I] = 0;
|
2016-12-26 06:23:49 +08:00
|
|
|
DEBUG(dbgs() << "Skipping unused instruction\n");
|
2016-12-27 02:44:36 +08:00
|
|
|
markInstructionForDeletion(I);
|
2016-12-26 06:23:49 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!I->isTerminator()) {
|
2017-01-03 02:00:53 +08:00
|
|
|
const auto *Symbolized = performSymbolicEvaluation(I, I->getParent());
|
|
|
|
// If we couldn't come up with a symbolic expression, use the unknown
|
|
|
|
// expression
|
|
|
|
if (Symbolized == nullptr)
|
|
|
|
Symbolized = createUnknownExpression(I);
|
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
|
|
|
|
// don't currently understand.
|
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.
|
|
|
|
bool NewGVN::singleReachablePHIPath(const MemoryAccess *First,
|
|
|
|
const MemoryAccess *Second) const {
|
|
|
|
if (First == Second)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (auto *FirstDef = dyn_cast<MemoryUseOrDef>(First)) {
|
|
|
|
auto *DefAccess = FirstDef->getDefiningAccess();
|
|
|
|
return singleReachablePHIPath(DefAccess, Second);
|
|
|
|
} else {
|
|
|
|
auto *MP = cast<MemoryPhi>(First);
|
|
|
|
auto ReachableOperandPred = [&](const Use &U) {
|
|
|
|
return ReachableBlocks.count(MP->getIncomingBlock(U));
|
|
|
|
};
|
|
|
|
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)
|
|
|
|
return singleReachablePHIPath(cast<MemoryAccess>(OperandList[0]), Second);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-01-03 02:00:46 +08:00
|
|
|
// Anything equivalent in the memory access table should be in the same
|
|
|
|
// 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());
|
|
|
|
if (!Result)
|
|
|
|
return false;
|
|
|
|
if (auto *MemDef = dyn_cast<MemoryDef>(Pair.first))
|
|
|
|
return !isInstructionTriviallyDead(MemDef->getMemoryInst());
|
|
|
|
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) {
|
|
|
|
// Unreachable instructions may not have changed because we never process
|
|
|
|
// them.
|
|
|
|
if (!ReachableBlocks.count(KV.first->getBlock()))
|
|
|
|
continue;
|
|
|
|
if (auto *FirstMUD = dyn_cast<MemoryUseOrDef>(KV.first)) {
|
2017-01-27 06:21:48 +08:00
|
|
|
auto *SecondMUD = dyn_cast<MemoryUseOrDef>(KV.second->RepMemoryAccess);
|
2017-01-03 03:03:16 +08:00
|
|
|
if (FirstMUD && SecondMUD)
|
2017-01-12 05:58:42 +08:00
|
|
|
assert((singleReachablePHIPath(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-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) {
|
|
|
|
return ReachableBlocks.count(FirstMP->getIncomingBlock(U)) &&
|
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-27 04:06:58 +08:00
|
|
|
// This is the main transformation entry point.
|
[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::runGVN(Function &F, DominatorTree *_DT, AssumptionCache *_AC,
|
2016-12-27 04:06:58 +08:00
|
|
|
TargetLibraryInfo *_TLI, AliasAnalysis *_AA,
|
|
|
|
MemorySSA *_MSSA) {
|
[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;
|
|
|
|
DT = _DT;
|
|
|
|
AC = _AC;
|
|
|
|
TLI = _TLI;
|
|
|
|
AA = _AA;
|
|
|
|
MSSA = _MSSA;
|
|
|
|
DL = &F.getParent()->getDataLayout();
|
|
|
|
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);
|
[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
|
|
|
// Note: We want 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.
|
|
|
|
// 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.
|
|
|
|
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
|
|
|
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(),
|
|
|
|
[&RPOOrdering](const DomTreeNode *A, const DomTreeNode *B) {
|
|
|
|
return RPOOrdering[A] < RPOOrdering[B];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now a standard depth first ordering of the domtree is equivalent to RPO.
|
|
|
|
auto DFI = df_begin(DT->getRootNode());
|
|
|
|
for (auto DFE = df_end(DT->getRootNode()); DFI != DFE; ++DFI) {
|
|
|
|
BasicBlock *B = DFI->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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle forward unreachable blocks and figure out which blocks
|
|
|
|
// have single preds.
|
|
|
|
for (auto &B : F) {
|
|
|
|
// Assign numbers to unreachable blocks.
|
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
|
|
|
if (!DFI.nodeVisited(DT->getNode(&B))) {
|
[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
|
|
|
DominatedInstRange.reserve(F.size());
|
|
|
|
// 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-01-05 05:01:02 +08:00
|
|
|
unsigned int Iterations = 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
|
|
|
// We start out in the entry block.
|
|
|
|
BasicBlock *LastBlock = &F.getEntryBlock();
|
|
|
|
while (TouchedInstructions.any()) {
|
2017-01-05 05:01:02 +08:00
|
|
|
++Iterations;
|
[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
|
|
|
// Walk through all the instructions in all the blocks in RPO.
|
|
|
|
for (int InstrNum = TouchedInstructions.find_first(); InstrNum != -1;
|
|
|
|
InstrNum = TouchedInstructions.find_next(InstrNum)) {
|
2017-01-21 07:29:28 +08:00
|
|
|
|
|
|
|
// This instruction was found to be dead. We don't bother looking
|
|
|
|
// at it again.
|
|
|
|
if (InstrNum == 0) {
|
|
|
|
TouchedInstructions.reset(InstrNum);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-12-26 06:23:49 +08:00
|
|
|
Value *V = DFSToInstr[InstrNum];
|
|
|
|
BasicBlock *CurrBlock = nullptr;
|
|
|
|
|
2016-12-29 03:17:17 +08:00
|
|
|
if (auto *I = dyn_cast<Instruction>(V))
|
2016-12-26 06:23:49 +08:00
|
|
|
CurrBlock = I->getParent();
|
2016-12-29 03:17:17 +08:00
|
|
|
else if (auto *MP = dyn_cast<MemoryPhi>(V))
|
2016-12-26 06:23:49 +08:00
|
|
|
CurrBlock = MP->getBlock();
|
|
|
|
else
|
|
|
|
llvm_unreachable("DFSToInstr gave us an unknown type of 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
|
|
|
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
2016-12-29 03:17:17 +08:00
|
|
|
if (auto *MP = dyn_cast<MemoryPhi>(V)) {
|
2016-12-26 06:23:49 +08:00
|
|
|
DEBUG(dbgs() << "Processing MemoryPhi " << *MP << "\n");
|
|
|
|
valueNumberMemoryPhi(MP);
|
2016-12-29 03:17:17 +08:00
|
|
|
} else if (auto *I = dyn_cast<Instruction>(V)) {
|
2016-12-26 06:23:49 +08:00
|
|
|
valueNumberInstruction(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
|
|
|
} else {
|
2016-12-26 06:23:49 +08:00
|
|
|
llvm_unreachable("Should have been a MemoryPhi or 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
|
|
|
}
|
2016-12-26 06:23:49 +08:00
|
|
|
updateProcessedCount(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
|
|
|
// Reset after processing (because we may mark ourselves as touched when
|
|
|
|
// we propagate equalities).
|
|
|
|
TouchedInstructions.reset(InstrNum);
|
|
|
|
}
|
|
|
|
}
|
2017-01-05 05:01:02 +08:00
|
|
|
NumGVNMaxIterations = std::max(NumGVNMaxIterations.getValue(), Iterations);
|
2017-01-03 02:00:46 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
verifyMemoryCongruency();
|
|
|
|
#endif
|
[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;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NewGVN::runOnFunction(Function &F) {
|
|
|
|
if (skipFunction(F))
|
|
|
|
return false;
|
|
|
|
return runGVN(F, &getAnalysis<DominatorTreeWrapperPass>().getDomTree(),
|
|
|
|
&getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F),
|
|
|
|
&getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(),
|
|
|
|
&getAnalysis<AAResultsWrapperPass>().getAAResults(),
|
|
|
|
&getAnalysis<MemorySSAWrapperPass>().getMSSA());
|
|
|
|
}
|
|
|
|
|
2016-12-27 04:06:58 +08:00
|
|
|
PreservedAnalyses NewGVNPass::run(Function &F, AnalysisManager<Function> &AM) {
|
[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 Impl;
|
|
|
|
|
|
|
|
// 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 = Impl.runGVN(F, &DT, &AC, &TLI, &AA, &MSSA);
|
|
|
|
if (!Changed)
|
|
|
|
return PreservedAnalyses::all();
|
|
|
|
PreservedAnalyses PA;
|
|
|
|
PA.preserve<DominatorTreeAnalysis>();
|
|
|
|
PA.preserve<GlobalsAA>();
|
|
|
|
return PA;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the basic block from an instruction/value.
|
|
|
|
static BasicBlock *getBlockForValue(Value *V) {
|
|
|
|
if (auto *I = dyn_cast<Instruction>(V))
|
|
|
|
return I->getParent();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct NewGVN::ValueDFS {
|
2016-12-29 03:17:17 +08:00
|
|
|
int DFSIn = 0;
|
|
|
|
int DFSOut = 0;
|
|
|
|
int LocalNum = 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
|
|
|
// Only one of these will be set.
|
2016-12-29 03:17:17 +08:00
|
|
|
Value *Val = nullptr;
|
|
|
|
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.
|
|
|
|
return std::tie(DFSIn, DFSOut, LocalNum, Val, U) <
|
|
|
|
std::tie(Other.DFSIn, Other.DFSOut, Other.LocalNum, Other.Val,
|
|
|
|
Other.U);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-01-27 10:37:11 +08:00
|
|
|
// This function converts the set of members for a congruence class from values,
|
|
|
|
// to sets of defs and uses with associated DFS info.
|
2017-01-09 13:34:19 +08:00
|
|
|
void NewGVN::convertDenseToDFSOrdered(
|
2017-01-27 10:37:11 +08:00
|
|
|
const CongruenceClass::MemberSet &Dense,
|
2017-01-09 13:34:19 +08:00
|
|
|
SmallVectorImpl<ValueDFS> &DFSOrderedSet) {
|
[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");
|
[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
|
|
|
ValueDFS VD;
|
2017-01-14 08:24:23 +08:00
|
|
|
DomTreeNode *DomNode = DT->getNode(BB);
|
|
|
|
VD.DFSIn = DomNode->getDFSNumIn();
|
|
|
|
VD.DFSOut = DomNode->getDFSNumOut();
|
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 it's a store, use the leader of the value operand.
|
|
|
|
if (auto *SI = dyn_cast<StoreInst>(D)) {
|
|
|
|
auto Leader =
|
|
|
|
lookupOperandLeader(SI->getValueOperand(), SI, SI->getParent());
|
|
|
|
VD.Val = alwaysAvailable(Leader) ? Leader : SI->getValueOperand();
|
|
|
|
} else {
|
|
|
|
VD.Val = D;
|
|
|
|
}
|
|
|
|
|
[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>(D))
|
2017-01-15 17:18:41 +08:00
|
|
|
VD.LocalNum = InstrDFS.lookup(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
|
|
|
else
|
|
|
|
llvm_unreachable("Should have been an instruction");
|
|
|
|
|
2016-12-29 07:24:02 +08:00
|
|
|
DFSOrderedSet.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
|
|
|
|
2017-01-14 08:24:23 +08:00
|
|
|
// Now add the 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
|
|
|
for (auto &U : D->uses()) {
|
|
|
|
if (auto *I = dyn_cast<Instruction>(U.getUser())) {
|
|
|
|
ValueDFS VD;
|
|
|
|
// 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.
|
|
|
|
VD.LocalNum = InstrDFS.size() + 1;
|
|
|
|
} else {
|
|
|
|
IBlock = I->getParent();
|
2017-01-15 17:18:41 +08:00
|
|
|
VD.LocalNum = InstrDFS.lookup(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);
|
|
|
|
VD.DFSIn = DomNode->getDFSNumIn();
|
|
|
|
VD.DFSOut = DomNode->getDFSNumOut();
|
[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
|
|
|
VD.U = &U;
|
2016-12-29 07:24:02 +08:00
|
|
|
DFSOrderedSet.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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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.
|
|
|
|
void NewGVN::convertDenseToLoadsAndStores(
|
|
|
|
const CongruenceClass::MemberSet &Dense,
|
|
|
|
SmallVectorImpl<ValueDFS> &LoadsAndStores) {
|
|
|
|
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();
|
|
|
|
VD.Val = D;
|
|
|
|
|
|
|
|
// If it's an instruction, use the real local dfs number.
|
|
|
|
if (auto *I = dyn_cast<Instruction>(D))
|
|
|
|
VD.LocalNum = InstrDFS.lookup(I);
|
|
|
|
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) {
|
|
|
|
// Patch the replacement so that it is not more restrictive than the value
|
|
|
|
// being replaced.
|
|
|
|
auto *Op = dyn_cast<BinaryOperator>(I);
|
|
|
|
auto *ReplOp = dyn_cast<BinaryOperator>(Repl);
|
|
|
|
|
|
|
|
if (Op && ReplOp)
|
|
|
|
ReplOp->andIRFlags(Op);
|
|
|
|
|
|
|
|
if (auto *ReplInst = dyn_cast<Instruction>(Repl)) {
|
|
|
|
// FIXME: If both the original and replacement value are part of the
|
|
|
|
// same control-flow region (meaning that the execution of one
|
|
|
|
// guarentees the executation 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.
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
// Check to see if there are non-terminating instructions to delete.
|
|
|
|
if (isa<TerminatorInst>(BB->begin()))
|
[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;
|
2017-01-27 02:30:29 +08:00
|
|
|
|
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;
|
|
|
|
}
|
[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()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (CongruenceClass *CC : 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;
|
|
|
|
|
[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: We should eventually be able to replace everything still
|
|
|
|
// in the initial class with undef, as they should be unreachable.
|
|
|
|
// Right now, initial still contains some things we skip value
|
|
|
|
// numbering of (UNREACHABLE's, for example).
|
|
|
|
if (CC == InitialClass || CC->Dead)
|
|
|
|
continue;
|
|
|
|
assert(CC->RepLeader && "We should have had a leader");
|
|
|
|
|
|
|
|
// 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.
|
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 *Leader = CC->RepStoredValue ? CC->RepStoredValue : CC->RepLeader;
|
|
|
|
if (alwaysAvailable(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
|
|
|
SmallPtrSet<Value *, 4> MembersLeft;
|
|
|
|
for (auto M : CC->Members) {
|
|
|
|
Value *Member = M;
|
|
|
|
// Void things have no uses we can replace.
|
|
|
|
if (Member == CC->RepLeader || Member->getType()->isVoidTy()) {
|
|
|
|
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");
|
[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
|
|
|
// Due to equality propagation, these may not always be
|
|
|
|
// instructions, they may be real values. We don't really
|
|
|
|
// care about trying to replace the non-instructions.
|
|
|
|
if (auto *I = dyn_cast<Instruction>(Member)) {
|
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
|
|
|
assert(Leader != I && "About to accidentally remove our leader");
|
|
|
|
replaceInstruction(I, 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
|
|
|
AnythingReplaced = true;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
MembersLeft.insert(I);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CC->Members.swap(MembersLeft);
|
|
|
|
} else {
|
|
|
|
DEBUG(dbgs() << "Eliminating in congruence class " << CC->ID << "\n");
|
|
|
|
// If this is a singleton, we can skip it.
|
|
|
|
if (CC->Members.size() != 1) {
|
|
|
|
|
|
|
|
// 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;
|
[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
|
|
|
convertDenseToDFSOrdered(CC->Members, DFSOrderedSet);
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
Value *Member = VD.Val;
|
|
|
|
Use *MemberUse = VD.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
|
|
|
|
2017-01-27 10:37:11 +08:00
|
|
|
// We ignore void things because we can't get a value from them.
|
|
|
|
if (Member && Member->getType()->isVoidTy())
|
|
|
|
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.
|
|
|
|
bool ShouldPush =
|
|
|
|
Member && (EliminationStack.empty() || isa<Constant>(Member));
|
|
|
|
bool OutOfScope =
|
|
|
|
!EliminationStack.isInScope(MemberDFSIn, MemberDFSOut);
|
|
|
|
|
|
|
|
if (OutOfScope || ShouldPush) {
|
|
|
|
// Sync to our current scope.
|
|
|
|
EliminationStack.popUntilDFSScope(MemberDFSIn, MemberDFSOut);
|
|
|
|
ShouldPush |= Member && EliminationStack.empty();
|
|
|
|
if (ShouldPush) {
|
|
|
|
EliminationStack.push_back(Member, MemberDFSIn, MemberDFSOut);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we get to this point, and the stack is empty we must have a use
|
|
|
|
// with nothing we can use to eliminate it, just skip it.
|
|
|
|
if (EliminationStack.empty())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Skip the Value's, we only want to eliminate on their uses.
|
|
|
|
if (Member)
|
|
|
|
continue;
|
|
|
|
Value *Result = EliminationStack.back();
|
|
|
|
|
2017-01-07 08:01:42 +08:00
|
|
|
// Don't replace our existing users with ourselves.
|
|
|
|
if (MemberUse->get() == 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
|
|
|
continue;
|
|
|
|
|
|
|
|
DEBUG(dbgs() << "Found replacement " << *Result << " for "
|
|
|
|
<< *MemberUse->get() << " in " << *(MemberUse->getUser())
|
|
|
|
<< "\n");
|
|
|
|
|
|
|
|
// If we replaced something in an instruction, handle the patching of
|
|
|
|
// metadata.
|
2016-12-27 04:06:58 +08:00
|
|
|
if (auto *ReplacedInst = dyn_cast<Instruction>(MemberUse->get()))
|
[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
|
|
|
patchReplacementInstruction(ReplacedInst, Result);
|
|
|
|
|
|
|
|
assert(isa<Instruction>(MemberUse->getUser()));
|
|
|
|
MemberUse->set(Result);
|
|
|
|
AnythingReplaced = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Cleanup the congruence class.
|
|
|
|
SmallPtrSet<Value *, 4> MembersLeft;
|
2017-01-03 02:22:38 +08:00
|
|
|
for (Value *Member : CC->Members) {
|
[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 (Member->getType()->isVoidTy()) {
|
|
|
|
MembersLeft.insert(Member);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (auto *MemberInst = dyn_cast<Instruction>(Member)) {
|
|
|
|
if (isInstructionTriviallyDead(MemberInst)) {
|
|
|
|
// TODO: Don't mark loads of undefs.
|
|
|
|
markInstructionForDeletion(MemberInst);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MembersLeft.insert(Member);
|
|
|
|
}
|
|
|
|
CC->Members.swap(MembersLeft);
|
2017-01-27 10:37:11 +08:00
|
|
|
|
|
|
|
// If we have possible dead stores to look at, try to eliminate them.
|
|
|
|
if (CC->StoreCount > 0) {
|
|
|
|
convertDenseToLoadsAndStores(CC->Members, PossibleDeadStores);
|
|
|
|
std::sort(PossibleDeadStores.begin(), PossibleDeadStores.end());
|
|
|
|
ValueDFSStack EliminationStack;
|
|
|
|
for (auto &VD : PossibleDeadStores) {
|
|
|
|
int MemberDFSIn = VD.DFSIn;
|
|
|
|
int MemberDFSOut = VD.DFSOut;
|
|
|
|
Instruction *Member = cast<Instruction>(VD.Val);
|
|
|
|
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);
|
|
|
|
CC->Members.erase(Member);
|
|
|
|
++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;
|
|
|
|
}
|