2017-10-21 05:47:29 +08:00
|
|
|
//===- NewGVN.cpp - Global Value Numbering Pass ---------------------------===//
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested 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-10-21 05:47: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
|
|
|
/// \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
|
2017-05-20 03:01:27 +08:00
|
|
|
/// something's value number changes. The vast majority of complexity and code
|
|
|
|
/// in this file is devoted to tracking what value numbers could change for what
|
|
|
|
/// instructions when various things happen. 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
|
|
|
|
///
|
|
|
|
/// In order to make the GVN mostly-complete, we use a technique derived from
|
|
|
|
/// "Detection of Redundant Expressions: A Complete and Polynomial-time
|
|
|
|
/// Algorithm in SSA" by R.R. Pai. The source of incompleteness in most SSA
|
|
|
|
/// based GVN algorithms is related to their inability to detect equivalence
|
|
|
|
/// between phi of ops (IE phi(a+b, c+d)) and op of phis (phi(a,c) + phi(b, d)).
|
|
|
|
/// We resolve this issue by generating the equivalent "phi of ops" form for
|
|
|
|
/// each op of phis we see, in a way that only takes polynomial time to resolve.
|
2017-01-27 05:39:49 +08:00
|
|
|
///
|
|
|
|
/// 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.
|
2017-10-21 05:47: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
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/Transforms/Scalar/NewGVN.h"
|
2017-10-21 05:47:29 +08:00
|
|
|
#include "llvm/ADT/ArrayRef.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/BitVector.h"
|
2017-10-21 05:47:29 +08:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
|
|
#include "llvm/ADT/DenseMapInfo.h"
|
|
|
|
#include "llvm/ADT/DenseSet.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/DepthFirstIterator.h"
|
2017-10-21 05:47:29 +08:00
|
|
|
#include "llvm/ADT/GraphTraits.h"
|
|
|
|
#include "llvm/ADT/Hashing.h"
|
|
|
|
#include "llvm/ADT/PointerIntPair.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/PostOrderIterator.h"
|
2017-10-21 05:47:29 +08:00
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2017-10-01 07:51:53 +08:00
|
|
|
#include "llvm/ADT/SparseBitVector.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/Statistic.h"
|
2017-10-21 05:47:29 +08:00
|
|
|
#include "llvm/ADT/iterator_range.h"
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
#include "llvm/Analysis/AliasAnalysis.h"
|
|
|
|
#include "llvm/Analysis/AssumptionCache.h"
|
|
|
|
#include "llvm/Analysis/CFGPrinter.h"
|
|
|
|
#include "llvm/Analysis/ConstantFolding.h"
|
|
|
|
#include "llvm/Analysis/GlobalsModRef.h"
|
|
|
|
#include "llvm/Analysis/InstructionSimplify.h"
|
|
|
|
#include "llvm/Analysis/MemoryBuiltins.h"
|
2017-04-14 10:53:37 +08:00
|
|
|
#include "llvm/Analysis/MemorySSA.h"
|
2017-10-21 05:47:29 +08:00
|
|
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
2018-06-05 05:23:21 +08:00
|
|
|
#include "llvm/Transforms/Utils/Local.h"
|
2017-10-21 05:47:29 +08:00
|
|
|
#include "llvm/IR/Argument.h"
|
|
|
|
#include "llvm/IR/BasicBlock.h"
|
|
|
|
#include "llvm/IR/Constant.h"
|
|
|
|
#include "llvm/IR/Constants.h"
|
|
|
|
#include "llvm/IR/Dominators.h"
|
|
|
|
#include "llvm/IR/Function.h"
|
|
|
|
#include "llvm/IR/InstrTypes.h"
|
|
|
|
#include "llvm/IR/Instruction.h"
|
|
|
|
#include "llvm/IR/Instructions.h"
|
|
|
|
#include "llvm/IR/IntrinsicInst.h"
|
|
|
|
#include "llvm/IR/Intrinsics.h"
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
|
|
|
#include "llvm/IR/Type.h"
|
|
|
|
#include "llvm/IR/Use.h"
|
|
|
|
#include "llvm/IR/User.h"
|
|
|
|
#include "llvm/IR/Value.h"
|
|
|
|
#include "llvm/Pass.h"
|
|
|
|
#include "llvm/Support/Allocator.h"
|
|
|
|
#include "llvm/Support/ArrayRecycler.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
2017-03-02 03:59:26 +08:00
|
|
|
#include "llvm/Support/DebugCounter.h"
|
2017-10-21 05:47:29 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#include "llvm/Support/PointerLikeTypeTraits.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
#include "llvm/Transforms/Scalar.h"
|
|
|
|
#include "llvm/Transforms/Scalar/GVNExpression.h"
|
2017-02-19 07:06:50 +08:00
|
|
|
#include "llvm/Transforms/Utils/PredicateInfo.h"
|
2017-04-02 21:23:44 +08:00
|
|
|
#include "llvm/Transforms/Utils/VNCoercion.h"
|
2017-10-21 05:47:29 +08:00
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <iterator>
|
|
|
|
#include <map>
|
|
|
|
#include <memory>
|
|
|
|
#include <set>
|
|
|
|
#include <string>
|
|
|
|
#include <tuple>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested 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 namespace llvm;
|
|
|
|
using namespace llvm::GVNExpression;
|
2017-04-02 21:23:44 +08:00
|
|
|
using namespace llvm::VNCoercion;
|
2017-10-21 05:47: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
|
|
|
#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-27 10:37:11 +08:00
|
|
|
STATISTIC(NumGVNDeadStores, "Number of redundant/dead stores eliminated");
|
2017-05-20 03:01:27 +08:00
|
|
|
STATISTIC(NumGVNPHIOfOpsCreated, "Number of PHI of ops created");
|
|
|
|
STATISTIC(NumGVNPHIOfOpsEliminations,
|
|
|
|
"Number of things eliminated using PHI of ops");
|
2017-03-02 03:59:26 +08:00
|
|
|
DEBUG_COUNTER(VNCounter, "newgvn-vn",
|
2017-08-11 01:48:11 +08:00
|
|
|
"Controls which instructions are value numbered");
|
2017-05-20 03:01:27 +08:00
|
|
|
DEBUG_COUNTER(PHIOfOpsCounter, "newgvn-phi",
|
2017-08-11 01:48:11 +08:00
|
|
|
"Controls which instructions we create phi of ops for");
|
2017-04-07 02:52:50 +08:00
|
|
|
// Currently store defining access refinement is too slow due to basicaa being
|
|
|
|
// egregiously slow. This flag lets us keep it working while we work on this
|
|
|
|
// issue.
|
|
|
|
static cl::opt<bool> EnableStoreRefinement("enable-store-refinement",
|
|
|
|
cl::init(false), cl::Hidden);
|
|
|
|
|
2017-08-10 22:12:57 +08:00
|
|
|
/// Currently, the generation "phi of ops" can result in correctness issues.
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
static cl::opt<bool> EnablePhiOfOps("enable-phi-of-ops", cl::init(true),
|
2017-08-10 22:12:57 +08:00
|
|
|
cl::Hidden);
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// GVN Pass
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
// Anchor methods.
|
|
|
|
namespace llvm {
|
|
|
|
namespace GVNExpression {
|
2017-10-21 05:47:29 +08:00
|
|
|
|
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;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
|
|
|
} // end namespace GVNExpression
|
|
|
|
} // end namespace llvm
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested 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-08-20 21:03:48 +08:00
|
|
|
namespace {
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-04-14 10:53:37 +08:00
|
|
|
// Tarjan's SCC finding algorithm with Nuutila's improvements
|
|
|
|
// SCCIterator is actually fairly complex for the simple thing we want.
|
|
|
|
// It also wants to hand us SCC's that are unrelated to the phi node we ask
|
|
|
|
// about, and have us process them there or risk redoing work.
|
|
|
|
// Graph traits over a filter iterator also doesn't work that well here.
|
2017-04-19 04:15:47 +08:00
|
|
|
// This SCC finder is specialized to walk use-def chains, and only follows
|
|
|
|
// instructions,
|
2017-04-14 10:53:37 +08:00
|
|
|
// not generic values (arguments, etc).
|
|
|
|
struct TarjanSCC {
|
|
|
|
TarjanSCC() : Components(1) {}
|
|
|
|
|
|
|
|
void Start(const Instruction *Start) {
|
|
|
|
if (Root.lookup(Start) == 0)
|
|
|
|
FindSCC(Start);
|
|
|
|
}
|
|
|
|
|
|
|
|
const SmallPtrSetImpl<const Value *> &getComponentFor(const Value *V) const {
|
|
|
|
unsigned ComponentID = ValueToComponent.lookup(V);
|
|
|
|
|
|
|
|
assert(ComponentID > 0 &&
|
|
|
|
"Asking for a component for a value we never processed");
|
|
|
|
return Components[ComponentID];
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
void FindSCC(const Instruction *I) {
|
|
|
|
Root[I] = ++DFSNum;
|
|
|
|
// Store the DFS Number we had before it possibly gets incremented.
|
|
|
|
unsigned int OurDFS = DFSNum;
|
|
|
|
for (auto &Op : I->operands()) {
|
|
|
|
if (auto *InstOp = dyn_cast<Instruction>(Op)) {
|
|
|
|
if (Root.lookup(Op) == 0)
|
|
|
|
FindSCC(InstOp);
|
|
|
|
if (!InComponent.count(Op))
|
|
|
|
Root[I] = std::min(Root.lookup(I), Root.lookup(Op));
|
|
|
|
}
|
|
|
|
}
|
2017-04-19 04:15:47 +08:00
|
|
|
// See if we really were the root of a component, by seeing if we still have
|
2017-05-20 03:01:27 +08:00
|
|
|
// our DFSNumber. If we do, we are the root of the component, and we have
|
|
|
|
// completed a component. If we do not, we are not the root of a component,
|
|
|
|
// and belong on the component stack.
|
2017-04-14 10:53:37 +08:00
|
|
|
if (Root.lookup(I) == OurDFS) {
|
|
|
|
unsigned ComponentID = Components.size();
|
|
|
|
Components.resize(Components.size() + 1);
|
|
|
|
auto &Component = Components.back();
|
|
|
|
Component.insert(I);
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Component root is " << *I << "\n");
|
2017-04-14 10:53:37 +08:00
|
|
|
InComponent.insert(I);
|
|
|
|
ValueToComponent[I] = ComponentID;
|
|
|
|
// Pop a component off the stack and label it.
|
|
|
|
while (!Stack.empty() && Root.lookup(Stack.back()) >= OurDFS) {
|
|
|
|
auto *Member = Stack.back();
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Component member is " << *Member << "\n");
|
2017-04-14 10:53:37 +08:00
|
|
|
Component.insert(Member);
|
|
|
|
InComponent.insert(Member);
|
|
|
|
ValueToComponent[Member] = ComponentID;
|
|
|
|
Stack.pop_back();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Part of a component, push to stack
|
|
|
|
Stack.push_back(I);
|
|
|
|
}
|
|
|
|
}
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-04-14 10:53:37 +08:00
|
|
|
unsigned int DFSNum = 1;
|
|
|
|
SmallPtrSet<const Value *, 8> InComponent;
|
|
|
|
DenseMap<const Value *, unsigned int> Root;
|
|
|
|
SmallVector<const Value *, 8> Stack;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-04-14 10:53:37 +08:00
|
|
|
// Store the components as vector of ptr sets, because we need the topo order
|
|
|
|
// of SCC's, but not individual member order
|
|
|
|
SmallVector<SmallPtrSet<const Value *, 8>, 8> Components;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-04-14 10:53:37 +08:00
|
|
|
DenseMap<const Value *, unsigned> ValueToComponent;
|
|
|
|
};
|
2017-10-21 05:47: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
|
|
|
// Congruence classes represent the set of expressions/instructions
|
|
|
|
// that are all the same *during some scope in the function*.
|
|
|
|
// That is, because of the way we perform equality propagation, and
|
|
|
|
// because of memory value numbering, it is not correct to assume
|
|
|
|
// you can willy-nilly replace any member with any other at any
|
|
|
|
// point in the function.
|
|
|
|
//
|
|
|
|
// For any Value in the Member set, it is valid to replace any dominated member
|
|
|
|
// with that Value.
|
|
|
|
//
|
2017-04-07 02:52:50 +08:00
|
|
|
// Every congruence class has a leader, and the leader is used to symbolize
|
|
|
|
// instructions in a canonical way (IE every operand of an instruction that is a
|
|
|
|
// member of the same congruence class will always be replaced with leader
|
|
|
|
// during symbolization). To simplify symbolization, we keep the leader as a
|
|
|
|
// constant if class can be proved to be a constant value. Otherwise, the
|
|
|
|
// leader is the member of the value set with the smallest DFS number. Each
|
|
|
|
// congruence class also has a defining expression, though the expression may be
|
|
|
|
// null. If it exists, it can be used for forward propagation and reassociation
|
|
|
|
// of values.
|
|
|
|
|
|
|
|
// For memory, we also track a representative MemoryAccess, and a set of memory
|
|
|
|
// members for MemoryPhis (which have no real instructions). Note that for
|
|
|
|
// memory, it seems tempting to try to split the memory members into a
|
|
|
|
// MemoryCongruenceClass or something. Unfortunately, this does not work
|
|
|
|
// easily. The value numbering of a given memory expression depends on the
|
|
|
|
// leader of the memory congruence class, and the leader of memory congruence
|
|
|
|
// class depends on the value numbering of a given memory expression. This
|
|
|
|
// leads to wasted propagation, and in some cases, missed optimization. For
|
|
|
|
// example: If we had value numbered two stores together before, but now do not,
|
|
|
|
// we move them to a new value congruence class. This in turn will move at one
|
|
|
|
// of the memorydefs to a new memory congruence class. Which in turn, affects
|
|
|
|
// the value numbering of the stores we just value numbered (because the memory
|
|
|
|
// congruence class is part of the value number). So while theoretically
|
|
|
|
// possible to split them up, it turns out to be *incredibly* complicated to get
|
|
|
|
// it to work right, because of the interdependency. While structurally
|
|
|
|
// slightly messier, it is algorithmically much simpler and faster to do what we
|
2017-04-08 02:38:09 +08:00
|
|
|
// do here, and track them both at once in the same class.
|
|
|
|
// Note: The default iterators for this class iterate over values
|
|
|
|
class CongruenceClass {
|
|
|
|
public:
|
|
|
|
using MemberType = Value;
|
|
|
|
using MemberSet = SmallPtrSet<MemberType *, 4>;
|
|
|
|
using MemoryMemberType = MemoryPhi;
|
|
|
|
using MemoryMemberSet = SmallPtrSet<const MemoryMemberType *, 2>;
|
|
|
|
|
|
|
|
explicit CongruenceClass(unsigned ID) : ID(ID) {}
|
|
|
|
CongruenceClass(unsigned ID, Value *Leader, const Expression *E)
|
|
|
|
: ID(ID), RepLeader(Leader), DefiningExpr(E) {}
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-04-08 02:38:09 +08:00
|
|
|
unsigned getID() const { return ID; }
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-04-08 02:38:09 +08:00
|
|
|
// True if this class has no members left. This is mainly used for assertion
|
|
|
|
// purposes, and for skipping empty classes.
|
|
|
|
bool isDead() const {
|
|
|
|
// If it's both dead from a value perspective, and dead from a memory
|
|
|
|
// perspective, it's really dead.
|
|
|
|
return empty() && memory_empty();
|
|
|
|
}
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-04-08 02:38:09 +08:00
|
|
|
// Leader functions
|
|
|
|
Value *getLeader() const { return RepLeader; }
|
|
|
|
void setLeader(Value *Leader) { RepLeader = Leader; }
|
|
|
|
const std::pair<Value *, unsigned int> &getNextLeader() const {
|
|
|
|
return NextLeader;
|
|
|
|
}
|
|
|
|
void resetNextLeader() { NextLeader = {nullptr, ~0}; }
|
|
|
|
void addPossibleNextLeader(std::pair<Value *, unsigned int> LeaderPair) {
|
|
|
|
if (LeaderPair.second < NextLeader.second)
|
|
|
|
NextLeader = LeaderPair;
|
|
|
|
}
|
|
|
|
|
|
|
|
Value *getStoredValue() const { return RepStoredValue; }
|
|
|
|
void setStoredValue(Value *Leader) { RepStoredValue = Leader; }
|
|
|
|
const MemoryAccess *getMemoryLeader() const { return RepMemoryAccess; }
|
|
|
|
void setMemoryLeader(const MemoryAccess *Leader) { RepMemoryAccess = Leader; }
|
|
|
|
|
|
|
|
// Forward propagation info
|
|
|
|
const Expression *getDefiningExpr() const { return DefiningExpr; }
|
|
|
|
|
|
|
|
// Value member set
|
|
|
|
bool empty() const { return Members.empty(); }
|
|
|
|
unsigned size() const { return Members.size(); }
|
|
|
|
MemberSet::const_iterator begin() const { return Members.begin(); }
|
|
|
|
MemberSet::const_iterator end() const { return Members.end(); }
|
|
|
|
void insert(MemberType *M) { Members.insert(M); }
|
|
|
|
void erase(MemberType *M) { Members.erase(M); }
|
|
|
|
void swap(MemberSet &Other) { Members.swap(Other); }
|
|
|
|
|
|
|
|
// Memory member set
|
|
|
|
bool memory_empty() const { return MemoryMembers.empty(); }
|
|
|
|
unsigned memory_size() const { return MemoryMembers.size(); }
|
|
|
|
MemoryMemberSet::const_iterator memory_begin() const {
|
|
|
|
return MemoryMembers.begin();
|
|
|
|
}
|
|
|
|
MemoryMemberSet::const_iterator memory_end() const {
|
|
|
|
return MemoryMembers.end();
|
|
|
|
}
|
|
|
|
iterator_range<MemoryMemberSet::const_iterator> memory() const {
|
|
|
|
return make_range(memory_begin(), memory_end());
|
|
|
|
}
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-04-08 02:38:09 +08:00
|
|
|
void memory_insert(const MemoryMemberType *M) { MemoryMembers.insert(M); }
|
|
|
|
void memory_erase(const MemoryMemberType *M) { MemoryMembers.erase(M); }
|
|
|
|
|
|
|
|
// Store count
|
|
|
|
unsigned getStoreCount() const { return StoreCount; }
|
|
|
|
void incStoreCount() { ++StoreCount; }
|
|
|
|
void decStoreCount() {
|
|
|
|
assert(StoreCount != 0 && "Store count went negative");
|
|
|
|
--StoreCount;
|
|
|
|
}
|
|
|
|
|
2017-05-11 03:57:43 +08:00
|
|
|
// True if this class has no memory members.
|
|
|
|
bool definesNoMemory() const { return StoreCount == 0 && memory_empty(); }
|
|
|
|
|
2018-05-31 06:24:08 +08:00
|
|
|
// Return true if two congruence classes are equivalent to each other. This
|
|
|
|
// means that every field but the ID number and the dead field are equivalent.
|
2017-04-08 02:38:09 +08:00
|
|
|
bool isEquivalentTo(const CongruenceClass *Other) const {
|
|
|
|
if (!Other)
|
|
|
|
return false;
|
|
|
|
if (this == Other)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (std::tie(StoreCount, RepLeader, RepStoredValue, RepMemoryAccess) !=
|
|
|
|
std::tie(Other->StoreCount, Other->RepLeader, Other->RepStoredValue,
|
|
|
|
Other->RepMemoryAccess))
|
|
|
|
return false;
|
|
|
|
if (DefiningExpr != Other->DefiningExpr)
|
|
|
|
if (!DefiningExpr || !Other->DefiningExpr ||
|
|
|
|
*DefiningExpr != *Other->DefiningExpr)
|
|
|
|
return false;
|
2018-05-31 06:24:08 +08:00
|
|
|
|
|
|
|
if (Members.size() != Other->Members.size())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return all_of(Members,
|
|
|
|
[&](const Value *V) { return Other->Members.count(V); });
|
2017-04-08 02:38:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
unsigned ID;
|
2017-10-21 05:47: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
|
|
|
// Representative leader.
|
2016-12-29 03:17:17 +08:00
|
|
|
Value *RepLeader = nullptr;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-04-08 02:38:09 +08:00
|
|
|
// The most dominating leader after our current leader, because the member set
|
|
|
|
// is not sorted and is expensive to keep sorted all the time.
|
|
|
|
std::pair<Value *, unsigned int> NextLeader = {nullptr, ~0U};
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
// If this is represented by a store, the value of the store.
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
Value *RepStoredValue = nullptr;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
// If this class contains MemoryDefs or MemoryPhis, this is the leading memory
|
|
|
|
// access.
|
|
|
|
const MemoryAccess *RepMemoryAccess = nullptr;
|
2017-10-21 05:47: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
|
|
|
// Defining Expression.
|
2016-12-29 03:17:17 +08:00
|
|
|
const Expression *DefiningExpr = nullptr;
|
2017-10-21 05:47: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
|
|
|
// Actual members of this class.
|
|
|
|
MemberSet Members;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
// This is the set of MemoryPhis that exist in the class. MemoryDefs and
|
|
|
|
// MemoryUses have real instructions representing them, so we only need to
|
|
|
|
// track MemoryPhis here.
|
|
|
|
MemoryMemberSet MemoryMembers;
|
2017-10-21 05:47:29 +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;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested 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-10-21 05:47:29 +08:00
|
|
|
|
|
|
|
} // end anonymous namespace
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
namespace llvm {
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-06-07 01:15:28 +08:00
|
|
|
struct ExactEqualsExpression {
|
|
|
|
const Expression &E;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-06-07 01:15:28 +08:00
|
|
|
explicit ExactEqualsExpression(const Expression &E) : E(E) {}
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-06-07 01:15:28 +08:00
|
|
|
hash_code getComputedHash() const { return E.getComputedHash(); }
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-06-07 01:15:28 +08:00
|
|
|
bool operator==(const Expression &Other) const {
|
|
|
|
return E.exactlyEquals(Other);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
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);
|
|
|
|
}
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2016-12-27 04:06:58 +08:00
|
|
|
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);
|
|
|
|
}
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
static unsigned getHashValue(const Expression *E) {
|
2017-06-07 01:15:28 +08:00
|
|
|
return E->getComputedHash();
|
|
|
|
}
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-06-07 01:15:28 +08:00
|
|
|
static unsigned getHashValue(const ExactEqualsExpression &E) {
|
|
|
|
return E.getComputedHash();
|
|
|
|
}
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-06-07 01:15:28 +08:00
|
|
|
static bool isEqual(const ExactEqualsExpression &LHS, const Expression *RHS) {
|
|
|
|
if (RHS == getTombstoneKey() || RHS == getEmptyKey())
|
|
|
|
return false;
|
|
|
|
return LHS == *RHS;
|
2016-12-27 04:06:58 +08:00
|
|
|
}
|
2017-06-07 01:15:28 +08:00
|
|
|
|
2016-12-27 04:06:58 +08:00
|
|
|
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;
|
2017-05-30 14:58:18 +08:00
|
|
|
// Compare hashes before equality. This is *not* what the hashtable does,
|
|
|
|
// since it is computing it modulo the number of buckets, whereas we are
|
|
|
|
// using the full hash keyspace. Since the hashes are precomputed, this
|
|
|
|
// check is *much* faster than equality.
|
|
|
|
if (LHS->getComputedHash() != RHS->getComputedHash())
|
|
|
|
return false;
|
2016-12-27 04:06:58 +08:00
|
|
|
return *LHS == *RHS;
|
|
|
|
}
|
|
|
|
};
|
2017-10-21 05:47: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
|
|
|
} // end namespace llvm
|
|
|
|
|
2017-02-11 19:06:55 +08:00
|
|
|
namespace {
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-03-12 12:46:45 +08:00
|
|
|
class NewGVN {
|
|
|
|
Function &F;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
DominatorTree *DT;
|
2017-03-12 12:46:45 +08:00
|
|
|
const TargetLibraryInfo *TLI;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
AliasAnalysis *AA;
|
|
|
|
MemorySSA *MSSA;
|
|
|
|
MemorySSAWalker *MSSAWalker;
|
2017-03-12 12:46:45 +08:00
|
|
|
const DataLayout &DL;
|
2017-02-19 07:06:50 +08:00
|
|
|
std::unique_ptr<PredicateInfo> PredInfo;
|
2017-05-10 00:40:04 +08:00
|
|
|
|
|
|
|
// These are the only two things the create* functions should have
|
|
|
|
// side-effects on due to allocating memory.
|
|
|
|
mutable BumpPtrAllocator ExpressionAllocator;
|
|
|
|
mutable ArrayRecycler<Value *> ArgRecycler;
|
|
|
|
mutable TarjanSCC SCCFinder;
|
2017-04-27 04:56:14 +08:00
|
|
|
const SimplifyQuery SQ;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2017-02-11 23:07:01 +08:00
|
|
|
// Number of function arguments, used by ranking
|
|
|
|
unsigned int NumFuncArgs;
|
|
|
|
|
2017-04-14 10:53:37 +08:00
|
|
|
// RPOOrdering of basic blocks
|
|
|
|
DenseMap<const DomTreeNode *, unsigned> RPOOrdering;
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Congruence class info.
|
2017-02-11 20:48:50 +08:00
|
|
|
|
|
|
|
// This class is called INITIAL in the paper. It is the class everything
|
|
|
|
// startsout in, and represents any value. Being an optimistic analysis,
|
2017-03-11 03:05:04 +08:00
|
|
|
// anything in the TOP class has the value TOP, which is indeterminate and
|
2017-02-11 20:48:50 +08:00
|
|
|
// equivalent to everything.
|
2017-03-11 03:05:04 +08:00
|
|
|
CongruenceClass *TOPClass;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
std::vector<CongruenceClass *> CongruenceClasses;
|
|
|
|
unsigned NextCongruenceNum;
|
|
|
|
|
|
|
|
// Value Mappings.
|
|
|
|
DenseMap<Value *, CongruenceClass *> ValueToClass;
|
|
|
|
DenseMap<Value *, const Expression *> ValueToExpression;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
// Value PHI handling, used to make equivalence between phi(op, op) and
|
|
|
|
// op(phi, phi).
|
|
|
|
// These mappings just store various data that would normally be part of the
|
|
|
|
// IR.
|
2017-10-01 07:51:53 +08:00
|
|
|
SmallPtrSet<const Instruction *, 8> PHINodeUses;
|
|
|
|
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
DenseMap<const Value *, bool> OpSafeForPHIOfOps;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
// Map a temporary instruction we created to a parent block.
|
|
|
|
DenseMap<const Value *, BasicBlock *> TempToBlock;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-08-04 05:17:49 +08:00
|
|
|
// Map between the already in-program instructions and the temporary phis we
|
|
|
|
// created that they are known equivalent to.
|
2017-05-20 03:01:27 +08:00
|
|
|
DenseMap<const Value *, PHINode *> RealToTemp;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
// In order to know when we should re-process instructions that have
|
|
|
|
// phi-of-ops, we track the set of expressions that they needed as
|
|
|
|
// leaders. When we discover new leaders for those expressions, we process the
|
|
|
|
// associated phi-of-op instructions again in case they have changed. The
|
|
|
|
// other way they may change is if they had leaders, and those leaders
|
|
|
|
// disappear. However, at the point they have leaders, there are uses of the
|
|
|
|
// relevant operands in the created phi node, and so they will get reprocessed
|
|
|
|
// through the normal user marking we perform.
|
|
|
|
mutable DenseMap<const Value *, SmallPtrSet<Value *, 2>> AdditionalUsers;
|
|
|
|
DenseMap<const Expression *, SmallPtrSet<Instruction *, 2>>
|
|
|
|
ExpressionToPhiOfOps;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
// Map from temporary operation to MemoryAccess.
|
|
|
|
DenseMap<const Instruction *, MemoryUseOrDef *> TempToMemory;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
// Set of all temporary instructions we created.
|
2017-08-04 05:17:49 +08:00
|
|
|
// Note: This will include instructions that were just created during value
|
|
|
|
// numbering. The way to test if something is using them is to check
|
|
|
|
// RealToTemp.
|
2017-05-20 03:01:27 +08:00
|
|
|
DenseSet<Instruction *> AllTempInstructions;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested 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-10-01 07:51:53 +08:00
|
|
|
// This is the set of instructions to revisit on a reachability change. At
|
|
|
|
// the end of the main iteration loop it will contain at least all the phi of
|
|
|
|
// ops instructions that will be changed to phis, as well as regular phis.
|
|
|
|
// During the iteration loop, it may contain other things, such as phi of ops
|
|
|
|
// instructions that used edge reachability to reach a result, and so need to
|
|
|
|
// be revisited when the edge changes, independent of whether the phi they
|
|
|
|
// depended on changes.
|
|
|
|
DenseMap<BasicBlock *, SparseBitVector<>> RevisitOnReachabilityChange;
|
|
|
|
|
2017-02-19 07:06:50 +08:00
|
|
|
// Mapping from predicate info we used to the instructions we used it with.
|
|
|
|
// In order to correctly ensure propagation, we must keep track of what
|
|
|
|
// comparisons we used, so that when the values of the comparisons change, we
|
|
|
|
// propagate the information to the places we used the comparison.
|
2017-05-10 00:40:04 +08:00
|
|
|
mutable DenseMap<const Value *, SmallPtrSet<Instruction *, 2>>
|
|
|
|
PredicateToUsers;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
// the same reasoning as PredicateToUsers. When we skip MemoryAccesses for
|
|
|
|
// stores, we no longer can rely solely on the def-use chains of MemorySSA.
|
2017-05-10 00:40:04 +08:00
|
|
|
mutable DenseMap<const MemoryAccess *, SmallPtrSet<MemoryAccess *, 2>>
|
|
|
|
MemoryToUsers;
|
2017-02-19 07:06:50 +08:00
|
|
|
|
2016-12-26 06:23:49 +08:00
|
|
|
// A table storing which memorydefs/phis represent a memory state provably
|
|
|
|
// equivalent to another memory state.
|
|
|
|
// We could use the congruence class machinery, but the MemoryAccess's are
|
|
|
|
// abstract memory states, so they can only ever be equivalent to each other,
|
|
|
|
// and not to constants, etc.
|
2017-01-27 06:21:48 +08:00
|
|
|
DenseMap<const MemoryAccess *, CongruenceClass *> MemoryAccessToClass;
|
2016-12-26 06:23:49 +08:00
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
// We could, if we wanted, build MemoryPhiExpressions and
|
|
|
|
// MemoryVariableExpressions, etc, and value number them the same way we value
|
|
|
|
// number phi expressions. For the moment, this seems like overkill. They
|
|
|
|
// can only exist in one of three states: they can be TOP (equal to
|
|
|
|
// everything), Equivalent to something else, or unique. Because we do not
|
|
|
|
// create expressions for them, we need to simulate leader change not just
|
|
|
|
// when they change class, but when they change state. Note: We can do the
|
|
|
|
// same thing for phis, and avoid having phi expressions if we wanted, We
|
|
|
|
// should eventually unify in one direction or the other, so this is a little
|
|
|
|
// bit of an experiment in which turns out easier to maintain.
|
|
|
|
enum MemoryPhiState { MPS_Invalid, MPS_TOP, MPS_Equivalent, MPS_Unique };
|
|
|
|
DenseMap<const MemoryPhi *, MemoryPhiState> MemoryPhiState;
|
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
enum InstCycleState { ICS_Unknown, ICS_CycleFree, ICS_Cycle };
|
|
|
|
mutable DenseMap<const Instruction *, InstCycleState> InstCycleState;
|
2017-10-21 05:47: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
|
|
|
// 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;
|
|
|
|
|
2017-05-20 04:22:20 +08:00
|
|
|
// We have a single expression that represents currently DeadExpressions.
|
|
|
|
// For dead expressions we can prove will stay dead, we mark them with
|
|
|
|
// DFS number zero. However, it's possible in the case of phi nodes
|
|
|
|
// for us to assume/prove all arguments are dead during fixpointing.
|
|
|
|
// We use DeadExpression for that case.
|
|
|
|
DeadExpression *SingletonDeadExpression = 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
|
|
|
// Which values have changed as a result of leader changes.
|
2017-01-12 04:22:05 +08:00
|
|
|
SmallPtrSet<Value *, 8> LeaderChanges;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Reachability info.
|
2016-12-29 03:17:17 +08:00
|
|
|
using BlockEdge = BasicBlockEdge;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
DenseSet<BlockEdge> ReachableEdges;
|
|
|
|
SmallPtrSet<const BasicBlock *, 8> ReachableBlocks;
|
|
|
|
|
|
|
|
// This is a bitvector because, on larger functions, we may have
|
|
|
|
// thousands of touched instructions at once (entire blocks,
|
|
|
|
// instructions with hundreds of uses, etc). Even with optimization
|
|
|
|
// for when we mark whole blocks as touched, when this was a
|
|
|
|
// SmallPtrSet or DenseSet, for some functions, we spent >20% of all
|
|
|
|
// the time in GVN just managing this list. The bitvector, on the
|
|
|
|
// other hand, efficiently supports test/set/clear of both
|
|
|
|
// individual and ranges, as well as "find next element" This
|
|
|
|
// enables us to use it as a worklist with essentially 0 cost.
|
|
|
|
BitVector TouchedInstructions;
|
|
|
|
|
|
|
|
DenseMap<const BasicBlock *, std::pair<unsigned, unsigned>> BlockInstRange;
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
// Debugging for how many times each block and instruction got processed.
|
|
|
|
DenseMap<const Value *, unsigned> ProcessedCount;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// DFS info.
|
2017-01-21 07:29:28 +08:00
|
|
|
// This contains a mapping from Instructions to DFS numbers.
|
|
|
|
// The numbering starts at 1. An instruction with DFS number zero
|
|
|
|
// means that the instruction is dead.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
DenseMap<const Value *, unsigned> InstrDFS;
|
2017-01-21 07:29:28 +08:00
|
|
|
|
|
|
|
// This contains the mapping DFS numbers to instructions.
|
2016-12-27 17:20:36 +08:00
|
|
|
SmallVector<Value *, 32> DFSToInstr;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Deletion info.
|
|
|
|
SmallPtrSet<Instruction *, 8> InstructionsToErase;
|
|
|
|
|
|
|
|
public:
|
2017-03-12 12:46:45 +08:00
|
|
|
NewGVN(Function &F, DominatorTree *DT, AssumptionCache *AC,
|
|
|
|
TargetLibraryInfo *TLI, AliasAnalysis *AA, MemorySSA *MSSA,
|
|
|
|
const DataLayout &DL)
|
2017-04-29 03:55:38 +08:00
|
|
|
: F(F), DT(DT), TLI(TLI), AA(AA), MSSA(MSSA), DL(DL),
|
[InstrSimplify,NewGVN] Add option to ignore additional instr info when simplifying.
NewGVN uses InstructionSimplify for simplifications of leaders of
congruence classes. It is not guaranteed that the metadata or other
flags/keywords (like nsw or exact) of the leader is available for all members
in a congruence class, so we cannot use it for simplification.
This patch adds a InstrInfoQuery struct with a boolean field
UseInstrInfo (which defaults to true to keep the current behavior as
default) and a set of helper methods to get metadata/keywords for a
given instruction, if UseInstrInfo is true. The whole thing might need a
better name, to avoid confusion with TargetInstrInfo but I am not sure
what a better name would be.
The current patch threads through InstrInfoQuery to the required
places, which is messier then it would need to be, if
InstructionSimplify and ValueTracking would share the same Query struct.
The reason I added it as a separate struct is that it can be shared
between InstructionSimplify and ValueTracking's query objects. Also,
some places do not need a full query object, just the InstrInfoQuery.
It also updates some interfaces that do not take a Query object, but a
set of optional parameters to take an additional boolean UseInstrInfo.
See https://bugs.llvm.org/show_bug.cgi?id=37540.
Reviewers: dberlin, davide, efriedma, sebpop, hiraditya
Reviewed By: hiraditya
Differential Revision: https://reviews.llvm.org/D47143
llvm-svn: 340031
2018-08-17 22:39:04 +08:00
|
|
|
PredInfo(make_unique<PredicateInfo>(F, *DT, *AC)),
|
|
|
|
SQ(DL, TLI, DT, AC, /*CtxI=*/nullptr, /*UseInstrInfo=*/false) {}
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-03-12 12:46:45 +08:00
|
|
|
bool runGVN();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
// Expression handling.
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *createExpression(Instruction *) const;
|
2017-09-05 10:17:42 +08:00
|
|
|
const Expression *createBinaryExpression(unsigned, Type *, Value *, Value *,
|
|
|
|
Instruction *) const;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-10-01 07:51:54 +08:00
|
|
|
// Our canonical form for phi arguments is a pair of incoming value, incoming
|
|
|
|
// basic block.
|
2017-10-21 05:47:29 +08:00
|
|
|
using ValPair = std::pair<Value *, BasicBlock *>;
|
|
|
|
|
2017-10-01 07:51:54 +08:00
|
|
|
PHIExpression *createPHIExpression(ArrayRef<ValPair>, const Instruction *,
|
|
|
|
BasicBlock *, bool &HasBackEdge,
|
2017-05-20 03:01:27 +08:00
|
|
|
bool &OriginalOpsConstant) const;
|
2017-05-20 04:22:20 +08:00
|
|
|
const DeadExpression *createDeadExpression() const;
|
2017-05-10 00:40:04 +08:00
|
|
|
const VariableExpression *createVariableExpression(Value *) const;
|
|
|
|
const ConstantExpression *createConstantExpression(Constant *) const;
|
|
|
|
const Expression *createVariableOrConstant(Value *V) const;
|
|
|
|
const UnknownExpression *createUnknownExpression(Instruction *) const;
|
2017-04-07 02:52:50 +08:00
|
|
|
const StoreExpression *createStoreExpression(StoreInst *,
|
2017-05-10 00:40:04 +08:00
|
|
|
const MemoryAccess *) const;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
LoadExpression *createLoadExpression(Type *, Value *, LoadInst *,
|
2017-05-10 00:40:04 +08:00
|
|
|
const MemoryAccess *) const;
|
|
|
|
const CallExpression *createCallExpression(CallInst *,
|
|
|
|
const MemoryAccess *) const;
|
|
|
|
const AggregateValueExpression *
|
|
|
|
createAggregateValueExpression(Instruction *) const;
|
|
|
|
bool setBasicExpressionInfo(Instruction *, BasicExpression *) const;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Congruence class handling.
|
|
|
|
CongruenceClass *createCongruenceClass(Value *Leader, const Expression *E) {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *result = new CongruenceClass(NextCongruenceNum++, Leader, E);
|
2016-12-29 07:24:02 +08:00
|
|
|
CongruenceClasses.emplace_back(result);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
CongruenceClass *createMemoryClass(MemoryAccess *MA) {
|
|
|
|
auto *CC = createCongruenceClass(nullptr, nullptr);
|
2017-04-08 02:38:09 +08:00
|
|
|
CC->setMemoryLeader(MA);
|
2017-04-07 02:52:50 +08:00
|
|
|
return CC;
|
|
|
|
}
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
CongruenceClass *ensureLeaderOfMemoryClass(MemoryAccess *MA) {
|
|
|
|
auto *CC = getMemoryClass(MA);
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC->getMemoryLeader() != MA)
|
2017-04-07 02:52:50 +08:00
|
|
|
CC = createMemoryClass(MA);
|
|
|
|
return CC;
|
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
CongruenceClass *createSingletonCongruenceClass(Value *Member) {
|
2016-12-28 22:00:11 +08:00
|
|
|
CongruenceClass *CClass = createCongruenceClass(Member, nullptr);
|
2017-04-08 02:38:09 +08:00
|
|
|
CClass->insert(Member);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
ValueToClass[Member] = CClass;
|
|
|
|
return CClass;
|
|
|
|
}
|
2017-10-21 05:47: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
|
|
|
void initializeCongruenceClasses(Function &F);
|
2017-10-01 07:51:53 +08:00
|
|
|
const Expression *makePossiblePHIOfOps(Instruction *,
|
2017-05-20 03:01:27 +08:00
|
|
|
SmallPtrSetImpl<Value *> &);
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
Value *findLeaderForInst(Instruction *ValueOp,
|
|
|
|
SmallPtrSetImpl<Value *> &Visited,
|
|
|
|
MemoryAccess *MemAccess, Instruction *OrigInst,
|
|
|
|
BasicBlock *PredBB);
|
2017-10-06 09:33:06 +08:00
|
|
|
bool OpIsSafeForPHIOfOpsHelper(Value *V, const BasicBlock *PHIBlock,
|
|
|
|
SmallPtrSetImpl<const Value *> &Visited,
|
|
|
|
SmallVectorImpl<Instruction *> &Worklist);
|
|
|
|
bool OpIsSafeForPHIOfOps(Value *Op, const BasicBlock *PHIBlock,
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
SmallPtrSetImpl<const Value *> &);
|
2017-05-20 03:01:27 +08:00
|
|
|
void addPhiOfOps(PHINode *Op, BasicBlock *BB, Instruction *ExistingValue);
|
2017-08-04 05:17:49 +08:00
|
|
|
void removePhiOfOps(Instruction *I, PHINode *PHITemp);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested 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
|
|
|
// Value number an Instruction or MemoryPhi.
|
|
|
|
void valueNumberMemoryPhi(MemoryPhi *);
|
|
|
|
void valueNumberInstruction(Instruction *);
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Symbolic evaluation.
|
|
|
|
const Expression *checkSimplificationResults(Expression *, Instruction *,
|
2017-05-10 00:40:04 +08:00
|
|
|
Value *) const;
|
2017-05-20 03:01:27 +08:00
|
|
|
const Expression *performSymbolicEvaluation(Value *,
|
|
|
|
SmallPtrSetImpl<Value *> &) const;
|
2017-04-02 21:23:44 +08:00
|
|
|
const Expression *performSymbolicLoadCoercion(Type *, Value *, LoadInst *,
|
2017-05-10 00:40:04 +08:00
|
|
|
Instruction *,
|
|
|
|
MemoryAccess *) const;
|
|
|
|
const Expression *performSymbolicLoadEvaluation(Instruction *) const;
|
|
|
|
const Expression *performSymbolicStoreEvaluation(Instruction *) const;
|
|
|
|
const Expression *performSymbolicCallEvaluation(Instruction *) const;
|
2017-10-01 07:51:54 +08:00
|
|
|
void sortPHIOps(MutableArrayRef<ValPair> Ops) const;
|
|
|
|
const Expression *performSymbolicPHIEvaluation(ArrayRef<ValPair>,
|
|
|
|
Instruction *I,
|
|
|
|
BasicBlock *PHIBlock) const;
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *performSymbolicAggrValueEvaluation(Instruction *) const;
|
|
|
|
const Expression *performSymbolicCmpEvaluation(Instruction *) const;
|
|
|
|
const Expression *performSymbolicPredicateInfoEvaluation(Instruction *) const;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Congruence finding.
|
2017-03-24 13:30:34 +08:00
|
|
|
bool someEquivalentDominates(const Instruction *, const Instruction *) const;
|
2017-02-01 06:31:53 +08:00
|
|
|
Value *lookupOperandLeader(Value *) const;
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
CongruenceClass *getClassForExpression(const Expression *E) const;
|
2017-01-14 06:40:01 +08:00
|
|
|
void performCongruenceFinding(Instruction *, const Expression *);
|
2017-04-07 02:52:50 +08:00
|
|
|
void moveValueToNewCongruenceClass(Instruction *, const Expression *,
|
|
|
|
CongruenceClass *, CongruenceClass *);
|
|
|
|
void moveMemoryToNewCongruenceClass(Instruction *, MemoryAccess *,
|
|
|
|
CongruenceClass *, CongruenceClass *);
|
|
|
|
Value *getNextValueLeader(CongruenceClass *) const;
|
|
|
|
const MemoryAccess *getNextMemoryLeader(CongruenceClass *) const;
|
|
|
|
bool setMemoryClass(const MemoryAccess *From, CongruenceClass *To);
|
|
|
|
CongruenceClass *getMemoryClass(const MemoryAccess *MA) const;
|
|
|
|
const MemoryAccess *lookupMemoryLeader(const MemoryAccess *) const;
|
2017-05-20 03:01:27 +08:00
|
|
|
bool isMemoryAccessTOP(const MemoryAccess *) const;
|
2017-04-07 02:52:50 +08:00
|
|
|
|
2017-02-11 23:07:01 +08:00
|
|
|
// Ranking
|
|
|
|
unsigned int getRank(const Value *) const;
|
|
|
|
bool shouldSwapOperands(const Value *, const Value *) const;
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Reachability handling.
|
|
|
|
void updateReachableEdge(BasicBlock *, BasicBlock *);
|
2018-10-18 08:39:46 +08:00
|
|
|
void processOutgoingEdges(Instruction *, BasicBlock *);
|
2017-02-01 06:32:03 +08:00
|
|
|
Value *findConditionEquivalence(Value *) const;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Elimination.
|
|
|
|
struct ValueDFS;
|
2017-04-08 02:38:09 +08:00
|
|
|
void convertClassToDFSOrdered(const CongruenceClass &,
|
2017-03-10 08:32:33 +08:00
|
|
|
SmallVectorImpl<ValueDFS> &,
|
|
|
|
DenseMap<const Value *, unsigned int> &,
|
2017-04-08 02:38:09 +08:00
|
|
|
SmallPtrSetImpl<Instruction *> &) const;
|
|
|
|
void convertClassToLoadsAndStores(const CongruenceClass &,
|
|
|
|
SmallVectorImpl<ValueDFS> &) const;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
bool eliminateInstructions(Function &);
|
|
|
|
void replaceInstruction(Instruction *, Value *);
|
|
|
|
void markInstructionForDeletion(Instruction *);
|
|
|
|
void deleteInstructionsInBlock(BasicBlock *);
|
2017-09-05 10:17:40 +08:00
|
|
|
Value *findPHIOfOpsLeader(const Expression *, const Instruction *,
|
|
|
|
const BasicBlock *) 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
|
|
|
// New instruction creation.
|
2017-10-21 05:47:29 +08:00
|
|
|
void handleNewInstruction(Instruction *) {}
|
2017-01-08 00:55:14 +08:00
|
|
|
|
|
|
|
// Various instruction touch utilities
|
2017-05-22 07:41:56 +08:00
|
|
|
template <typename Map, typename KeyType, typename Func>
|
|
|
|
void for_each_found(Map &, const KeyType &, Func);
|
|
|
|
template <typename Map, typename KeyType>
|
|
|
|
void touchAndErase(Map &, const KeyType &);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
void markUsersTouched(Value *);
|
2017-04-07 02:52:50 +08:00
|
|
|
void markMemoryUsersTouched(const MemoryAccess *);
|
|
|
|
void markMemoryDefTouched(const MemoryAccess *);
|
2017-02-19 07:06:50 +08:00
|
|
|
void markPredicateUsersTouched(Instruction *);
|
2017-04-07 02:52:50 +08:00
|
|
|
void markValueLeaderChangeTouched(CongruenceClass *CC);
|
|
|
|
void markMemoryLeaderChangeTouched(CongruenceClass *CC);
|
2017-05-30 14:58:18 +08:00
|
|
|
void markPhiOfOpsChanged(const Expression *E);
|
2017-05-10 00:40:04 +08:00
|
|
|
void addPredicateUsers(const PredicateBase *, Instruction *) const;
|
|
|
|
void addMemoryUsers(const MemoryAccess *To, MemoryAccess *U) const;
|
2017-05-20 03:01:27 +08:00
|
|
|
void addAdditionalUsers(Value *To, Value *User) const;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2017-03-18 23:41:40 +08:00
|
|
|
// Main loop of value numbering
|
|
|
|
void iterateTouchedInstructions();
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Utilities.
|
|
|
|
void cleanupTables();
|
|
|
|
std::pair<unsigned, unsigned> assignDFSNumbers(BasicBlock *, unsigned);
|
2017-05-20 03:01:27 +08:00
|
|
|
void updateProcessedCount(const Value *V);
|
2017-01-12 04:22:36 +08:00
|
|
|
void verifyMemoryCongruency() const;
|
2017-03-18 23:41:40 +08:00
|
|
|
void verifyIterationSettled(Function &F);
|
2017-05-17 03:58:47 +08:00
|
|
|
void verifyStoreExpressions() const;
|
2017-05-19 07:22:44 +08:00
|
|
|
bool singleReachablePHIPath(SmallPtrSet<const MemoryAccess *, 8> &,
|
|
|
|
const MemoryAccess *, const MemoryAccess *) const;
|
2017-03-18 23:41:40 +08:00
|
|
|
BasicBlock *getBlockForValue(Value *V) const;
|
2017-05-10 00:40:04 +08:00
|
|
|
void deleteExpression(const Expression *E) const;
|
2017-05-20 03:01:27 +08:00
|
|
|
MemoryUseOrDef *getMemoryAccess(const Instruction *) const;
|
|
|
|
MemoryAccess *getDefiningAccess(const MemoryAccess *) const;
|
|
|
|
MemoryPhi *getMemoryAccess(const BasicBlock *) const;
|
|
|
|
template <class T, class Range> T *getMinDFSOfRange(const Range &) const;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-04-07 02:52:58 +08:00
|
|
|
unsigned InstrToDFSNum(const Value *V) const {
|
2017-04-07 02:52:50 +08:00
|
|
|
assert(isa<Instruction>(V) && "This should not be used for MemoryAccesses");
|
|
|
|
return InstrDFS.lookup(V);
|
|
|
|
}
|
|
|
|
|
2017-04-07 02:52:58 +08:00
|
|
|
unsigned InstrToDFSNum(const MemoryAccess *MA) const {
|
|
|
|
return MemoryToDFSNum(MA);
|
|
|
|
}
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-04-07 02:52:58 +08:00
|
|
|
Value *InstrFromDFSNum(unsigned DFSNum) { return DFSToInstr[DFSNum]; }
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-04-07 02:52:58 +08:00
|
|
|
// Given a MemoryAccess, return the relevant instruction DFS number. Note:
|
|
|
|
// This deliberately takes a value so it can be used with Use's, which will
|
|
|
|
// auto-convert to Value's but not to MemoryAccess's.
|
|
|
|
unsigned MemoryToDFSNum(const Value *MA) const {
|
|
|
|
assert(isa<MemoryAccess>(MA) &&
|
|
|
|
"This should not be used with instructions");
|
|
|
|
return isa<MemoryUseOrDef>(MA)
|
|
|
|
? InstrToDFSNum(cast<MemoryUseOrDef>(MA)->getMemoryInst())
|
|
|
|
: InstrDFS.lookup(MA);
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
bool isCycleFree(const Instruction *) const;
|
|
|
|
bool isBackedge(BasicBlock *From, BasicBlock *To) const;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-03-18 23:41:40 +08:00
|
|
|
// Debug counter info. When verifying, we have to reset the value numbering
|
|
|
|
// debug counter to the same state it started in to get the same results.
|
2018-07-24 05:49:36 +08:00
|
|
|
int64_t StartingVNCounter;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
};
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-02-11 19:06:55 +08:00
|
|
|
} // end anonymous namespace
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2016-12-28 21:37:17 +08:00
|
|
|
template <typename T>
|
|
|
|
static bool equalsLoadStoreHelper(const T &LHS, const Expression &RHS) {
|
2017-04-01 17:44:29 +08:00
|
|
|
if (!isa<LoadExpression>(RHS) && !isa<StoreExpression>(RHS))
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return false;
|
2017-04-01 17:44:29 +08:00
|
|
|
return LHS.MemoryExpression::equals(RHS);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
2016-12-28 21:37:17 +08:00
|
|
|
bool LoadExpression::equals(const Expression &Other) const {
|
|
|
|
return equalsLoadStoreHelper(*this, Other);
|
|
|
|
}
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2016-12-28 21:37:17 +08:00
|
|
|
bool StoreExpression::equals(const Expression &Other) const {
|
2017-04-01 17:44:29 +08:00
|
|
|
if (!equalsLoadStoreHelper(*this, Other))
|
|
|
|
return false;
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
// Make sure that store vs store includes the value operand.
|
2017-04-01 17:44:29 +08:00
|
|
|
if (const auto *S = dyn_cast<StoreExpression>(&Other))
|
|
|
|
if (getStoredValue() != S->getStoredValue())
|
|
|
|
return false;
|
|
|
|
return true;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
// Determine if the edge From->To is a backedge
|
|
|
|
bool NewGVN::isBackedge(BasicBlock *From, BasicBlock *To) const {
|
2017-08-02 12:05:49 +08:00
|
|
|
return From == To ||
|
|
|
|
RPOOrdering.lookup(DT->getNode(From)) >=
|
|
|
|
RPOOrdering.lookup(DT->getNode(To));
|
2017-05-20 03:01:27 +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
|
|
|
#ifndef NDEBUG
|
|
|
|
static std::string getBlockName(const BasicBlock *B) {
|
2018-06-30 01:48:58 +08:00
|
|
|
return DOTGraphTraits<const Function *>::getSimpleNodeLabel(B, nullptr);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
// Get a MemoryAccess for an instruction, fake or real.
|
|
|
|
MemoryUseOrDef *NewGVN::getMemoryAccess(const Instruction *I) const {
|
|
|
|
auto *Result = MSSA->getMemoryAccess(I);
|
|
|
|
return Result ? Result : TempToMemory.lookup(I);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get a MemoryPhi for a basic block. These are all real.
|
|
|
|
MemoryPhi *NewGVN::getMemoryAccess(const BasicBlock *BB) const {
|
|
|
|
return MSSA->getMemoryAccess(BB);
|
|
|
|
}
|
|
|
|
|
2017-03-18 23:41:40 +08:00
|
|
|
// Get the basic block from an instruction/memory value.
|
|
|
|
BasicBlock *NewGVN::getBlockForValue(Value *V) const {
|
2017-05-20 03:01:27 +08:00
|
|
|
if (auto *I = dyn_cast<Instruction>(V)) {
|
|
|
|
auto *Parent = I->getParent();
|
|
|
|
if (Parent)
|
|
|
|
return Parent;
|
|
|
|
Parent = TempToBlock.lookup(V);
|
|
|
|
assert(Parent && "Every fake instruction should have a block");
|
|
|
|
return Parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto *MP = dyn_cast<MemoryPhi>(V);
|
|
|
|
assert(MP && "Should have been an instruction or a MemoryPhi");
|
|
|
|
return MP->getBlock();
|
2017-03-18 23:41:40 +08:00
|
|
|
}
|
|
|
|
|
2017-03-24 14:33:48 +08:00
|
|
|
// Delete a definitely dead expression, so it can be reused by the expression
|
|
|
|
// allocator. Some of these are not in creation functions, so we have to accept
|
|
|
|
// const versions.
|
2017-05-10 00:40:04 +08:00
|
|
|
void NewGVN::deleteExpression(const Expression *E) const {
|
2017-03-24 14:33:48 +08:00
|
|
|
assert(isa<BasicExpression>(E));
|
|
|
|
auto *BE = cast<BasicExpression>(E);
|
|
|
|
const_cast<BasicExpression *>(BE)->deallocateOperands(ArgRecycler);
|
|
|
|
ExpressionAllocator.Deallocate(E);
|
|
|
|
}
|
2017-09-05 10:17:41 +08:00
|
|
|
|
2017-09-05 10:17:43 +08:00
|
|
|
// If V is a predicateinfo copy, get the thing it is a copy of.
|
|
|
|
static Value *getCopyOf(const Value *V) {
|
2017-09-05 10:17:41 +08:00
|
|
|
if (auto *II = dyn_cast<IntrinsicInst>(V))
|
2017-09-05 10:17:43 +08:00
|
|
|
if (II->getIntrinsicID() == Intrinsic::ssa_copy)
|
|
|
|
return II->getOperand(0);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return true if V is really PN, even accounting for predicateinfo copies.
|
|
|
|
static bool isCopyOfPHI(const Value *V, const PHINode *PN) {
|
|
|
|
return V == PN || getCopyOf(V) == PN;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool isCopyOfAPHI(const Value *V) {
|
|
|
|
auto *CO = getCopyOf(V);
|
|
|
|
return CO && isa<PHINode>(CO);
|
2017-09-05 10:17:41 +08:00
|
|
|
}
|
|
|
|
|
2017-10-01 07:51:54 +08:00
|
|
|
// Sort PHI Operands into a canonical order. What we use here is an RPO
|
|
|
|
// order. The BlockInstRange numbers are generated in an RPO walk of the basic
|
|
|
|
// blocks.
|
|
|
|
void NewGVN::sortPHIOps(MutableArrayRef<ValPair> Ops) const {
|
llvm::sort(C.begin(), C.end(), ...) -> llvm::sort(C, ...)
Summary: The convenience wrapper in STLExtras is available since rL342102.
Reviewers: dblaikie, javed.absar, JDevlieghere, andreadb
Subscribers: MatzeB, sanjoy, arsenm, dschuff, mehdi_amini, sdardis, nemanjai, jvesely, nhaehnle, sbc100, jgravelle-google, eraman, aheejin, kbarton, JDevlieghere, javed.absar, gbedwell, jrtc27, mgrang, atanasyan, steven_wu, george.burgess.iv, dexonsmith, kristina, jsji, llvm-commits
Differential Revision: https://reviews.llvm.org/D52573
llvm-svn: 343163
2018-09-27 10:13:45 +08:00
|
|
|
llvm::sort(Ops, [&](const ValPair &P1, const ValPair &P2) {
|
2017-10-01 07:51:54 +08:00
|
|
|
return BlockInstRange.lookup(P1.second).first <
|
|
|
|
BlockInstRange.lookup(P2.second).first;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-10-01 07:51:53 +08:00
|
|
|
// 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.
|
|
|
|
static bool alwaysAvailable(Value *V) {
|
|
|
|
return isa<Constant>(V) || isa<Argument>(V);
|
|
|
|
}
|
|
|
|
|
2017-10-01 07:51:54 +08:00
|
|
|
// Create a PHIExpression from an array of {incoming edge, value} pairs. I is
|
|
|
|
// the original instruction we are creating a PHIExpression for (but may not be
|
|
|
|
// a phi node). We require, as an invariant, that all the PHIOperands in the
|
|
|
|
// same block are sorted the same way. sortPHIOps will sort them into a
|
|
|
|
// canonical order.
|
|
|
|
PHIExpression *NewGVN::createPHIExpression(ArrayRef<ValPair> PHIOperands,
|
|
|
|
const Instruction *I,
|
|
|
|
BasicBlock *PHIBlock,
|
|
|
|
bool &HasBackedge,
|
2017-05-20 03:01:27 +08:00
|
|
|
bool &OriginalOpsConstant) const {
|
2017-10-01 07:51:54 +08:00
|
|
|
unsigned NumOps = PHIOperands.size();
|
|
|
|
auto *E = new (ExpressionAllocator) PHIExpression(NumOps, 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);
|
2017-10-01 07:51:54 +08:00
|
|
|
E->setType(PHIOperands.begin()->first->getType());
|
|
|
|
E->setOpcode(Instruction::PHI);
|
2017-05-10 00:58:28 +08:00
|
|
|
|
2017-01-26 07:37:49 +08:00
|
|
|
// Filter out unreachable phi operands.
|
2017-10-01 07:51:54 +08:00
|
|
|
auto Filtered = make_filter_range(PHIOperands, [&](const ValPair &P) {
|
|
|
|
auto *BB = P.second;
|
|
|
|
if (auto *PHIOp = dyn_cast<PHINode>(I))
|
|
|
|
if (isCopyOfPHI(P.first, PHIOp))
|
|
|
|
return false;
|
2017-09-05 10:17:43 +08:00
|
|
|
if (!ReachableEdges.count({BB, PHIBlock}))
|
2017-05-25 23:44:20 +08:00
|
|
|
return false;
|
|
|
|
// Things in TOPClass are equivalent to everything.
|
2017-10-01 07:51:54 +08:00
|
|
|
if (ValueToClass.lookup(P.first) == TOPClass)
|
2017-05-25 23:44:20 +08:00
|
|
|
return false;
|
2017-10-01 07:51:54 +08:00
|
|
|
OriginalOpsConstant = OriginalOpsConstant && isa<Constant>(P.first);
|
2017-09-05 10:17:43 +08:00
|
|
|
HasBackedge = HasBackedge || isBackedge(BB, PHIBlock);
|
2017-10-01 07:51:54 +08:00
|
|
|
return lookupOperandLeader(P.first) != I;
|
2017-01-26 07:37:49 +08:00
|
|
|
});
|
2017-10-01 07:51:54 +08:00
|
|
|
std::transform(Filtered.begin(), Filtered.end(), op_inserter(E),
|
|
|
|
[&](const ValPair &P) -> Value * {
|
|
|
|
return lookupOperandLeader(P.first);
|
|
|
|
});
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set basic expression info (Arguments, type, opcode) for Expression
|
|
|
|
// E from Instruction I in block B.
|
2017-05-10 00:40:04 +08:00
|
|
|
bool NewGVN::setBasicExpressionInfo(Instruction *I, BasicExpression *E) const {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
bool AllConstant = true;
|
|
|
|
if (auto *GEP = dyn_cast<GetElementPtrInst>(I))
|
|
|
|
E->setType(GEP->getSourceElementType());
|
|
|
|
else
|
|
|
|
E->setType(I->getType());
|
|
|
|
E->setOpcode(I->getOpcode());
|
|
|
|
E->allocateOperands(ArgRecycler, ExpressionAllocator);
|
|
|
|
|
2016-12-27 03:57:25 +08:00
|
|
|
// Transform the operand array into an operand leader array, and keep track of
|
|
|
|
// whether all members are constant.
|
|
|
|
std::transform(I->op_begin(), I->op_end(), op_inserter(E), [&](Value *O) {
|
2017-02-01 06:31:53 +08:00
|
|
|
auto Operand = lookupOperandLeader(O);
|
2017-05-20 03:01:27 +08:00
|
|
|
AllConstant = AllConstant && isa<Constant>(Operand);
|
2016-12-27 03:57:25 +08:00
|
|
|
return Operand;
|
|
|
|
});
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return AllConstant;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Expression *NewGVN::createBinaryExpression(unsigned Opcode, Type *T,
|
2017-09-05 10:17:42 +08:00
|
|
|
Value *Arg1, Value *Arg2,
|
|
|
|
Instruction *I) const {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *E = new (ExpressionAllocator) BasicExpression(2);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
E->setType(T);
|
|
|
|
E->setOpcode(Opcode);
|
|
|
|
E->allocateOperands(ArgRecycler, ExpressionAllocator);
|
|
|
|
if (Instruction::isCommutative(Opcode)) {
|
|
|
|
// Ensure that commutative instructions that only differ by a permutation
|
|
|
|
// of their operands get the same value number by sorting the operand value
|
|
|
|
// numbers. Since all commutative instructions have two operands it is more
|
|
|
|
// efficient to sort by hand rather than using, say, std::sort.
|
2017-02-11 23:07:01 +08:00
|
|
|
if (shouldSwapOperands(Arg1, Arg2))
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
std::swap(Arg1, Arg2);
|
|
|
|
}
|
2017-02-01 06:31:53 +08:00
|
|
|
E->op_push_back(lookupOperandLeader(Arg1));
|
|
|
|
E->op_push_back(lookupOperandLeader(Arg2));
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2017-04-27 04:56:14 +08:00
|
|
|
Value *V = SimplifyBinOp(Opcode, E->getOperand(0), E->getOperand(1), SQ);
|
2017-09-05 10:17:42 +08:00
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, 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
|
|
|
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.
|
|
|
|
const Expression *NewGVN::checkSimplificationResults(Expression *E,
|
2017-05-10 00:40:04 +08:00
|
|
|
Instruction *I,
|
|
|
|
Value *V) const {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (!V)
|
|
|
|
return nullptr;
|
|
|
|
if (auto *C = dyn_cast<Constant>(V)) {
|
|
|
|
if (I)
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Simplified " << *I << " to "
|
|
|
|
<< " constant " << *C << "\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
|
|
|
NumGVNOpsSimplified++;
|
|
|
|
assert(isa<BasicExpression>(E) &&
|
|
|
|
"We should always have had a basic expression here");
|
2017-03-24 14:33:48 +08:00
|
|
|
deleteExpression(E);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return createConstantExpression(C);
|
|
|
|
} else if (isa<Argument>(V) || isa<GlobalVariable>(V)) {
|
|
|
|
if (I)
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Simplified " << *I << " to "
|
|
|
|
<< " variable " << *V << "\n");
|
2017-03-24 14:33:48 +08:00
|
|
|
deleteExpression(E);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return createVariableExpression(V);
|
|
|
|
}
|
|
|
|
|
|
|
|
CongruenceClass *CC = ValueToClass.lookup(V);
|
2017-08-31 03:52:39 +08:00
|
|
|
if (CC) {
|
|
|
|
if (CC->getLeader() && CC->getLeader() != I) {
|
2018-11-08 01:20:07 +08:00
|
|
|
// If we simplified to something else, we need to communicate
|
|
|
|
// that we're users of the value we simplified to.
|
|
|
|
if (I != V) {
|
|
|
|
// Don't add temporary instructions to the user lists.
|
|
|
|
if (!AllTempInstructions.count(I))
|
|
|
|
addAdditionalUsers(V, I);
|
|
|
|
}
|
2017-08-31 03:52:39 +08:00
|
|
|
return createVariableOrConstant(CC->getLeader());
|
2017-05-30 14:42:29 +08:00
|
|
|
}
|
2017-08-31 03:52:39 +08:00
|
|
|
if (CC->getDefiningExpr()) {
|
|
|
|
// If we simplified to something else, we need to communicate
|
|
|
|
// that we're users of the value we simplified to.
|
|
|
|
if (I != V) {
|
|
|
|
// Don't add temporary instructions to the user lists.
|
|
|
|
if (!AllTempInstructions.count(I))
|
|
|
|
addAdditionalUsers(V, I);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (I)
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Simplified " << *I << " to "
|
|
|
|
<< " expression " << *CC->getDefiningExpr() << "\n");
|
2017-08-31 03:52:39 +08:00
|
|
|
NumGVNOpsSimplified++;
|
|
|
|
deleteExpression(E);
|
|
|
|
return CC->getDefiningExpr();
|
|
|
|
}
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
2017-08-31 03:52:39 +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 nullptr;
|
|
|
|
}
|
|
|
|
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
// Create a value expression from the instruction I, replacing operands with
|
|
|
|
// their leaders.
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *NewGVN::createExpression(Instruction *I) const {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *E = new (ExpressionAllocator) BasicExpression(I->getNumOperands());
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2017-02-01 06:32:03 +08:00
|
|
|
bool AllConstant = setBasicExpressionInfo(I, E);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
if (I->isCommutative()) {
|
|
|
|
// Ensure that commutative instructions that only differ by a permutation
|
|
|
|
// of their operands get the same value number by sorting the operand value
|
|
|
|
// numbers. Since all commutative instructions have two operands it is more
|
|
|
|
// efficient to sort by hand rather than using, say, std::sort.
|
|
|
|
assert(I->getNumOperands() == 2 && "Unsupported commutative instruction!");
|
2017-02-13 07:24:42 +08:00
|
|
|
if (shouldSwapOperands(E->getOperand(0), E->getOperand(1)))
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
E->swapOperands(0, 1);
|
|
|
|
}
|
2017-08-03 23:18:27 +08:00
|
|
|
// Perform simplification.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested 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 *CI = dyn_cast<CmpInst>(I)) {
|
|
|
|
// Sort the operand value numbers so x<y and y>x get the same value
|
|
|
|
// number.
|
|
|
|
CmpInst::Predicate Predicate = CI->getPredicate();
|
2017-02-11 23:07:01 +08:00
|
|
|
if (shouldSwapOperands(E->getOperand(0), E->getOperand(1))) {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
E->swapOperands(0, 1);
|
|
|
|
Predicate = CmpInst::getSwappedPredicate(Predicate);
|
|
|
|
}
|
|
|
|
E->setOpcode((CI->getOpcode() << 8) | Predicate);
|
|
|
|
// TODO: 25% of our time is spent in SimplifyCmpInst with pointer operands
|
|
|
|
assert(I->getOperand(0)->getType() == I->getOperand(1)->getType() &&
|
|
|
|
"Wrong types on cmp instruction");
|
2017-02-01 06:32:03 +08:00
|
|
|
assert((E->getOperand(0)->getType() == I->getOperand(0)->getType() &&
|
|
|
|
E->getOperand(1)->getType() == I->getOperand(1)->getType()));
|
2017-04-27 04:56:14 +08:00
|
|
|
Value *V =
|
|
|
|
SimplifyCmpInst(Predicate, E->getOperand(0), E->getOperand(1), SQ);
|
2017-02-01 06:32:01 +08:00
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V))
|
|
|
|
return SimplifiedE;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
} else if (isa<SelectInst>(I)) {
|
|
|
|
if (isa<Constant>(E->getOperand(0)) ||
|
2017-08-24 10:43:17 +08:00
|
|
|
E->getOperand(1) == E->getOperand(2)) {
|
2017-02-01 06:32:03 +08:00
|
|
|
assert(E->getOperand(1)->getType() == I->getOperand(1)->getType() &&
|
|
|
|
E->getOperand(2)->getType() == I->getOperand(2)->getType());
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
Value *V = SimplifySelectInst(E->getOperand(0), E->getOperand(1),
|
2017-04-27 04:56:14 +08:00
|
|
|
E->getOperand(2), SQ);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V))
|
|
|
|
return SimplifiedE;
|
|
|
|
}
|
|
|
|
} else if (I->isBinaryOp()) {
|
2017-04-27 04:56:14 +08:00
|
|
|
Value *V =
|
|
|
|
SimplifyBinOp(E->getOpcode(), E->getOperand(0), E->getOperand(1), SQ);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V))
|
|
|
|
return SimplifiedE;
|
|
|
|
} else if (auto *BI = dyn_cast<BitCastInst>(I)) {
|
2017-04-29 03:55:38 +08:00
|
|
|
Value *V =
|
|
|
|
SimplifyCastInst(BI->getOpcode(), BI->getOperand(0), BI->getType(), SQ);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V))
|
|
|
|
return SimplifiedE;
|
|
|
|
} else if (isa<GetElementPtrInst>(I)) {
|
2017-04-27 04:56:14 +08:00
|
|
|
Value *V = SimplifyGEPInst(
|
|
|
|
E->getType(), ArrayRef<Value *>(E->op_begin(), E->op_end()), SQ);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V))
|
|
|
|
return SimplifiedE;
|
|
|
|
} else if (AllConstant) {
|
|
|
|
// We don't bother trying to simplify unless all of the operands
|
|
|
|
// were constant.
|
|
|
|
// TODO: There are a lot of Simplify*'s we could call here, if we
|
|
|
|
// wanted to. The original motivating case for this code was a
|
|
|
|
// zext i1 false to i8, which we don't have an interface to
|
|
|
|
// simplify (IE there is no SimplifyZExt).
|
|
|
|
|
|
|
|
SmallVector<Constant *, 8> C;
|
|
|
|
for (Value *Arg : E->operands())
|
2016-12-29 07:24:02 +08:00
|
|
|
C.emplace_back(cast<Constant>(Arg));
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2017-03-12 12:46:45 +08:00
|
|
|
if (Value *V = ConstantFoldInstOperands(I, C, DL, TLI))
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (const Expression *SimplifiedE = checkSimplificationResults(E, I, V))
|
|
|
|
return SimplifiedE;
|
|
|
|
}
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
|
|
|
const AggregateValueExpression *
|
2017-05-10 00:40:04 +08:00
|
|
|
NewGVN::createAggregateValueExpression(Instruction *I) const {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (auto *II = dyn_cast<InsertValueInst>(I)) {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *E = new (ExpressionAllocator)
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
AggregateValueExpression(I->getNumOperands(), II->getNumIndices());
|
2017-02-01 06:32:03 +08:00
|
|
|
setBasicExpressionInfo(I, E);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
E->allocateIntOperands(ExpressionAllocator);
|
2016-12-27 03:57:25 +08:00
|
|
|
std::copy(II->idx_begin(), II->idx_end(), int_op_inserter(E));
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return E;
|
|
|
|
} else if (auto *EI = dyn_cast<ExtractValueInst>(I)) {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *E = new (ExpressionAllocator)
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
AggregateValueExpression(I->getNumOperands(), EI->getNumIndices());
|
2017-02-01 06:32:03 +08:00
|
|
|
setBasicExpressionInfo(EI, E);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
E->allocateIntOperands(ExpressionAllocator);
|
2016-12-27 03:57:25 +08:00
|
|
|
std::copy(EI->idx_begin(), EI->idx_end(), int_op_inserter(E));
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
llvm_unreachable("Unhandled type of aggregate value operation");
|
|
|
|
}
|
|
|
|
|
2017-05-20 04:22:20 +08:00
|
|
|
const DeadExpression *NewGVN::createDeadExpression() const {
|
|
|
|
// DeadExpression has no arguments and all DeadExpression's are the same,
|
|
|
|
// so we only need one of them.
|
|
|
|
return SingletonDeadExpression;
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const VariableExpression *NewGVN::createVariableExpression(Value *V) const {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *E = new (ExpressionAllocator) VariableExpression(V);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
E->setOpcode(V->getValueID());
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *NewGVN::createVariableOrConstant(Value *V) const {
|
2017-02-19 07:06:50 +08:00
|
|
|
if (auto *C = dyn_cast<Constant>(V))
|
|
|
|
return createConstantExpression(C);
|
|
|
|
return createVariableExpression(V);
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const ConstantExpression *NewGVN::createConstantExpression(Constant *C) const {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *E = new (ExpressionAllocator) ConstantExpression(C);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
E->setOpcode(C->getValueID());
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const UnknownExpression *NewGVN::createUnknownExpression(Instruction *I) const {
|
2017-01-03 02:00:53 +08:00
|
|
|
auto *E = new (ExpressionAllocator) UnknownExpression(I);
|
|
|
|
E->setOpcode(I->getOpcode());
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const CallExpression *
|
|
|
|
NewGVN::createCallExpression(CallInst *CI, const MemoryAccess *MA) const {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// FIXME: Add operand bundles for calls.
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *E =
|
2017-04-07 02:52:50 +08:00
|
|
|
new (ExpressionAllocator) CallExpression(CI->getNumOperands(), CI, MA);
|
2017-02-01 06:32:03 +08:00
|
|
|
setBasicExpressionInfo(CI, E);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2017-03-24 13:30:34 +08:00
|
|
|
// Return true if some equivalent of instruction Inst dominates instruction U.
|
|
|
|
bool NewGVN::someEquivalentDominates(const Instruction *Inst,
|
|
|
|
const Instruction *U) const {
|
|
|
|
auto *CC = ValueToClass.lookup(Inst);
|
2017-10-01 07:51:53 +08:00
|
|
|
// This must be an instruction because we are only called from phi nodes
|
2017-03-24 14:33:51 +08:00
|
|
|
// in the case that the value it needs to check against is an instruction.
|
|
|
|
|
2018-06-14 13:41:49 +08:00
|
|
|
// The most likely candidates for dominance are the leader and the next leader.
|
2017-03-24 14:33:51 +08:00
|
|
|
// The leader or nextleader will dominate in all cases where there is an
|
|
|
|
// equivalent that is higher up in the dom tree.
|
|
|
|
// We can't *only* check them, however, because the
|
|
|
|
// dominator tree could have an infinite number of non-dominating siblings
|
|
|
|
// with instructions that are in the right congruence class.
|
|
|
|
// A
|
|
|
|
// B C D E F G
|
|
|
|
// |
|
|
|
|
// H
|
|
|
|
// Instruction U could be in H, with equivalents in every other sibling.
|
|
|
|
// Depending on the rpo order picked, the leader could be the equivalent in
|
|
|
|
// any of these siblings.
|
|
|
|
if (!CC)
|
|
|
|
return false;
|
2017-10-01 07:51:53 +08:00
|
|
|
if (alwaysAvailable(CC->getLeader()))
|
|
|
|
return true;
|
2017-04-08 02:38:09 +08:00
|
|
|
if (DT->dominates(cast<Instruction>(CC->getLeader()), U))
|
2017-03-24 14:33:51 +08:00
|
|
|
return true;
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC->getNextLeader().first &&
|
|
|
|
DT->dominates(cast<Instruction>(CC->getNextLeader().first), U))
|
2017-03-24 14:33:51 +08:00
|
|
|
return true;
|
2017-04-08 02:38:09 +08:00
|
|
|
return llvm::any_of(*CC, [&](const Value *Member) {
|
|
|
|
return Member != CC->getLeader() &&
|
2017-03-24 14:33:51 +08:00
|
|
|
DT->dominates(cast<Instruction>(Member), U);
|
|
|
|
});
|
2017-03-24 13:30:34 +08:00
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// See if we have a congruence class and leader for this operand, and if so,
|
|
|
|
// return it. Otherwise, return the operand itself.
|
2017-02-01 06:31:53 +08:00
|
|
|
Value *NewGVN::lookupOperandLeader(Value *V) const {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
CongruenceClass *CC = ValueToClass.lookup(V);
|
2017-02-11 20:48:50 +08:00
|
|
|
if (CC) {
|
2017-05-20 04:22:20 +08:00
|
|
|
// Everything in TOP is represented by undef, as it can be any value.
|
2017-02-11 20:48:50 +08:00
|
|
|
// We do have to make sure we get the type right though, so we can't set the
|
|
|
|
// RepLeader to undef.
|
2017-03-11 03:05:04 +08:00
|
|
|
if (CC == TOPClass)
|
2017-02-11 20:48:50 +08:00
|
|
|
return UndefValue::get(V->getType());
|
2017-04-08 02:38:09 +08:00
|
|
|
return CC->getStoredValue() ? CC->getStoredValue() : CC->getLeader();
|
2017-02-11 20:48:50 +08:00
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
return V;
|
|
|
|
}
|
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
const MemoryAccess *NewGVN::lookupMemoryLeader(const MemoryAccess *MA) const {
|
|
|
|
auto *CC = getMemoryClass(MA);
|
2017-04-08 02:38:09 +08:00
|
|
|
assert(CC->getMemoryLeader() &&
|
2017-05-12 23:25:56 +08:00
|
|
|
"Every MemoryAccess should be mapped to a congruence class with a "
|
|
|
|
"representative memory access");
|
2017-04-08 02:38:09 +08:00
|
|
|
return CC->getMemoryLeader();
|
2016-12-26 06:23:49 +08:00
|
|
|
}
|
|
|
|
|
2017-01-27 10:37:11 +08:00
|
|
|
// Return true if the MemoryAccess is really equivalent to everything. This is
|
|
|
|
// equivalent to the lattice value "TOP" in most lattices. This is the initial
|
2017-04-07 02:52:50 +08:00
|
|
|
// state of all MemoryAccesses.
|
2017-05-20 03:01:27 +08:00
|
|
|
bool NewGVN::isMemoryAccessTOP(const MemoryAccess *MA) const {
|
2017-04-07 02:52:50 +08:00
|
|
|
return getMemoryClass(MA) == TOPClass;
|
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
LoadExpression *NewGVN::createLoadExpression(Type *LoadType, Value *PointerOp,
|
2017-04-07 02:52:50 +08:00
|
|
|
LoadInst *LI,
|
2017-05-10 00:40:04 +08:00
|
|
|
const MemoryAccess *MA) const {
|
2017-04-07 02:52:50 +08:00
|
|
|
auto *E =
|
|
|
|
new (ExpressionAllocator) LoadExpression(1, LI, lookupMemoryLeader(MA));
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
E->allocateOperands(ArgRecycler, ExpressionAllocator);
|
|
|
|
E->setType(LoadType);
|
|
|
|
|
|
|
|
// Give store and loads same opcode so they value number together.
|
|
|
|
E->setOpcode(0);
|
2017-04-07 02:52:50 +08:00
|
|
|
E->op_push_back(PointerOp);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (LI)
|
|
|
|
E->setAlignment(LI->getAlignment());
|
|
|
|
|
|
|
|
// TODO: Value number heap versions. We may be able to discover
|
|
|
|
// things alias analysis can't on it's own (IE that a store and a
|
|
|
|
// load have the same value, and thus, it isn't clobbering the load).
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const StoreExpression *
|
|
|
|
NewGVN::createStoreExpression(StoreInst *SI, const MemoryAccess *MA) const {
|
2017-02-01 06:31:53 +08:00
|
|
|
auto *StoredValueLeader = lookupOperandLeader(SI->getValueOperand());
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
auto *E = new (ExpressionAllocator)
|
2017-04-07 02:52:50 +08:00
|
|
|
StoreExpression(SI->getNumOperands(), SI, StoredValueLeader, MA);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
E->allocateOperands(ArgRecycler, ExpressionAllocator);
|
|
|
|
E->setType(SI->getValueOperand()->getType());
|
|
|
|
|
|
|
|
// Give store and loads same opcode so they value number together.
|
|
|
|
E->setOpcode(0);
|
2017-02-01 06:31:53 +08:00
|
|
|
E->op_push_back(lookupOperandLeader(SI->getPointerOperand()));
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// TODO: Value number heap versions. We may be able to discover
|
|
|
|
// things alias analysis can't on it's own (IE that a store and a
|
|
|
|
// load have the same value, and thus, it isn't clobbering the load).
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *NewGVN::performSymbolicStoreEvaluation(Instruction *I) const {
|
2017-01-03 02:00:46 +08:00
|
|
|
// Unlike loads, we never try to eliminate stores, so we do not check if they
|
|
|
|
// are simple and avoid value numbering them.
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *SI = cast<StoreInst>(I);
|
2017-05-20 03:01:27 +08:00
|
|
|
auto *StoreAccess = getMemoryAccess(SI);
|
2017-01-27 10:37:11 +08:00
|
|
|
// Get the expression, if any, for the RHS of the MemoryDef.
|
2017-04-07 02:52:50 +08:00
|
|
|
const MemoryAccess *StoreRHS = StoreAccess->getDefiningAccess();
|
|
|
|
if (EnableStoreRefinement)
|
|
|
|
StoreRHS = MSSAWalker->getClobberingMemoryAccess(StoreAccess);
|
|
|
|
// If we bypassed the use-def chains, make sure we add a use.
|
2017-08-26 15:37:11 +08:00
|
|
|
StoreRHS = lookupMemoryLeader(StoreRHS);
|
2017-04-07 02:52:50 +08:00
|
|
|
if (StoreRHS != StoreAccess->getDefiningAccess())
|
|
|
|
addMemoryUsers(StoreRHS, StoreAccess);
|
2017-01-27 10:37:11 +08:00
|
|
|
// If we are defined by ourselves, use the live on entry def.
|
|
|
|
if (StoreRHS == StoreAccess)
|
|
|
|
StoreRHS = MSSA->getLiveOnEntryDef();
|
|
|
|
|
2017-01-03 02:00:46 +08:00
|
|
|
if (SI->isSimple()) {
|
2017-01-27 10:37:11 +08:00
|
|
|
// See if we are defined by a previous store expression, it already has a
|
|
|
|
// value, and it's the same value as our current store. FIXME: Right now, we
|
|
|
|
// only do this for simple stores, we should expand to cover memcpys, etc.
|
2017-04-07 02:52:50 +08:00
|
|
|
const auto *LastStore = createStoreExpression(SI, StoreRHS);
|
|
|
|
const auto *LastCC = ExpressionToClass.lookup(LastStore);
|
2017-06-19 08:24:00 +08:00
|
|
|
// We really want to check whether the expression we matched was a store. No
|
|
|
|
// easy way to do that. However, we can check that the class we found has a
|
|
|
|
// store, which, assuming the value numbering state is not corrupt, is
|
|
|
|
// sufficient, because we must also be equivalent to that store's expression
|
|
|
|
// for it to be in the same class as the load.
|
|
|
|
if (LastCC && LastCC->getStoredValue() == LastStore->getStoredValue())
|
2017-04-07 02:52:50 +08:00
|
|
|
return LastStore;
|
2017-01-27 10:37:11 +08:00
|
|
|
// Also check if our value operand is defined by a load of the same memory
|
2017-04-07 02:52:50 +08:00
|
|
|
// location, and the memory state is the same as it was then (otherwise, it
|
|
|
|
// could have been overwritten later. See test32 in
|
|
|
|
// transforms/DeadStoreElimination/simple.ll).
|
2017-06-19 08:24:00 +08:00
|
|
|
if (auto *LI = dyn_cast<LoadInst>(LastStore->getStoredValue()))
|
2017-02-01 06:31:53 +08:00
|
|
|
if ((lookupOperandLeader(LI->getPointerOperand()) ==
|
2017-06-19 08:24:00 +08:00
|
|
|
LastStore->getOperand(0)) &&
|
2017-05-20 03:01:27 +08:00
|
|
|
(lookupMemoryLeader(getMemoryAccess(LI)->getDefiningAccess()) ==
|
2017-04-07 02:52:50 +08:00
|
|
|
StoreRHS))
|
2017-06-19 08:24:00 +08:00
|
|
|
return LastStore;
|
|
|
|
deleteExpression(LastStore);
|
2016-12-26 06:23:49 +08:00
|
|
|
}
|
2017-04-07 02:52:50 +08:00
|
|
|
|
|
|
|
// If the store is not equivalent to anything, value number it as a store that
|
|
|
|
// produces a unique memory state (instead of using it's MemoryUse, we use
|
|
|
|
// it's MemoryDef).
|
2017-02-01 06:32:03 +08:00
|
|
|
return createStoreExpression(SI, StoreAccess);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
2017-04-02 21:23:44 +08:00
|
|
|
// See if we can extract the value of a loaded pointer from a load, a store, or
|
|
|
|
// a memory instruction.
|
|
|
|
const Expression *
|
|
|
|
NewGVN::performSymbolicLoadCoercion(Type *LoadType, Value *LoadPtr,
|
|
|
|
LoadInst *LI, Instruction *DepInst,
|
2017-05-10 00:40:04 +08:00
|
|
|
MemoryAccess *DefiningAccess) const {
|
2017-04-02 21:23:44 +08:00
|
|
|
assert((!LI || LI->isSimple()) && "Not a simple load");
|
|
|
|
if (auto *DepSI = dyn_cast<StoreInst>(DepInst)) {
|
|
|
|
// Can't forward from non-atomic to atomic without violating memory model.
|
|
|
|
// Also don't need to coerce if they are the same type, we will just
|
2017-08-03 23:18:27 +08:00
|
|
|
// propagate.
|
2017-04-02 21:23:44 +08:00
|
|
|
if (LI->isAtomic() > DepSI->isAtomic() ||
|
|
|
|
LoadType == DepSI->getValueOperand()->getType())
|
|
|
|
return nullptr;
|
|
|
|
int Offset = analyzeLoadFromClobberingStore(LoadType, LoadPtr, DepSI, DL);
|
|
|
|
if (Offset >= 0) {
|
|
|
|
if (auto *C = dyn_cast<Constant>(
|
|
|
|
lookupOperandLeader(DepSI->getValueOperand()))) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Coercing load from store " << *DepSI
|
|
|
|
<< " to constant " << *C << "\n");
|
2017-04-02 21:23:44 +08:00
|
|
|
return createConstantExpression(
|
|
|
|
getConstantStoreValueForLoad(C, Offset, LoadType, DL));
|
|
|
|
}
|
|
|
|
}
|
2017-08-27 06:31:10 +08:00
|
|
|
} else if (auto *DepLI = dyn_cast<LoadInst>(DepInst)) {
|
2017-04-02 21:23:44 +08:00
|
|
|
// Can't forward from non-atomic to atomic without violating memory model.
|
|
|
|
if (LI->isAtomic() > DepLI->isAtomic())
|
|
|
|
return nullptr;
|
|
|
|
int Offset = analyzeLoadFromClobberingLoad(LoadType, LoadPtr, DepLI, DL);
|
|
|
|
if (Offset >= 0) {
|
2017-08-03 23:18:27 +08:00
|
|
|
// We can coerce a constant load into a load.
|
2017-04-02 21:23:44 +08:00
|
|
|
if (auto *C = dyn_cast<Constant>(lookupOperandLeader(DepLI)))
|
|
|
|
if (auto *PossibleConstant =
|
|
|
|
getConstantLoadValueForLoad(C, Offset, LoadType, DL)) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Coercing load from load " << *LI
|
|
|
|
<< " to constant " << *PossibleConstant << "\n");
|
2017-04-02 21:23:44 +08:00
|
|
|
return createConstantExpression(PossibleConstant);
|
|
|
|
}
|
|
|
|
}
|
2017-08-27 06:31:10 +08:00
|
|
|
} else if (auto *DepMI = dyn_cast<MemIntrinsic>(DepInst)) {
|
2017-04-02 21:23:44 +08:00
|
|
|
int Offset = analyzeLoadFromClobberingMemInst(LoadType, LoadPtr, DepMI, DL);
|
|
|
|
if (Offset >= 0) {
|
|
|
|
if (auto *PossibleConstant =
|
|
|
|
getConstantMemInstValueForLoad(DepMI, Offset, LoadType, DL)) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Coercing load from meminst " << *DepMI
|
|
|
|
<< " to constant " << *PossibleConstant << "\n");
|
2017-04-02 21:23:44 +08:00
|
|
|
return createConstantExpression(PossibleConstant);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// All of the below are only true if the loaded pointer is produced
|
|
|
|
// by the dependent instruction.
|
|
|
|
if (LoadPtr != lookupOperandLeader(DepInst) &&
|
|
|
|
!AA->isMustAlias(LoadPtr, DepInst))
|
|
|
|
return nullptr;
|
|
|
|
// If this load really doesn't depend on anything, then we must be loading an
|
|
|
|
// undef value. This can happen when loading for a fresh allocation with no
|
|
|
|
// intervening stores, for example. Note that this is only true in the case
|
|
|
|
// that the result of the allocation is pointer equal to the load ptr.
|
|
|
|
if (isa<AllocaInst>(DepInst) || isMallocLikeFn(DepInst, TLI)) {
|
|
|
|
return createConstantExpression(UndefValue::get(LoadType));
|
|
|
|
}
|
|
|
|
// If this load occurs either right after a lifetime begin,
|
|
|
|
// then the loaded value is undefined.
|
|
|
|
else if (auto *II = dyn_cast<IntrinsicInst>(DepInst)) {
|
|
|
|
if (II->getIntrinsicID() == Intrinsic::lifetime_start)
|
|
|
|
return createConstantExpression(UndefValue::get(LoadType));
|
|
|
|
}
|
|
|
|
// If this load follows a calloc (which zero initializes memory),
|
|
|
|
// then the loaded value is zero
|
|
|
|
else if (isCallocLikeFn(DepInst, TLI)) {
|
|
|
|
return createConstantExpression(Constant::getNullValue(LoadType));
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *NewGVN::performSymbolicLoadEvaluation(Instruction *I) const {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *LI = cast<LoadInst>(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// We can eliminate in favor of non-simple loads, but we won't be able to
|
2017-01-03 02:00:46 +08:00
|
|
|
// eliminate the loads themselves.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (!LI->isSimple())
|
|
|
|
return nullptr;
|
|
|
|
|
2017-02-01 06:31:53 +08:00
|
|
|
Value *LoadAddressLeader = lookupOperandLeader(LI->getPointerOperand());
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Load of undef is undef.
|
|
|
|
if (isa<UndefValue>(LoadAddressLeader))
|
|
|
|
return createConstantExpression(UndefValue::get(LI->getType()));
|
2017-05-20 03:01:27 +08:00
|
|
|
MemoryAccess *OriginalAccess = getMemoryAccess(I);
|
|
|
|
MemoryAccess *DefiningAccess =
|
|
|
|
MSSAWalker->getClobberingMemoryAccess(OriginalAccess);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested 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 (!MSSA->isLiveOnEntryDef(DefiningAccess)) {
|
|
|
|
if (auto *MD = dyn_cast<MemoryDef>(DefiningAccess)) {
|
|
|
|
Instruction *DefiningInst = MD->getMemoryInst();
|
|
|
|
// If the defining instruction is not reachable, replace with undef.
|
|
|
|
if (!ReachableBlocks.count(DefiningInst->getParent()))
|
|
|
|
return createConstantExpression(UndefValue::get(LI->getType()));
|
2017-04-02 21:23:44 +08:00
|
|
|
// This will handle stores and memory insts. We only do if it the
|
|
|
|
// defining access has a different type, or it is a pointer produced by
|
|
|
|
// certain memory operations that cause the memory to have a fixed value
|
|
|
|
// (IE things like calloc).
|
2017-04-07 02:52:53 +08:00
|
|
|
if (const auto *CoercionResult =
|
|
|
|
performSymbolicLoadCoercion(LI->getType(), LoadAddressLeader, LI,
|
|
|
|
DefiningInst, DefiningAccess))
|
2017-04-02 21:23:44 +08:00
|
|
|
return CoercionResult;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
const auto *LE = createLoadExpression(LI->getType(), LoadAddressLeader, LI,
|
|
|
|
DefiningAccess);
|
2017-08-26 15:37:11 +08:00
|
|
|
// If our MemoryLeader is not our defining access, add a use to the
|
|
|
|
// MemoryLeader, so that we get reprocessed when it changes.
|
|
|
|
if (LE->getMemoryLeader() != DefiningAccess)
|
|
|
|
addMemoryUsers(LE->getMemoryLeader(), OriginalAccess);
|
|
|
|
return LE;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
2017-02-19 07:06:50 +08:00
|
|
|
const Expression *
|
2017-05-10 00:40:04 +08:00
|
|
|
NewGVN::performSymbolicPredicateInfoEvaluation(Instruction *I) const {
|
2017-02-19 07:06:50 +08:00
|
|
|
auto *PI = PredInfo->getPredicateInfoFor(I);
|
|
|
|
if (!PI)
|
|
|
|
return nullptr;
|
|
|
|
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Found predicate info from instruction !\n");
|
2017-02-23 06:20:58 +08:00
|
|
|
|
|
|
|
auto *PWC = dyn_cast<PredicateWithCondition>(PI);
|
|
|
|
if (!PWC)
|
2017-02-19 07:06:50 +08:00
|
|
|
return nullptr;
|
|
|
|
|
2017-02-23 06:20:58 +08:00
|
|
|
auto *CopyOf = I->getOperand(0);
|
|
|
|
auto *Cond = PWC->Condition;
|
|
|
|
|
2017-02-19 07:06:50 +08:00
|
|
|
// If this a copy of the condition, it must be either true or false depending
|
2017-08-03 23:18:27 +08:00
|
|
|
// on the predicate info type and edge.
|
2017-02-19 07:06:50 +08:00
|
|
|
if (CopyOf == Cond) {
|
2017-02-23 06:20:58 +08:00
|
|
|
// We should not need to add predicate users because the predicate info is
|
|
|
|
// already a use of this operand.
|
2017-02-19 07:06:50 +08:00
|
|
|
if (isa<PredicateAssume>(PI))
|
|
|
|
return createConstantExpression(ConstantInt::getTrue(Cond->getType()));
|
|
|
|
if (auto *PBranch = dyn_cast<PredicateBranch>(PI)) {
|
|
|
|
if (PBranch->TrueEdge)
|
|
|
|
return createConstantExpression(ConstantInt::getTrue(Cond->getType()));
|
|
|
|
return createConstantExpression(ConstantInt::getFalse(Cond->getType()));
|
|
|
|
}
|
2017-02-23 06:20:58 +08:00
|
|
|
if (auto *PSwitch = dyn_cast<PredicateSwitch>(PI))
|
|
|
|
return createConstantExpression(cast<Constant>(PSwitch->CaseValue));
|
2017-02-19 07:06:50 +08:00
|
|
|
}
|
2017-02-23 06:20:58 +08:00
|
|
|
|
2017-02-19 07:06:50 +08:00
|
|
|
// Not a copy of the condition, so see what the predicates tell us about this
|
|
|
|
// value. First, though, we check to make sure the value is actually a copy
|
|
|
|
// of one of the condition operands. It's possible, in certain cases, for it
|
|
|
|
// to be a copy of a predicateinfo copy. In particular, if two branch
|
|
|
|
// operations use the same condition, and one branch dominates the other, we
|
|
|
|
// will end up with a copy of a copy. This is currently a small deficiency in
|
2017-02-23 06:20:58 +08:00
|
|
|
// predicateinfo. What will end up happening here is that we will value
|
2017-02-19 07:06:50 +08:00
|
|
|
// number both copies the same anyway.
|
2017-02-23 06:20:58 +08:00
|
|
|
|
|
|
|
// Everything below relies on the condition being a comparison.
|
|
|
|
auto *Cmp = dyn_cast<CmpInst>(Cond);
|
|
|
|
if (!Cmp)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if (CopyOf != Cmp->getOperand(0) && CopyOf != Cmp->getOperand(1)) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Copy is not of any condition operands!\n");
|
2017-02-19 07:06:50 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
2017-02-23 06:20:58 +08:00
|
|
|
Value *FirstOp = lookupOperandLeader(Cmp->getOperand(0));
|
|
|
|
Value *SecondOp = lookupOperandLeader(Cmp->getOperand(1));
|
2017-02-19 07:06:50 +08:00
|
|
|
bool SwappedOps = false;
|
2017-08-03 23:18:27 +08:00
|
|
|
// Sort the ops.
|
2017-02-19 07:06:50 +08:00
|
|
|
if (shouldSwapOperands(FirstOp, SecondOp)) {
|
|
|
|
std::swap(FirstOp, SecondOp);
|
|
|
|
SwappedOps = true;
|
|
|
|
}
|
|
|
|
CmpInst::Predicate Predicate =
|
|
|
|
SwappedOps ? Cmp->getSwappedPredicate() : Cmp->getPredicate();
|
|
|
|
|
|
|
|
if (isa<PredicateAssume>(PI)) {
|
2018-05-23 01:38:22 +08:00
|
|
|
// If we assume the operands are equal, then they are equal.
|
|
|
|
if (Predicate == CmpInst::ICMP_EQ) {
|
2017-02-19 07:06:50 +08:00
|
|
|
addPredicateUsers(PI, I);
|
2018-05-23 01:38:22 +08:00
|
|
|
addAdditionalUsers(SwappedOps ? Cmp->getOperand(1) : Cmp->getOperand(0),
|
|
|
|
I);
|
2017-02-19 07:06:50 +08:00
|
|
|
return createVariableOrConstant(FirstOp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (const auto *PBranch = dyn_cast<PredicateBranch>(PI)) {
|
|
|
|
// If we are *not* a copy of the comparison, we may equal to the other
|
|
|
|
// operand when the predicate implies something about equality of
|
|
|
|
// operations. In particular, if the comparison is true/false when the
|
|
|
|
// operands are equal, and we are on the right edge, we know this operation
|
|
|
|
// is equal to something.
|
|
|
|
if ((PBranch->TrueEdge && Predicate == CmpInst::ICMP_EQ) ||
|
|
|
|
(!PBranch->TrueEdge && Predicate == CmpInst::ICMP_NE)) {
|
|
|
|
addPredicateUsers(PI, I);
|
2017-08-31 03:53:23 +08:00
|
|
|
addAdditionalUsers(SwappedOps ? Cmp->getOperand(1) : Cmp->getOperand(0),
|
|
|
|
I);
|
2017-02-19 07:06:50 +08:00
|
|
|
return createVariableOrConstant(FirstOp);
|
|
|
|
}
|
|
|
|
// Handle the special case of floating point.
|
|
|
|
if (((PBranch->TrueEdge && Predicate == CmpInst::FCMP_OEQ) ||
|
|
|
|
(!PBranch->TrueEdge && Predicate == CmpInst::FCMP_UNE)) &&
|
|
|
|
isa<ConstantFP>(FirstOp) && !cast<ConstantFP>(FirstOp)->isZero()) {
|
|
|
|
addPredicateUsers(PI, I);
|
2017-08-31 03:53:23 +08:00
|
|
|
addAdditionalUsers(SwappedOps ? Cmp->getOperand(1) : Cmp->getOperand(0),
|
|
|
|
I);
|
2017-02-19 07:06:50 +08:00
|
|
|
return createConstantExpression(cast<Constant>(FirstOp));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Evaluate read only and pure calls, and create an expression result.
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *NewGVN::performSymbolicCallEvaluation(Instruction *I) const {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *CI = cast<CallInst>(I);
|
2017-02-19 07:06:50 +08:00
|
|
|
if (auto *II = dyn_cast<IntrinsicInst>(I)) {
|
2018-06-14 13:41:49 +08:00
|
|
|
// Intrinsics with the returned attribute are copies of arguments.
|
2017-02-19 07:06:50 +08:00
|
|
|
if (auto *ReturnedValue = II->getReturnedArgOperand()) {
|
|
|
|
if (II->getIntrinsicID() == Intrinsic::ssa_copy)
|
|
|
|
if (const auto *Result = performSymbolicPredicateInfoEvaluation(I))
|
|
|
|
return Result;
|
|
|
|
return createVariableOrConstant(ReturnedValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (AA->doesNotAccessMemory(CI)) {
|
2017-04-08 02:38:09 +08:00
|
|
|
return createCallExpression(CI, TOPClass->getMemoryLeader());
|
2017-02-19 07:06:50 +08:00
|
|
|
} else if (AA->onlyReadsMemory(CI)) {
|
2016-12-27 03:57:25 +08:00
|
|
|
MemoryAccess *DefiningAccess = MSSAWalker->getClobberingMemoryAccess(CI);
|
2017-04-07 02:52:50 +08:00
|
|
|
return createCallExpression(CI, DefiningAccess);
|
2016-12-28 02:15:39 +08:00
|
|
|
}
|
|
|
|
return nullptr;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
// Retrieve the memory class for a given MemoryAccess.
|
|
|
|
CongruenceClass *NewGVN::getMemoryClass(const MemoryAccess *MA) const {
|
|
|
|
auto *Result = MemoryAccessToClass.lookup(MA);
|
|
|
|
assert(Result && "Should have found memory class");
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the MemoryAccess equivalence table to say that From is equal to To,
|
2016-12-26 06:23:49 +08:00
|
|
|
// and return true if this is different from what already existed in the table.
|
2017-04-07 02:52:50 +08:00
|
|
|
bool NewGVN::setMemoryClass(const MemoryAccess *From,
|
|
|
|
CongruenceClass *NewClass) {
|
|
|
|
assert(NewClass &&
|
|
|
|
"Every MemoryAccess should be getting mapped to a non-null class");
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Setting " << *From);
|
|
|
|
LLVM_DEBUG(dbgs() << " equivalent to congruence class ");
|
|
|
|
LLVM_DEBUG(dbgs() << NewClass->getID()
|
|
|
|
<< " with current MemoryAccess leader ");
|
|
|
|
LLVM_DEBUG(dbgs() << *NewClass->getMemoryLeader() << "\n");
|
2017-01-27 06:21:48 +08:00
|
|
|
|
|
|
|
auto LookupResult = MemoryAccessToClass.find(From);
|
2016-12-26 06:23:49 +08:00
|
|
|
bool Changed = false;
|
|
|
|
// If it's already in the table, see if the value changed.
|
2017-01-27 06:21:48 +08:00
|
|
|
if (LookupResult != MemoryAccessToClass.end()) {
|
2017-04-07 02:52:50 +08:00
|
|
|
auto *OldClass = LookupResult->second;
|
|
|
|
if (OldClass != NewClass) {
|
|
|
|
// If this is a phi, we have to handle memory member updates.
|
|
|
|
if (auto *MP = dyn_cast<MemoryPhi>(From)) {
|
2017-04-08 02:38:09 +08:00
|
|
|
OldClass->memory_erase(MP);
|
|
|
|
NewClass->memory_insert(MP);
|
2017-04-07 02:52:50 +08:00
|
|
|
// This may have killed the class if it had no non-memory members
|
2017-04-08 02:38:09 +08:00
|
|
|
if (OldClass->getMemoryLeader() == From) {
|
2017-05-12 23:22:45 +08:00
|
|
|
if (OldClass->definesNoMemory()) {
|
2017-04-08 02:38:09 +08:00
|
|
|
OldClass->setMemoryLeader(nullptr);
|
2017-04-07 02:52:50 +08:00
|
|
|
} else {
|
2017-04-08 02:38:09 +08:00
|
|
|
OldClass->setMemoryLeader(getNextMemoryLeader(OldClass));
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Memory class leader change for class "
|
|
|
|
<< OldClass->getID() << " to "
|
|
|
|
<< *OldClass->getMemoryLeader()
|
|
|
|
<< " due to removal of a memory member " << *From
|
|
|
|
<< "\n");
|
2017-04-07 02:52:50 +08:00
|
|
|
markMemoryLeaderChangeTouched(OldClass);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-12-26 06:23:49 +08:00
|
|
|
// It wasn't equivalent before, and now it is.
|
2017-04-07 02:52:50 +08:00
|
|
|
LookupResult->second = NewClass;
|
2016-12-26 06:23:49 +08:00
|
|
|
Changed = true;
|
|
|
|
}
|
|
|
|
}
|
2017-01-03 02:00:46 +08:00
|
|
|
|
2016-12-26 06:23:49 +08:00
|
|
|
return Changed;
|
|
|
|
}
|
2017-03-24 14:33:48 +08:00
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
// Determine if a instruction is cycle-free. That means the values in the
|
|
|
|
// instruction don't depend on any expressions that can change value as a result
|
|
|
|
// of the instruction. For example, a non-cycle free instruction would be v =
|
|
|
|
// phi(0, v+1).
|
|
|
|
bool NewGVN::isCycleFree(const Instruction *I) const {
|
|
|
|
// In order to compute cycle-freeness, we do SCC finding on the instruction,
|
|
|
|
// and see what kind of SCC it ends up in. If it is a singleton, it is
|
|
|
|
// cycle-free. If it is not in a singleton, it is only cycle free if the
|
|
|
|
// other members are all phi nodes (as they do not compute anything, they are
|
|
|
|
// copies).
|
|
|
|
auto ICS = InstCycleState.lookup(I);
|
|
|
|
if (ICS == ICS_Unknown) {
|
|
|
|
SCCFinder.Start(I);
|
|
|
|
auto &SCC = SCCFinder.getComponentFor(I);
|
2018-04-12 13:53:20 +08:00
|
|
|
// It's cycle free if it's size 1 or the SCC is *only* phi nodes.
|
2017-04-14 10:53:37 +08:00
|
|
|
if (SCC.size() == 1)
|
2017-05-20 03:01:27 +08:00
|
|
|
InstCycleState.insert({I, ICS_CycleFree});
|
2017-04-14 10:53:37 +08:00
|
|
|
else {
|
2017-09-05 10:17:43 +08:00
|
|
|
bool AllPhis = llvm::all_of(SCC, [](const Value *V) {
|
|
|
|
return isa<PHINode>(V) || isCopyOfAPHI(V);
|
|
|
|
});
|
2017-05-20 03:01:27 +08:00
|
|
|
ICS = AllPhis ? ICS_CycleFree : ICS_Cycle;
|
2017-04-14 10:53:37 +08:00
|
|
|
for (auto *Member : SCC)
|
|
|
|
if (auto *MemberPhi = dyn_cast<PHINode>(Member))
|
2017-05-20 03:01:27 +08:00
|
|
|
InstCycleState.insert({MemberPhi, ICS});
|
2017-04-14 10:53:37 +08:00
|
|
|
}
|
|
|
|
}
|
2017-05-20 03:01:27 +08:00
|
|
|
if (ICS == ICS_Cycle)
|
2017-04-14 10:53:37 +08:00
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-08-03 23:18:27 +08:00
|
|
|
// Evaluate PHI nodes symbolically and create an expression result.
|
2017-10-01 07:51:54 +08:00
|
|
|
const Expression *
|
|
|
|
NewGVN::performSymbolicPHIEvaluation(ArrayRef<ValPair> PHIOps,
|
|
|
|
Instruction *I,
|
|
|
|
BasicBlock *PHIBlock) const {
|
2017-04-14 10:53:37 +08:00
|
|
|
// True if one of the incoming phi edges is a backedge.
|
|
|
|
bool HasBackedge = false;
|
|
|
|
// All constant tracks the state of whether all the *original* phi operands
|
2017-05-20 04:22:20 +08:00
|
|
|
// This is really shorthand for "this phi cannot cycle due to forward
|
|
|
|
// change in value of the phi is guaranteed not to later change the value of
|
|
|
|
// the phi. IE it can't be v = phi(undef, v+1)
|
2017-09-05 10:17:43 +08:00
|
|
|
bool OriginalOpsConstant = true;
|
2017-10-01 07:51:54 +08:00
|
|
|
auto *E = cast<PHIExpression>(createPHIExpression(
|
|
|
|
PHIOps, I, PHIBlock, HasBackedge, OriginalOpsConstant));
|
2017-01-07 08:01:42 +08:00
|
|
|
// We match the semantics of SimplifyPhiNode from InstructionSimplify here.
|
2017-05-03 05:11:40 +08:00
|
|
|
// See if all arguments are the same.
|
2017-01-07 08:01:42 +08:00
|
|
|
// We track if any were undef because they need special handling.
|
|
|
|
bool HasUndef = false;
|
2017-05-20 04:22:20 +08:00
|
|
|
auto Filtered = make_filter_range(E->operands(), [&](Value *Arg) {
|
2017-01-07 08:01:42 +08:00
|
|
|
if (isa<UndefValue>(Arg)) {
|
|
|
|
HasUndef = true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
});
|
2017-05-20 04:22:20 +08:00
|
|
|
// If we are left with no operands, it's dead.
|
2018-10-31 08:23:23 +08:00
|
|
|
if (empty(Filtered)) {
|
2017-05-25 23:44:20 +08:00
|
|
|
// If it has undef at this point, it means there are no-non-undef arguments,
|
|
|
|
// and thus, the value of the phi node must be undef.
|
|
|
|
if (HasUndef) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(
|
|
|
|
dbgs() << "PHI Node " << *I
|
|
|
|
<< " has no non-undef arguments, valuing it as undef\n");
|
2017-05-25 23:44:20 +08:00
|
|
|
return createConstantExpression(UndefValue::get(I->getType()));
|
|
|
|
}
|
|
|
|
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "No arguments of PHI node " << *I << " are live\n");
|
2017-03-24 14:33:48 +08:00
|
|
|
deleteExpression(E);
|
2017-05-20 04:22:20 +08:00
|
|
|
return createDeadExpression();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested 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-07 08:01:42 +08:00
|
|
|
Value *AllSameValue = *(Filtered.begin());
|
|
|
|
++Filtered.begin();
|
|
|
|
// Can't use std::equal here, sadly, because filter.begin moves.
|
2017-09-05 10:17:43 +08:00
|
|
|
if (llvm::all_of(Filtered, [&](Value *Arg) { return Arg == AllSameValue; })) {
|
2017-01-07 08:01:42 +08:00
|
|
|
// In LLVM's non-standard representation of phi nodes, it's possible to have
|
|
|
|
// phi nodes with cycles (IE dependent on other phis that are .... dependent
|
|
|
|
// on the original phi node), especially in weird CFG's where some arguments
|
|
|
|
// are unreachable, or uninitialized along certain paths. This can cause
|
|
|
|
// infinite loops during evaluation. We work around this by not trying to
|
|
|
|
// really evaluate them independently, but instead using a variable
|
|
|
|
// expression to say if one is equivalent to the other.
|
|
|
|
// We also special case undef, so that if we have an undef, we can't use the
|
|
|
|
// common value unless it dominates the phi block.
|
|
|
|
if (HasUndef) {
|
2017-04-14 10:53:37 +08:00
|
|
|
// If we have undef and at least one other value, this is really a
|
|
|
|
// multivalued phi, and we need to know if it's cycle free in order to
|
|
|
|
// evaluate whether we can ignore the undef. The other parts of this are
|
|
|
|
// just shortcuts. If there is no backedge, or all operands are
|
2017-09-05 10:17:43 +08:00
|
|
|
// constants, it also must be cycle free.
|
|
|
|
if (HasBackedge && !OriginalOpsConstant &&
|
2017-05-25 23:44:20 +08:00
|
|
|
!isa<UndefValue>(AllSameValue) && !isCycleFree(I))
|
2017-04-14 10:53:37 +08:00
|
|
|
return E;
|
|
|
|
|
2017-01-07 08:01:42 +08:00
|
|
|
// Only have to check for instructions
|
2017-01-07 10:05:50 +08:00
|
|
|
if (auto *AllSameInst = dyn_cast<Instruction>(AllSameValue))
|
2017-03-24 13:30:34 +08:00
|
|
|
if (!someEquivalentDominates(AllSameInst, I))
|
2017-01-07 08:01:42 +08:00
|
|
|
return E;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
2017-06-07 01:15:28 +08:00
|
|
|
// Can't simplify to something that comes later in the iteration.
|
|
|
|
// Otherwise, when and if it changes congruence class, we will never catch
|
|
|
|
// up. We will always be a class behind it.
|
|
|
|
if (isa<Instruction>(AllSameValue) &&
|
|
|
|
InstrToDFSNum(AllSameValue) > InstrToDFSNum(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++;
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Simplified PHI node " << *I << " to " << *AllSameValue
|
|
|
|
<< "\n");
|
2017-03-24 14:33:48 +08:00
|
|
|
deleteExpression(E);
|
2017-02-19 07:06:50 +08:00
|
|
|
return createVariableOrConstant(AllSameValue);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *
|
|
|
|
NewGVN::performSymbolicAggrValueEvaluation(Instruction *I) const {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (auto *EI = dyn_cast<ExtractValueInst>(I)) {
|
2019-04-17 02:55:16 +08:00
|
|
|
auto *WO = dyn_cast<WithOverflowInst>(EI->getAggregateOperand());
|
|
|
|
if (WO && EI->getNumIndices() == 1 && *EI->idx_begin() == 0)
|
|
|
|
// EI is an extract from one of our with.overflow intrinsics. Synthesize
|
|
|
|
// a semantically equivalent expression instead of an extract value
|
|
|
|
// expression.
|
|
|
|
return createBinaryExpression(WO->getBinaryOp(), EI->getType(),
|
|
|
|
WO->getLHS(), WO->getRHS(), 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-02-01 06:32:03 +08:00
|
|
|
return createAggregateValueExpression(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
const Expression *NewGVN::performSymbolicCmpEvaluation(Instruction *I) const {
|
2017-08-09 02:41:49 +08:00
|
|
|
assert(isa<CmpInst>(I) && "Expected a cmp instruction.");
|
|
|
|
|
|
|
|
auto *CI = cast<CmpInst>(I);
|
2017-02-19 07:06:50 +08:00
|
|
|
// See if our operands are equal to those of a previous predicate, and if so,
|
|
|
|
// if it implies true or false.
|
2017-02-01 06:31:58 +08:00
|
|
|
auto Op0 = lookupOperandLeader(CI->getOperand(0));
|
|
|
|
auto Op1 = lookupOperandLeader(CI->getOperand(1));
|
2017-02-19 07:06:50 +08:00
|
|
|
auto OurPredicate = CI->getPredicate();
|
2017-03-04 08:44:43 +08:00
|
|
|
if (shouldSwapOperands(Op0, Op1)) {
|
2017-02-19 07:06:50 +08:00
|
|
|
std::swap(Op0, Op1);
|
|
|
|
OurPredicate = CI->getSwappedPredicate();
|
|
|
|
}
|
|
|
|
|
2017-08-03 23:18:27 +08:00
|
|
|
// Avoid processing the same info twice.
|
2017-02-19 07:06:50 +08:00
|
|
|
const PredicateBase *LastPredInfo = nullptr;
|
|
|
|
// See if we know something about the comparison itself, like it is the target
|
|
|
|
// of an assume.
|
|
|
|
auto *CmpPI = PredInfo->getPredicateInfoFor(I);
|
|
|
|
if (dyn_cast_or_null<PredicateAssume>(CmpPI))
|
|
|
|
return createConstantExpression(ConstantInt::getTrue(CI->getType()));
|
|
|
|
|
2017-02-01 06:31:58 +08:00
|
|
|
if (Op0 == Op1) {
|
2017-02-19 07:06:50 +08:00
|
|
|
// This condition does not depend on predicates, no need to add users
|
2017-02-01 06:31:58 +08:00
|
|
|
if (CI->isTrueWhenEqual())
|
|
|
|
return createConstantExpression(ConstantInt::getTrue(CI->getType()));
|
|
|
|
else if (CI->isFalseWhenEqual())
|
|
|
|
return createConstantExpression(ConstantInt::getFalse(CI->getType()));
|
|
|
|
}
|
2017-02-19 07:06:50 +08:00
|
|
|
|
|
|
|
// NOTE: Because we are comparing both operands here and below, and using
|
|
|
|
// previous comparisons, we rely on fact that predicateinfo knows to mark
|
|
|
|
// comparisons that use renamed operands as users of the earlier comparisons.
|
|
|
|
// It is *not* enough to just mark predicateinfo renamed operands as users of
|
|
|
|
// the earlier comparisons, because the *other* operand may have changed in a
|
|
|
|
// previous iteration.
|
|
|
|
// Example:
|
|
|
|
// icmp slt %a, %b
|
|
|
|
// %b.0 = ssa.copy(%b)
|
|
|
|
// false branch:
|
|
|
|
// icmp slt %c, %b.0
|
|
|
|
|
|
|
|
// %c and %a may start out equal, and thus, the code below will say the second
|
|
|
|
// %icmp is false. c may become equal to something else, and in that case the
|
|
|
|
// %second icmp *must* be reexamined, but would not if only the renamed
|
|
|
|
// %operands are considered users of the icmp.
|
|
|
|
|
|
|
|
// *Currently* we only check one level of comparisons back, and only mark one
|
2017-08-03 23:18:27 +08:00
|
|
|
// level back as touched when changes happen. If you modify this code to look
|
2017-02-19 07:06:50 +08:00
|
|
|
// back farther through comparisons, you *must* mark the appropriate
|
|
|
|
// comparisons as users in PredicateInfo.cpp, or you will cause bugs. See if
|
|
|
|
// we know something just from the operands themselves
|
|
|
|
|
|
|
|
// See if our operands have predicate info, so that we may be able to derive
|
|
|
|
// something from a previous comparison.
|
|
|
|
for (const auto &Op : CI->operands()) {
|
|
|
|
auto *PI = PredInfo->getPredicateInfoFor(Op);
|
|
|
|
if (const auto *PBranch = dyn_cast_or_null<PredicateBranch>(PI)) {
|
|
|
|
if (PI == LastPredInfo)
|
|
|
|
continue;
|
|
|
|
LastPredInfo = PI;
|
2017-09-02 03:20:18 +08:00
|
|
|
// In phi of ops cases, we may have predicate info that we are evaluating
|
|
|
|
// in a different context.
|
|
|
|
if (!DT->dominates(PBranch->To, getBlockForValue(I)))
|
|
|
|
continue;
|
|
|
|
// TODO: Along the false edge, we may know more things too, like
|
|
|
|
// icmp of
|
2017-02-19 07:06:50 +08:00
|
|
|
// same operands is false.
|
2017-09-02 03:20:18 +08:00
|
|
|
// TODO: We only handle actual comparison conditions below, not
|
|
|
|
// and/or.
|
2017-02-19 07:06:50 +08:00
|
|
|
auto *BranchCond = dyn_cast<CmpInst>(PBranch->Condition);
|
|
|
|
if (!BranchCond)
|
|
|
|
continue;
|
|
|
|
auto *BranchOp0 = lookupOperandLeader(BranchCond->getOperand(0));
|
|
|
|
auto *BranchOp1 = lookupOperandLeader(BranchCond->getOperand(1));
|
|
|
|
auto BranchPredicate = BranchCond->getPredicate();
|
2017-03-04 08:44:43 +08:00
|
|
|
if (shouldSwapOperands(BranchOp0, BranchOp1)) {
|
2017-02-19 07:06:50 +08:00
|
|
|
std::swap(BranchOp0, BranchOp1);
|
|
|
|
BranchPredicate = BranchCond->getSwappedPredicate();
|
|
|
|
}
|
|
|
|
if (BranchOp0 == Op0 && BranchOp1 == Op1) {
|
|
|
|
if (PBranch->TrueEdge) {
|
|
|
|
// If we know the previous predicate is true and we are in the true
|
|
|
|
// edge then we may be implied true or false.
|
2017-05-02 06:26:28 +08:00
|
|
|
if (CmpInst::isImpliedTrueByMatchingCmp(BranchPredicate,
|
|
|
|
OurPredicate)) {
|
2017-02-19 07:06:50 +08:00
|
|
|
addPredicateUsers(PI, I);
|
|
|
|
return createConstantExpression(
|
|
|
|
ConstantInt::getTrue(CI->getType()));
|
|
|
|
}
|
|
|
|
|
2017-05-02 06:26:28 +08:00
|
|
|
if (CmpInst::isImpliedFalseByMatchingCmp(BranchPredicate,
|
|
|
|
OurPredicate)) {
|
2017-02-19 07:06:50 +08:00
|
|
|
addPredicateUsers(PI, I);
|
|
|
|
return createConstantExpression(
|
|
|
|
ConstantInt::getFalse(CI->getType()));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Just handle the ne and eq cases, where if we have the same
|
|
|
|
// operands, we may know something.
|
|
|
|
if (BranchPredicate == OurPredicate) {
|
|
|
|
addPredicateUsers(PI, I);
|
|
|
|
// Same predicate, same ops,we know it was false, so this is false.
|
|
|
|
return createConstantExpression(
|
|
|
|
ConstantInt::getFalse(CI->getType()));
|
|
|
|
} else if (BranchPredicate ==
|
|
|
|
CmpInst::getInversePredicate(OurPredicate)) {
|
|
|
|
addPredicateUsers(PI, I);
|
|
|
|
// Inverse predicate, we know the other was false, so this is true.
|
|
|
|
return createConstantExpression(
|
|
|
|
ConstantInt::getTrue(CI->getType()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Create expression will take care of simplifyCmpInst
|
2017-02-01 06:32:03 +08:00
|
|
|
return createExpression(I);
|
2017-02-01 06:31:58 +08:00
|
|
|
}
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Substitute and symbolize the value before value numbering.
|
2017-05-20 03:01:27 +08:00
|
|
|
const Expression *
|
|
|
|
NewGVN::performSymbolicEvaluation(Value *V,
|
|
|
|
SmallPtrSetImpl<Value *> &Visited) const {
|
2016-12-28 22:00:11 +08:00
|
|
|
const Expression *E = nullptr;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (auto *C = dyn_cast<Constant>(V))
|
|
|
|
E = createConstantExpression(C);
|
|
|
|
else if (isa<Argument>(V) || isa<GlobalVariable>(V)) {
|
|
|
|
E = createVariableExpression(V);
|
|
|
|
} else {
|
|
|
|
// TODO: memory intrinsics.
|
|
|
|
// TODO: Some day, we should do the forward propagation and reassociation
|
|
|
|
// parts of the algorithm.
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *I = cast<Instruction>(V);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
switch (I->getOpcode()) {
|
|
|
|
case Instruction::ExtractValue:
|
|
|
|
case Instruction::InsertValue:
|
2017-02-01 06:32:03 +08:00
|
|
|
E = performSymbolicAggrValueEvaluation(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
break;
|
2017-10-01 07:51:54 +08:00
|
|
|
case Instruction::PHI: {
|
|
|
|
SmallVector<ValPair, 3> Ops;
|
|
|
|
auto *PN = cast<PHINode>(I);
|
|
|
|
for (unsigned i = 0; i < PN->getNumOperands(); ++i)
|
|
|
|
Ops.push_back({PN->getIncomingValue(i), PN->getIncomingBlock(i)});
|
|
|
|
// Sort to ensure the invariant createPHIExpression requires is met.
|
|
|
|
sortPHIOps(Ops);
|
|
|
|
E = performSymbolicPHIEvaluation(Ops, I, getBlockForValue(I));
|
|
|
|
} break;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
case Instruction::Call:
|
2017-02-01 06:32:03 +08:00
|
|
|
E = performSymbolicCallEvaluation(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
break;
|
|
|
|
case Instruction::Store:
|
2017-02-01 06:32:03 +08:00
|
|
|
E = performSymbolicStoreEvaluation(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
break;
|
|
|
|
case Instruction::Load:
|
2017-02-01 06:32:03 +08:00
|
|
|
E = performSymbolicLoadEvaluation(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
break;
|
2018-07-31 03:41:25 +08:00
|
|
|
case Instruction::BitCast:
|
2017-02-01 06:32:03 +08:00
|
|
|
E = createExpression(I);
|
2017-10-21 05:47:29 +08:00
|
|
|
break;
|
2017-02-01 06:31:58 +08:00
|
|
|
case Instruction::ICmp:
|
2017-10-21 05:47:29 +08:00
|
|
|
case Instruction::FCmp:
|
2017-02-01 06:32:03 +08:00
|
|
|
E = performSymbolicCmpEvaluation(I);
|
2017-10-21 05:47:29 +08:00
|
|
|
break;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
case Instruction::Add:
|
|
|
|
case Instruction::FAdd:
|
|
|
|
case Instruction::Sub:
|
|
|
|
case Instruction::FSub:
|
|
|
|
case Instruction::Mul:
|
|
|
|
case Instruction::FMul:
|
|
|
|
case Instruction::UDiv:
|
|
|
|
case Instruction::SDiv:
|
|
|
|
case Instruction::FDiv:
|
|
|
|
case Instruction::URem:
|
|
|
|
case Instruction::SRem:
|
|
|
|
case Instruction::FRem:
|
|
|
|
case Instruction::Shl:
|
|
|
|
case Instruction::LShr:
|
|
|
|
case Instruction::AShr:
|
|
|
|
case Instruction::And:
|
|
|
|
case Instruction::Or:
|
|
|
|
case Instruction::Xor:
|
|
|
|
case Instruction::Trunc:
|
|
|
|
case Instruction::ZExt:
|
|
|
|
case Instruction::SExt:
|
|
|
|
case Instruction::FPToUI:
|
|
|
|
case Instruction::FPToSI:
|
|
|
|
case Instruction::UIToFP:
|
|
|
|
case Instruction::SIToFP:
|
|
|
|
case Instruction::FPTrunc:
|
|
|
|
case Instruction::FPExt:
|
|
|
|
case Instruction::PtrToInt:
|
|
|
|
case Instruction::IntToPtr:
|
|
|
|
case Instruction::Select:
|
|
|
|
case Instruction::ExtractElement:
|
|
|
|
case Instruction::InsertElement:
|
|
|
|
case Instruction::ShuffleVector:
|
|
|
|
case Instruction::GetElementPtr:
|
2017-02-01 06:32:03 +08:00
|
|
|
E = createExpression(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
2017-05-22 07:41:56 +08:00
|
|
|
// Look up a container in a map, and then call a function for each thing in the
|
|
|
|
// found container.
|
|
|
|
template <typename Map, typename KeyType, typename Func>
|
|
|
|
void NewGVN::for_each_found(Map &M, const KeyType &Key, Func F) {
|
|
|
|
const auto Result = M.find_as(Key);
|
|
|
|
if (Result != M.end())
|
|
|
|
for (typename Map::mapped_type::value_type Mapped : Result->second)
|
|
|
|
F(Mapped);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look up a container of values/instructions in a map, and touch all the
|
|
|
|
// instructions in the container. Then erase value from the map.
|
|
|
|
template <typename Map, typename KeyType>
|
|
|
|
void NewGVN::touchAndErase(Map &M, const KeyType &Key) {
|
|
|
|
const auto Result = M.find_as(Key);
|
|
|
|
if (Result != M.end()) {
|
|
|
|
for (const typename Map::mapped_type::value_type Mapped : Result->second)
|
|
|
|
TouchedInstructions.set(InstrToDFSNum(Mapped));
|
|
|
|
M.erase(Result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
void NewGVN::addAdditionalUsers(Value *To, Value *User) const {
|
2017-09-05 10:17:42 +08:00
|
|
|
assert(User && To != User);
|
2017-05-31 09:47:32 +08:00
|
|
|
if (isa<Instruction>(To))
|
|
|
|
AdditionalUsers[To].insert(User);
|
2017-05-20 03:01:27 +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
|
|
|
void NewGVN::markUsersTouched(Value *V) {
|
|
|
|
// Now mark the users as touched.
|
2016-12-30 06:15:12 +08:00
|
|
|
for (auto *User : V->users()) {
|
|
|
|
assert(isa<Instruction>(User) && "Use of value not within an instruction?");
|
2017-04-07 02:52:58 +08:00
|
|
|
TouchedInstructions.set(InstrToDFSNum(User));
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
2017-05-22 07:41:56 +08:00
|
|
|
touchAndErase(AdditionalUsers, 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
|
|
|
}
|
|
|
|
|
2017-05-10 00:40:04 +08:00
|
|
|
void NewGVN::addMemoryUsers(const MemoryAccess *To, MemoryAccess *U) const {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Adding memory user " << *U << " to " << *To << "\n");
|
2017-04-07 02:52:50 +08:00
|
|
|
MemoryToUsers[To].insert(U);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NewGVN::markMemoryDefTouched(const MemoryAccess *MA) {
|
2017-04-07 02:52:58 +08:00
|
|
|
TouchedInstructions.set(MemoryToDFSNum(MA));
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void NewGVN::markMemoryUsersTouched(const MemoryAccess *MA) {
|
|
|
|
if (isa<MemoryUse>(MA))
|
|
|
|
return;
|
|
|
|
for (auto U : MA->users())
|
2017-04-07 02:52:58 +08:00
|
|
|
TouchedInstructions.set(MemoryToDFSNum(U));
|
2017-05-22 07:41:56 +08:00
|
|
|
touchAndErase(MemoryToUsers, MA);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
2017-02-19 07:06:50 +08:00
|
|
|
// Add I to the set of users of a given predicate.
|
2017-05-10 00:40:04 +08:00
|
|
|
void NewGVN::addPredicateUsers(const PredicateBase *PB, Instruction *I) const {
|
2017-05-20 03:01:27 +08:00
|
|
|
// Don't add temporary instructions to the user lists.
|
|
|
|
if (AllTempInstructions.count(I))
|
|
|
|
return;
|
|
|
|
|
2017-02-19 07:06:50 +08:00
|
|
|
if (auto *PBranch = dyn_cast<PredicateBranch>(PB))
|
|
|
|
PredicateToUsers[PBranch->Condition].insert(I);
|
|
|
|
else if (auto *PAssume = dyn_cast<PredicateBranch>(PB))
|
|
|
|
PredicateToUsers[PAssume->Condition].insert(I);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Touch all the predicates that depend on this instruction.
|
|
|
|
void NewGVN::markPredicateUsersTouched(Instruction *I) {
|
2017-05-22 07:41:56 +08:00
|
|
|
touchAndErase(PredicateToUsers, I);
|
2017-02-19 07:06:50 +08:00
|
|
|
}
|
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
// Mark users affected by a memory leader change.
|
|
|
|
void NewGVN::markMemoryLeaderChangeTouched(CongruenceClass *CC) {
|
2017-04-08 02:38:09 +08:00
|
|
|
for (auto M : CC->memory())
|
2017-04-07 02:52:50 +08:00
|
|
|
markMemoryDefTouched(M);
|
|
|
|
}
|
|
|
|
|
2017-01-08 00:55:14 +08:00
|
|
|
// Touch the instructions that need to be updated after a congruence class has a
|
|
|
|
// leader change, and mark changed values.
|
2017-04-07 02:52:50 +08:00
|
|
|
void NewGVN::markValueLeaderChangeTouched(CongruenceClass *CC) {
|
2017-04-08 02:38:09 +08:00
|
|
|
for (auto M : *CC) {
|
2017-01-08 00:55:14 +08:00
|
|
|
if (auto *I = dyn_cast<Instruction>(M))
|
2017-04-07 02:52:58 +08:00
|
|
|
TouchedInstructions.set(InstrToDFSNum(I));
|
2017-01-12 04:22:05 +08:00
|
|
|
LeaderChanges.insert(M);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
// Give a range of things that have instruction DFS numbers, this will return
|
|
|
|
// the member of the range with the smallest dfs number.
|
|
|
|
template <class T, class Range>
|
|
|
|
T *NewGVN::getMinDFSOfRange(const Range &R) const {
|
|
|
|
std::pair<T *, unsigned> MinDFS = {nullptr, ~0U};
|
|
|
|
for (const auto X : R) {
|
2017-04-07 02:52:58 +08:00
|
|
|
auto DFSNum = InstrToDFSNum(X);
|
2017-04-07 02:52:50 +08:00
|
|
|
if (DFSNum < MinDFS.second)
|
|
|
|
MinDFS = {X, DFSNum};
|
|
|
|
}
|
|
|
|
return MinDFS.first;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This function returns the MemoryAccess that should be the next leader of
|
|
|
|
// congruence class CC, under the assumption that the current leader is going to
|
|
|
|
// disappear.
|
|
|
|
const MemoryAccess *NewGVN::getNextMemoryLeader(CongruenceClass *CC) const {
|
|
|
|
// TODO: If this ends up to slow, we can maintain a next memory leader like we
|
|
|
|
// do for regular leaders.
|
2017-08-26 15:37:11 +08:00
|
|
|
// Make sure there will be a leader to find.
|
2017-05-11 03:57:43 +08:00
|
|
|
assert(!CC->definesNoMemory() && "Can't get next leader if there is none");
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC->getStoreCount() > 0) {
|
|
|
|
if (auto *NL = dyn_cast_or_null<StoreInst>(CC->getNextLeader().first))
|
2017-05-20 03:01:27 +08:00
|
|
|
return getMemoryAccess(NL);
|
2017-04-07 02:52:50 +08:00
|
|
|
// Find the store with the minimum DFS number.
|
|
|
|
auto *V = getMinDFSOfRange<Value>(make_filter_range(
|
2017-04-08 02:38:09 +08:00
|
|
|
*CC, [&](const Value *V) { return isa<StoreInst>(V); }));
|
2017-05-20 03:01:27 +08:00
|
|
|
return getMemoryAccess(cast<StoreInst>(V));
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
2017-04-08 02:38:09 +08:00
|
|
|
assert(CC->getStoreCount() == 0);
|
2017-04-07 02:52:50 +08:00
|
|
|
|
|
|
|
// Given our assertion, hitting this part must mean
|
2017-04-08 02:38:09 +08:00
|
|
|
// !OldClass->memory_empty()
|
|
|
|
if (CC->memory_size() == 1)
|
|
|
|
return *CC->memory_begin();
|
|
|
|
return getMinDFSOfRange<const MemoryPhi>(CC->memory());
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// This function returns the next value leader of a congruence class, under the
|
|
|
|
// assumption that the current leader is going away. This should end up being
|
|
|
|
// the next most dominating member.
|
|
|
|
Value *NewGVN::getNextValueLeader(CongruenceClass *CC) const {
|
|
|
|
// We don't need to sort members if there is only 1, and we don't care about
|
|
|
|
// sorting the TOP class because everything either gets out of it or is
|
|
|
|
// unreachable.
|
|
|
|
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC->size() == 1 || CC == TOPClass) {
|
|
|
|
return *(CC->begin());
|
|
|
|
} else if (CC->getNextLeader().first) {
|
2017-04-07 02:52:50 +08:00
|
|
|
++NumGVNAvoidedSortedLeaderChanges;
|
2017-04-08 02:38:09 +08:00
|
|
|
return CC->getNextLeader().first;
|
2017-04-07 02:52:50 +08:00
|
|
|
} else {
|
|
|
|
++NumGVNSortedLeaderChanges;
|
|
|
|
// NOTE: If this ends up to slow, we can maintain a dual structure for
|
|
|
|
// member testing/insertion, or keep things mostly sorted, and sort only
|
|
|
|
// here, or use SparseBitVector or ....
|
2017-04-08 02:38:09 +08:00
|
|
|
return getMinDFSOfRange<Value>(*CC);
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move a MemoryAccess, currently in OldClass, to NewClass, including updates to
|
|
|
|
// the memory members, etc for the move.
|
|
|
|
//
|
|
|
|
// The invariants of this function are:
|
|
|
|
//
|
2017-07-12 03:15:36 +08:00
|
|
|
// - I must be moving to NewClass from OldClass
|
|
|
|
// - The StoreCount of OldClass and NewClass is expected to have been updated
|
2018-04-09 12:37:53 +08:00
|
|
|
// for I already if it is a store.
|
2017-07-12 03:15:36 +08:00
|
|
|
// - The OldClass memory leader has not been updated yet if I was the leader.
|
2017-04-07 02:52:50 +08:00
|
|
|
void NewGVN::moveMemoryToNewCongruenceClass(Instruction *I,
|
|
|
|
MemoryAccess *InstMA,
|
|
|
|
CongruenceClass *OldClass,
|
|
|
|
CongruenceClass *NewClass) {
|
2018-06-14 13:41:49 +08:00
|
|
|
// If the leader is I, and we had a representative MemoryAccess, it should
|
2017-04-07 02:52:50 +08:00
|
|
|
// be the MemoryAccess of OldClass.
|
2017-04-11 07:08:35 +08:00
|
|
|
assert((!InstMA || !OldClass->getMemoryLeader() ||
|
|
|
|
OldClass->getLeader() != I ||
|
2017-07-12 03:49:12 +08:00
|
|
|
MemoryAccessToClass.lookup(OldClass->getMemoryLeader()) ==
|
|
|
|
MemoryAccessToClass.lookup(InstMA)) &&
|
2017-04-11 07:08:35 +08:00
|
|
|
"Representative MemoryAccess mismatch");
|
2017-04-07 02:52:50 +08:00
|
|
|
// First, see what happens to the new class
|
2017-04-08 02:38:09 +08:00
|
|
|
if (!NewClass->getMemoryLeader()) {
|
2017-04-07 02:52:50 +08:00
|
|
|
// Should be a new class, or a store becoming a leader of a new class.
|
2017-04-08 02:38:09 +08:00
|
|
|
assert(NewClass->size() == 1 ||
|
|
|
|
(isa<StoreInst>(I) && NewClass->getStoreCount() == 1));
|
|
|
|
NewClass->setMemoryLeader(InstMA);
|
2017-04-07 02:52:50 +08:00
|
|
|
// Mark it touched if we didn't just create a singleton
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Memory class leader change for class "
|
|
|
|
<< NewClass->getID()
|
|
|
|
<< " due to new memory instruction becoming leader\n");
|
2017-04-07 02:52:50 +08:00
|
|
|
markMemoryLeaderChangeTouched(NewClass);
|
|
|
|
}
|
|
|
|
setMemoryClass(InstMA, NewClass);
|
|
|
|
// Now, fixup the old class if necessary
|
2017-04-08 02:38:09 +08:00
|
|
|
if (OldClass->getMemoryLeader() == InstMA) {
|
2017-05-11 03:57:43 +08:00
|
|
|
if (!OldClass->definesNoMemory()) {
|
2017-04-08 02:38:09 +08:00
|
|
|
OldClass->setMemoryLeader(getNextMemoryLeader(OldClass));
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Memory class leader change for class "
|
|
|
|
<< OldClass->getID() << " to "
|
|
|
|
<< *OldClass->getMemoryLeader()
|
|
|
|
<< " due to removal of old leader " << *InstMA << "\n");
|
2017-04-07 02:52:50 +08:00
|
|
|
markMemoryLeaderChangeTouched(OldClass);
|
|
|
|
} else
|
2017-04-08 02:38:09 +08:00
|
|
|
OldClass->setMemoryLeader(nullptr);
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-12 04:22:05 +08:00
|
|
|
// Move a value, currently in OldClass, to be part of NewClass
|
2017-04-07 02:52:50 +08:00
|
|
|
// Update OldClass and NewClass for the move (including changing leaders, etc).
|
|
|
|
void NewGVN::moveValueToNewCongruenceClass(Instruction *I, const Expression *E,
|
2017-01-14 06:40:01 +08:00
|
|
|
CongruenceClass *OldClass,
|
2017-01-12 04:22:05 +08:00
|
|
|
CongruenceClass *NewClass) {
|
2017-04-08 02:38:09 +08:00
|
|
|
if (I == OldClass->getNextLeader().first)
|
|
|
|
OldClass->resetNextLeader();
|
2017-01-14 06:40:01 +08:00
|
|
|
|
2017-05-20 03:01:24 +08:00
|
|
|
OldClass->erase(I);
|
|
|
|
NewClass->insert(I);
|
2017-01-14 06:40:01 +08:00
|
|
|
|
2017-04-08 02:38:09 +08:00
|
|
|
if (NewClass->getLeader() != I)
|
|
|
|
NewClass->addPossibleNextLeader({I, InstrToDFSNum(I)});
|
2017-04-07 02:52:50 +08:00
|
|
|
// Handle our special casing of stores.
|
2017-01-27 06:21:48 +08:00
|
|
|
if (auto *SI = dyn_cast<StoreInst>(I)) {
|
2017-04-08 02:38:09 +08:00
|
|
|
OldClass->decStoreCount();
|
|
|
|
// Okay, so when do we want to make a store a leader of a class?
|
|
|
|
// If we have a store defined by an earlier load, we want the earlier load
|
|
|
|
// to lead the class.
|
|
|
|
// If we have a store defined by something else, we want the store to lead
|
|
|
|
// the class so everything else gets the "something else" as a value.
|
2017-04-07 02:52:50 +08:00
|
|
|
// If we have a store as the single member of the class, we want the store
|
2017-04-08 02:38:09 +08:00
|
|
|
// as the leader
|
|
|
|
if (NewClass->getStoreCount() == 0 && !NewClass->getStoredValue()) {
|
2017-04-07 02:52:50 +08:00
|
|
|
// If it's a store expression we are using, it means we are not equivalent
|
|
|
|
// to something earlier.
|
2017-05-16 14:06:15 +08:00
|
|
|
if (auto *SE = dyn_cast<StoreExpression>(E)) {
|
|
|
|
NewClass->setStoredValue(SE->getStoredValue());
|
2017-04-07 02:52:50 +08:00
|
|
|
markValueLeaderChangeTouched(NewClass);
|
|
|
|
// Shift the new class leader to be the store
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Changing leader of congruence class "
|
|
|
|
<< NewClass->getID() << " from "
|
|
|
|
<< *NewClass->getLeader() << " to " << *SI
|
|
|
|
<< " because store joined class\n");
|
2017-04-07 02:52:50 +08:00
|
|
|
// If we changed the leader, we have to mark it changed because we don't
|
2017-07-12 03:19:45 +08:00
|
|
|
// know what it will do to symbolic evaluation.
|
2017-04-08 02:38:09 +08:00
|
|
|
NewClass->setLeader(SI);
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
|
|
|
// We rely on the code below handling the MemoryAccess change.
|
|
|
|
}
|
2017-04-08 02:38:09 +08:00
|
|
|
NewClass->incStoreCount();
|
2017-01-12 04:22:05 +08:00
|
|
|
}
|
2017-04-07 02:52:50 +08:00
|
|
|
// True if there is no memory instructions left in a class that had memory
|
|
|
|
// instructions before.
|
2017-01-12 04:22:05 +08:00
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
// If it's not a memory use, set the MemoryAccess equivalence
|
2017-05-20 03:01:27 +08:00
|
|
|
auto *InstMA = dyn_cast_or_null<MemoryDef>(getMemoryAccess(I));
|
2017-04-07 02:52:50 +08:00
|
|
|
if (InstMA)
|
|
|
|
moveMemoryToNewCongruenceClass(I, InstMA, OldClass, NewClass);
|
2017-01-14 06:40:01 +08:00
|
|
|
ValueToClass[I] = NewClass;
|
2017-01-12 04:22:05 +08:00
|
|
|
// See if we destroyed the class or need to swap leaders.
|
2017-04-08 02:38:09 +08:00
|
|
|
if (OldClass->empty() && OldClass != TOPClass) {
|
|
|
|
if (OldClass->getDefiningExpr()) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Erasing expression " << *OldClass->getDefiningExpr()
|
|
|
|
<< " from table\n");
|
2017-06-07 01:15:28 +08:00
|
|
|
// We erase it as an exact expression to make sure we don't just erase an
|
|
|
|
// equivalent one.
|
|
|
|
auto Iter = ExpressionToClass.find_as(
|
|
|
|
ExactEqualsExpression(*OldClass->getDefiningExpr()));
|
|
|
|
if (Iter != ExpressionToClass.end())
|
|
|
|
ExpressionToClass.erase(Iter);
|
|
|
|
#ifdef EXPENSIVE_CHECKS
|
|
|
|
assert(
|
|
|
|
(*OldClass->getDefiningExpr() != *E || ExpressionToClass.lookup(E)) &&
|
|
|
|
"We erased the expression we just inserted, which should not happen");
|
|
|
|
#endif
|
2017-01-12 04:22:05 +08:00
|
|
|
}
|
2017-04-08 02:38:09 +08:00
|
|
|
} else if (OldClass->getLeader() == I) {
|
2017-01-12 04:22:05 +08:00
|
|
|
// When the leader changes, the value numbering of
|
|
|
|
// everything may change due to symbolization changes, so we need to
|
|
|
|
// reprocess.
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Value class leader change for class "
|
|
|
|
<< OldClass->getID() << "\n");
|
2017-01-14 06:40:01 +08:00
|
|
|
++NumGVNLeaderChanges;
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
// Destroy the stored value if there are no more stores to represent it.
|
2017-04-07 02:52:50 +08:00
|
|
|
// Note that this is basically clean up for the expression removal that
|
|
|
|
// happens below. If we remove stores from a class, we may leave it as a
|
|
|
|
// class of equivalent memory phis.
|
2017-04-08 02:38:09 +08:00
|
|
|
if (OldClass->getStoreCount() == 0) {
|
|
|
|
if (OldClass->getStoredValue())
|
|
|
|
OldClass->setStoredValue(nullptr);
|
2017-01-27 06:21:48 +08:00
|
|
|
}
|
2017-04-08 02:38:09 +08:00
|
|
|
OldClass->setLeader(getNextValueLeader(OldClass));
|
|
|
|
OldClass->resetNextLeader();
|
2017-04-07 02:52:50 +08:00
|
|
|
markValueLeaderChangeTouched(OldClass);
|
2017-01-08 00:55:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
// For a given expression, mark the phi of ops instructions that could have
|
|
|
|
// changed as a result.
|
2017-05-30 14:58:18 +08:00
|
|
|
void NewGVN::markPhiOfOpsChanged(const Expression *E) {
|
2017-10-01 07:51:55 +08:00
|
|
|
touchAndErase(ExpressionToPhiOfOps, E);
|
2017-05-20 03:01:27 +08:00
|
|
|
}
|
2017-05-22 07:41:56 +08:00
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Perform congruence finding on a given value numbering expression.
|
2017-01-14 06:40:01 +08:00
|
|
|
void NewGVN::performCongruenceFinding(Instruction *I, const Expression *E) {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// This is guaranteed to return something, since it will at least find
|
2017-02-11 20:48:50 +08:00
|
|
|
// TOP.
|
2017-05-20 04:22:20 +08:00
|
|
|
|
|
|
|
CongruenceClass *IClass = ValueToClass.lookup(I);
|
2017-01-14 06:40:01 +08:00
|
|
|
assert(IClass && "Should have found a IClass");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Dead classes should have been eliminated from the mapping.
|
2017-04-07 02:52:50 +08:00
|
|
|
assert(!IClass->isDead() && "Found a dead class");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
CongruenceClass *EClass = nullptr;
|
2017-01-03 02:00:53 +08:00
|
|
|
if (const auto *VE = dyn_cast<VariableExpression>(E)) {
|
2017-05-20 03:01:27 +08:00
|
|
|
EClass = ValueToClass.lookup(VE->getVariableValue());
|
2017-05-20 04:22:20 +08:00
|
|
|
} else if (isa<DeadExpression>(E)) {
|
|
|
|
EClass = TOPClass;
|
|
|
|
}
|
|
|
|
if (!EClass) {
|
2017-05-30 14:58:18 +08:00
|
|
|
auto lookupResult = ExpressionToClass.insert({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 it's not in the value table, create a new congruence class.
|
|
|
|
if (lookupResult.second) {
|
2016-12-28 22:00:11 +08:00
|
|
|
CongruenceClass *NewClass = createCongruenceClass(nullptr, E);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
auto place = lookupResult.first;
|
|
|
|
place->second = NewClass;
|
|
|
|
|
|
|
|
// Constants and variables should always be made the leader.
|
2017-01-08 00:55:14 +08:00
|
|
|
if (const auto *CE = dyn_cast<ConstantExpression>(E)) {
|
2017-04-08 02:38:09 +08:00
|
|
|
NewClass->setLeader(CE->getConstantValue());
|
2017-01-08 00:55:14 +08:00
|
|
|
} else if (const auto *SE = dyn_cast<StoreExpression>(E)) {
|
|
|
|
StoreInst *SI = SE->getStoreInst();
|
2017-04-08 02:38:09 +08:00
|
|
|
NewClass->setLeader(SI);
|
2017-05-16 14:06:15 +08:00
|
|
|
NewClass->setStoredValue(SE->getStoredValue());
|
2017-01-27 06:21:48 +08:00
|
|
|
// The RepMemoryAccess field will be filled in properly by the
|
|
|
|
// moveValueToNewCongruenceClass call.
|
2017-01-08 00:55:14 +08:00
|
|
|
} else {
|
2017-04-08 02:38:09 +08:00
|
|
|
NewClass->setLeader(I);
|
2017-01-08 00:55:14 +08:00
|
|
|
}
|
|
|
|
assert(!isa<VariableExpression>(E) &&
|
|
|
|
"VariableExpression should have been handled already");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
EClass = NewClass;
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Created new congruence class for " << *I
|
|
|
|
<< " using expression " << *E << " at "
|
|
|
|
<< NewClass->getID() << " and leader "
|
|
|
|
<< *(NewClass->getLeader()));
|
2017-04-08 02:38:09 +08:00
|
|
|
if (NewClass->getStoredValue())
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << " and stored value "
|
|
|
|
<< *(NewClass->getStoredValue()));
|
|
|
|
LLVM_DEBUG(dbgs() << "\n");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
} else {
|
|
|
|
EClass = lookupResult.first->second;
|
2017-01-03 02:00:46 +08:00
|
|
|
if (isa<ConstantExpression>(E))
|
2017-04-11 07:08:35 +08:00
|
|
|
assert((isa<Constant>(EClass->getLeader()) ||
|
|
|
|
(EClass->getStoredValue() &&
|
|
|
|
isa<Constant>(EClass->getStoredValue()))) &&
|
|
|
|
"Any class with a constant expression should have a "
|
|
|
|
"constant leader");
|
2017-01-03 02:00:46 +08:00
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
assert(EClass && "Somehow don't have an eclass");
|
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
assert(!EClass->isDead() && "We accidentally looked up a dead class");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
2017-01-14 06:40:01 +08:00
|
|
|
bool ClassChanged = IClass != EClass;
|
|
|
|
bool LeaderChanged = LeaderChanges.erase(I);
|
2017-01-12 04:22:05 +08:00
|
|
|
if (ClassChanged || LeaderChanged) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "New class " << EClass->getID() << " for expression "
|
|
|
|
<< *E << "\n");
|
2017-05-20 03:01:27 +08:00
|
|
|
if (ClassChanged) {
|
2017-04-07 02:52:50 +08:00
|
|
|
moveValueToNewCongruenceClass(I, E, IClass, EClass);
|
2017-05-30 14:58:18 +08:00
|
|
|
markPhiOfOpsChanged(E);
|
2017-05-20 03:01:27 +08:00
|
|
|
}
|
|
|
|
|
2017-01-14 06:40:01 +08:00
|
|
|
markUsersTouched(I);
|
2017-05-20 03:01:27 +08:00
|
|
|
if (MemoryAccess *MA = getMemoryAccess(I))
|
2017-01-14 06:40:01 +08:00
|
|
|
markMemoryUsersTouched(MA);
|
2017-02-19 07:06:50 +08:00
|
|
|
if (auto *CI = dyn_cast<CmpInst>(I))
|
|
|
|
markPredicateUsersTouched(CI);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
2017-05-17 03:58:47 +08:00
|
|
|
// If we changed the class of the store, we want to ensure nothing finds the
|
|
|
|
// old store expression. In particular, loads do not compare against stored
|
|
|
|
// value, so they will find old store expressions (and associated class
|
|
|
|
// mappings) if we leave them in the table.
|
2017-05-19 12:06:10 +08:00
|
|
|
if (ClassChanged && isa<StoreInst>(I)) {
|
2017-05-17 03:58:47 +08:00
|
|
|
auto *OldE = ValueToExpression.lookup(I);
|
|
|
|
// It could just be that the old class died. We don't want to erase it if we
|
|
|
|
// just moved classes.
|
2017-06-07 01:15:28 +08:00
|
|
|
if (OldE && isa<StoreExpression>(OldE) && *E != *OldE) {
|
|
|
|
// Erase this as an exact expression to ensure we don't erase expressions
|
|
|
|
// equivalent to it.
|
|
|
|
auto Iter = ExpressionToClass.find_as(ExactEqualsExpression(*OldE));
|
|
|
|
if (Iter != ExpressionToClass.end())
|
|
|
|
ExpressionToClass.erase(Iter);
|
|
|
|
}
|
2017-05-17 03:58:47 +08:00
|
|
|
}
|
|
|
|
ValueToExpression[I] = E;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Process the fact that Edge (from, to) is reachable, including marking
|
|
|
|
// any newly reachable blocks and instructions for processing.
|
|
|
|
void NewGVN::updateReachableEdge(BasicBlock *From, BasicBlock *To) {
|
|
|
|
// Check if the Edge was reachable before.
|
|
|
|
if (ReachableEdges.insert({From, To}).second) {
|
|
|
|
// If this block wasn't reachable before, all instructions are touched.
|
|
|
|
if (ReachableBlocks.insert(To).second) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Block " << getBlockName(To)
|
|
|
|
<< " marked reachable\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
|
|
|
const auto &InstRange = BlockInstRange.lookup(To);
|
|
|
|
TouchedInstructions.set(InstRange.first, InstRange.second);
|
|
|
|
} else {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Block " << getBlockName(To)
|
|
|
|
<< " was reachable, but new edge {"
|
|
|
|
<< getBlockName(From) << "," << getBlockName(To)
|
|
|
|
<< "} to it found\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
|
|
|
|
|
|
|
// 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-05-20 03:01:27 +08:00
|
|
|
if (MemoryAccess *MemPhi = getMemoryAccess(To))
|
2017-04-07 02:52:58 +08:00
|
|
|
TouchedInstructions.set(InstrToDFSNum(MemPhi));
|
2017-01-03 02:00:46 +08:00
|
|
|
|
2017-10-01 07:51:53 +08:00
|
|
|
// FIXME: We should just add a union op on a Bitvector and
|
|
|
|
// SparseBitVector. We can do it word by word faster than we are doing it
|
|
|
|
// here.
|
|
|
|
for (auto InstNum : RevisitOnReachabilityChange[To])
|
|
|
|
TouchedInstructions.set(InstNum);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Given a predicate condition (from a switch, cmp, or whatever) and a block,
|
|
|
|
// see if we know some constant value for it already.
|
2017-02-01 06:32:03 +08:00
|
|
|
Value *NewGVN::findConditionEquivalence(Value *Cond) const {
|
2017-02-01 06:31:53 +08:00
|
|
|
auto Result = lookupOperandLeader(Cond);
|
2017-06-20 00:46:15 +08:00
|
|
|
return isa<Constant>(Result) ? Result : 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
|
|
|
}
|
|
|
|
|
|
|
|
// Process the outgoing edges of a block for reachability.
|
2018-10-18 08:39:46 +08:00
|
|
|
void NewGVN::processOutgoingEdges(Instruction *TI, BasicBlock *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
|
|
|
// Evaluate reachability of terminator instruction.
|
|
|
|
BranchInst *BR;
|
|
|
|
if ((BR = dyn_cast<BranchInst>(TI)) && BR->isConditional()) {
|
|
|
|
Value *Cond = BR->getCondition();
|
2017-02-01 06:32:03 +08:00
|
|
|
Value *CondEvaluated = findConditionEquivalence(Cond);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (!CondEvaluated) {
|
|
|
|
if (auto *I = dyn_cast<Instruction>(Cond)) {
|
2017-02-01 06:32:03 +08:00
|
|
|
const Expression *E = createExpression(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (const auto *CE = dyn_cast<ConstantExpression>(E)) {
|
|
|
|
CondEvaluated = CE->getConstantValue();
|
|
|
|
}
|
|
|
|
} else if (isa<ConstantInt>(Cond)) {
|
|
|
|
CondEvaluated = Cond;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ConstantInt *CI;
|
|
|
|
BasicBlock *TrueSucc = BR->getSuccessor(0);
|
|
|
|
BasicBlock *FalseSucc = BR->getSuccessor(1);
|
|
|
|
if (CondEvaluated && (CI = dyn_cast<ConstantInt>(CondEvaluated))) {
|
|
|
|
if (CI->isOne()) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Condition for Terminator " << *TI
|
|
|
|
<< " evaluated to true\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
|
|
|
updateReachableEdge(B, TrueSucc);
|
|
|
|
} else if (CI->isZero()) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Condition for Terminator " << *TI
|
|
|
|
<< " evaluated to false\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
|
|
|
updateReachableEdge(B, FalseSucc);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
updateReachableEdge(B, TrueSucc);
|
|
|
|
updateReachableEdge(B, FalseSucc);
|
|
|
|
}
|
|
|
|
} else if (auto *SI = dyn_cast<SwitchInst>(TI)) {
|
|
|
|
// For switches, propagate the case values into the case
|
|
|
|
// destinations.
|
|
|
|
|
|
|
|
// Remember how many outgoing edges there are to every successor.
|
|
|
|
SmallDenseMap<BasicBlock *, unsigned, 16> SwitchEdges;
|
|
|
|
|
|
|
|
Value *SwitchCond = SI->getCondition();
|
2017-02-01 06:32:03 +08:00
|
|
|
Value *CondEvaluated = findConditionEquivalence(SwitchCond);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// See if we were able to turn this switch statement into a constant.
|
|
|
|
if (CondEvaluated && isa<ConstantInt>(CondEvaluated)) {
|
2016-12-29 03:17:17 +08:00
|
|
|
auto *CondVal = cast<ConstantInt>(CondEvaluated);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// We should be able to get case value for this.
|
2017-04-12 15:27:28 +08:00
|
|
|
auto Case = *SI->findCaseValue(CondVal);
|
|
|
|
if (Case.getCaseSuccessor() == SI->getDefaultDest()) {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// We proved the value is outside of the range of the case.
|
|
|
|
// We can't do anything other than mark the default dest as reachable,
|
|
|
|
// and go home.
|
|
|
|
updateReachableEdge(B, SI->getDefaultDest());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Now get where it goes and mark it reachable.
|
2017-04-12 15:27:28 +08:00
|
|
|
BasicBlock *TargetBlock = Case.getCaseSuccessor();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
updateReachableEdge(B, TargetBlock);
|
|
|
|
} else {
|
|
|
|
for (unsigned i = 0, e = SI->getNumSuccessors(); i != e; ++i) {
|
|
|
|
BasicBlock *TargetBlock = SI->getSuccessor(i);
|
|
|
|
++SwitchEdges[TargetBlock];
|
|
|
|
updateReachableEdge(B, TargetBlock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Otherwise this is either unconditional, or a type we have no
|
|
|
|
// idea about. Just mark successors as reachable.
|
|
|
|
for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) {
|
|
|
|
BasicBlock *TargetBlock = TI->getSuccessor(i);
|
|
|
|
updateReachableEdge(B, TargetBlock);
|
|
|
|
}
|
2017-01-03 02:00:46 +08:00
|
|
|
|
|
|
|
// This also may be a memory defining terminator, in which case, set it
|
2017-04-07 02:52:50 +08:00
|
|
|
// equivalent only to itself.
|
|
|
|
//
|
2017-05-20 03:01:27 +08:00
|
|
|
auto *MA = getMemoryAccess(TI);
|
2017-04-07 02:52:50 +08:00
|
|
|
if (MA && !isa<MemoryUse>(MA)) {
|
|
|
|
auto *CC = ensureLeaderOfMemoryClass(MA);
|
|
|
|
if (setMemoryClass(MA, CC))
|
|
|
|
markMemoryUsersTouched(MA);
|
|
|
|
}
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-04 05:17:49 +08:00
|
|
|
// Remove the PHI of Ops PHI for I
|
|
|
|
void NewGVN::removePhiOfOps(Instruction *I, PHINode *PHITemp) {
|
|
|
|
InstrDFS.erase(PHITemp);
|
|
|
|
// It's still a temp instruction. We keep it in the array so it gets erased.
|
2017-10-01 07:51:53 +08:00
|
|
|
// However, it's no longer used by I, or in the block
|
2017-08-04 05:17:49 +08:00
|
|
|
TempToBlock.erase(PHITemp);
|
|
|
|
RealToTemp.erase(I);
|
2017-10-01 07:51:53 +08:00
|
|
|
// We don't remove the users from the phi node uses. This wastes a little
|
|
|
|
// time, but such is life. We could use two sets to track which were there
|
|
|
|
// are the start of NewGVN, and which were added, but right nowt he cost of
|
|
|
|
// tracking is more than the cost of checking for more phi of ops.
|
2017-08-04 05:17:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add PHI Op in BB as a PHI of operations version of ExistingValue.
|
2017-05-20 03:01:27 +08:00
|
|
|
void NewGVN::addPhiOfOps(PHINode *Op, BasicBlock *BB,
|
|
|
|
Instruction *ExistingValue) {
|
|
|
|
InstrDFS[Op] = InstrToDFSNum(ExistingValue);
|
|
|
|
AllTempInstructions.insert(Op);
|
|
|
|
TempToBlock[Op] = BB;
|
2017-06-30 01:01:10 +08:00
|
|
|
RealToTemp[ExistingValue] = Op;
|
2017-10-01 07:51:53 +08:00
|
|
|
// Add all users to phi node use, as they are now uses of the phi of ops phis
|
|
|
|
// and may themselves be phi of ops.
|
|
|
|
for (auto *U : ExistingValue->users())
|
|
|
|
if (auto *UI = dyn_cast<Instruction>(U))
|
|
|
|
PHINodeUses.insert(UI);
|
2017-05-20 03:01:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool okayForPHIOfOps(const Instruction *I) {
|
2017-08-10 22:12:57 +08:00
|
|
|
if (!EnablePhiOfOps)
|
|
|
|
return false;
|
2017-05-20 03:01:27 +08:00
|
|
|
return isa<BinaryOperator>(I) || isa<SelectInst>(I) || isa<CmpInst>(I) ||
|
|
|
|
isa<LoadInst>(I);
|
|
|
|
}
|
|
|
|
|
2017-10-06 09:33:06 +08:00
|
|
|
bool NewGVN::OpIsSafeForPHIOfOpsHelper(
|
|
|
|
Value *V, const BasicBlock *PHIBlock,
|
|
|
|
SmallPtrSetImpl<const Value *> &Visited,
|
|
|
|
SmallVectorImpl<Instruction *> &Worklist) {
|
|
|
|
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
if (!isa<Instruction>(V))
|
|
|
|
return true;
|
|
|
|
auto OISIt = OpSafeForPHIOfOps.find(V);
|
|
|
|
if (OISIt != OpSafeForPHIOfOps.end())
|
|
|
|
return OISIt->second;
|
2017-10-01 07:51:04 +08:00
|
|
|
|
2017-10-06 09:33:06 +08:00
|
|
|
// Keep walking until we either dominate the phi block, or hit a phi, or run
|
|
|
|
// out of things to check.
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
if (DT->properlyDominates(getBlockForValue(V), PHIBlock)) {
|
|
|
|
OpSafeForPHIOfOps.insert({V, true});
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// PHI in the same block.
|
|
|
|
if (isa<PHINode>(V) && getBlockForValue(V) == PHIBlock) {
|
|
|
|
OpSafeForPHIOfOps.insert({V, false});
|
|
|
|
return false;
|
|
|
|
}
|
2017-10-01 07:51:04 +08:00
|
|
|
|
|
|
|
auto *OrigI = cast<Instruction>(V);
|
|
|
|
for (auto *Op : OrigI->operand_values()) {
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
if (!isa<Instruction>(Op))
|
|
|
|
continue;
|
2017-10-01 07:51:04 +08:00
|
|
|
// Stop now if we find an unsafe operand.
|
|
|
|
auto OISIt = OpSafeForPHIOfOps.find(OrigI);
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
if (OISIt != OpSafeForPHIOfOps.end()) {
|
|
|
|
if (!OISIt->second) {
|
|
|
|
OpSafeForPHIOfOps.insert({V, false});
|
|
|
|
return false;
|
|
|
|
}
|
2017-10-01 07:51:04 +08:00
|
|
|
continue;
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
}
|
2017-10-06 09:33:06 +08:00
|
|
|
if (!Visited.insert(Op).second)
|
|
|
|
continue;
|
2017-10-01 07:51:04 +08:00
|
|
|
Worklist.push_back(cast<Instruction>(Op));
|
|
|
|
}
|
2017-10-06 09:33:06 +08:00
|
|
|
return true;
|
|
|
|
}
|
2017-10-01 07:51:04 +08:00
|
|
|
|
2017-10-06 09:33:06 +08:00
|
|
|
// Return true if this operand will be safe to use for phi of ops.
|
|
|
|
//
|
|
|
|
// The reason some operands are unsafe is that we are not trying to recursively
|
|
|
|
// translate everything back through phi nodes. We actually expect some lookups
|
|
|
|
// of expressions to fail. In particular, a lookup where the expression cannot
|
|
|
|
// exist in the predecessor. This is true even if the expression, as shown, can
|
|
|
|
// be determined to be constant.
|
|
|
|
bool NewGVN::OpIsSafeForPHIOfOps(Value *V, const BasicBlock *PHIBlock,
|
|
|
|
SmallPtrSetImpl<const Value *> &Visited) {
|
|
|
|
SmallVector<Instruction *, 4> Worklist;
|
|
|
|
if (!OpIsSafeForPHIOfOpsHelper(V, PHIBlock, Visited, Worklist))
|
|
|
|
return false;
|
2017-10-01 07:51:04 +08:00
|
|
|
while (!Worklist.empty()) {
|
|
|
|
auto *I = Worklist.pop_back_val();
|
2017-10-06 09:33:06 +08:00
|
|
|
if (!OpIsSafeForPHIOfOpsHelper(I, PHIBlock, Visited, Worklist))
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
OpSafeForPHIOfOps.insert({V, true});
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to find a leader for instruction TransInst, which is a phi translated
|
|
|
|
// version of something in our original program. Visited is used to ensure we
|
|
|
|
// don't infinite loop during translations of cycles. OrigInst is the
|
|
|
|
// instruction in the original program, and PredBB is the predecessor we
|
|
|
|
// translated it through.
|
|
|
|
Value *NewGVN::findLeaderForInst(Instruction *TransInst,
|
|
|
|
SmallPtrSetImpl<Value *> &Visited,
|
|
|
|
MemoryAccess *MemAccess, Instruction *OrigInst,
|
|
|
|
BasicBlock *PredBB) {
|
|
|
|
unsigned IDFSNum = InstrToDFSNum(OrigInst);
|
|
|
|
// Make sure it's marked as a temporary instruction.
|
|
|
|
AllTempInstructions.insert(TransInst);
|
|
|
|
// and make sure anything that tries to add it's DFS number is
|
|
|
|
// redirected to the instruction we are making a phi of ops
|
|
|
|
// for.
|
|
|
|
TempToBlock.insert({TransInst, PredBB});
|
|
|
|
InstrDFS.insert({TransInst, IDFSNum});
|
|
|
|
|
|
|
|
const Expression *E = performSymbolicEvaluation(TransInst, Visited);
|
|
|
|
InstrDFS.erase(TransInst);
|
|
|
|
AllTempInstructions.erase(TransInst);
|
|
|
|
TempToBlock.erase(TransInst);
|
|
|
|
if (MemAccess)
|
|
|
|
TempToMemory.erase(TransInst);
|
|
|
|
if (!E)
|
|
|
|
return nullptr;
|
2017-09-05 10:17:40 +08:00
|
|
|
auto *FoundVal = findPHIOfOpsLeader(E, OrigInst, PredBB);
|
|
|
|
if (!FoundVal) {
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
ExpressionToPhiOfOps[E].insert(OrigInst);
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Cannot find phi of ops operand for " << *TransInst
|
|
|
|
<< " in block " << getBlockName(PredBB) << "\n");
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (auto *SI = dyn_cast<StoreInst>(FoundVal))
|
|
|
|
FoundVal = SI->getValueOperand();
|
|
|
|
return FoundVal;
|
|
|
|
}
|
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
// When we see an instruction that is an op of phis, generate the equivalent phi
|
|
|
|
// of ops form.
|
|
|
|
const Expression *
|
2017-10-01 07:51:53 +08:00
|
|
|
NewGVN::makePossiblePHIOfOps(Instruction *I,
|
2017-05-20 03:01:27 +08:00
|
|
|
SmallPtrSetImpl<Value *> &Visited) {
|
|
|
|
if (!okayForPHIOfOps(I))
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if (!Visited.insert(I).second)
|
|
|
|
return nullptr;
|
|
|
|
// For now, we require the instruction be cycle free because we don't
|
|
|
|
// *always* create a phi of ops for instructions that could be done as phi
|
|
|
|
// of ops, we only do it if we think it is useful. If we did do it all the
|
|
|
|
// time, we could remove the cycle free check.
|
|
|
|
if (!isCycleFree(I))
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
SmallPtrSet<const Value *, 8> ProcessedPHIs;
|
|
|
|
// TODO: We don't do phi translation on memory accesses because it's
|
|
|
|
// complicated. For a load, we'd need to be able to simulate a new memoryuse,
|
|
|
|
// which we don't have a good way of doing ATM.
|
|
|
|
auto *MemAccess = getMemoryAccess(I);
|
|
|
|
// If the memory operation is defined by a memory operation this block that
|
|
|
|
// isn't a MemoryPhi, transforming the pointer backwards through a scalar phi
|
|
|
|
// can't help, as it would still be killed by that memory operation.
|
|
|
|
if (MemAccess && !isa<MemoryPhi>(MemAccess->getDefiningAccess()) &&
|
|
|
|
MemAccess->getDefiningAccess()->getBlock() == I->getParent())
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
// Convert op of phis to phi of ops
|
2018-04-21 00:37:13 +08:00
|
|
|
SmallPtrSet<const Value *, 10> VisitedOps;
|
|
|
|
SmallVector<Value *, 4> Ops(I->operand_values());
|
|
|
|
BasicBlock *SamePHIBlock = nullptr;
|
|
|
|
PHINode *OpPHI = nullptr;
|
|
|
|
if (!DebugCounter::shouldExecute(PHIOfOpsCounter))
|
|
|
|
return nullptr;
|
|
|
|
for (auto *Op : Ops) {
|
2017-10-01 07:51:53 +08:00
|
|
|
if (!isa<PHINode>(Op)) {
|
|
|
|
auto *ValuePHI = RealToTemp.lookup(Op);
|
|
|
|
if (!ValuePHI)
|
|
|
|
continue;
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Found possible dependent phi of ops\n");
|
2017-10-01 07:51:53 +08:00
|
|
|
Op = ValuePHI;
|
|
|
|
}
|
2018-04-21 00:37:13 +08:00
|
|
|
OpPHI = cast<PHINode>(Op);
|
|
|
|
if (!SamePHIBlock) {
|
|
|
|
SamePHIBlock = getBlockForValue(OpPHI);
|
|
|
|
} else if (SamePHIBlock != getBlockForValue(OpPHI)) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(
|
|
|
|
dbgs()
|
|
|
|
<< "PHIs for operands are not all in the same block, aborting\n");
|
2018-04-21 00:37:13 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
2017-05-20 03:01:27 +08:00
|
|
|
// No point in doing this for one-operand phis.
|
2018-04-21 00:37:13 +08:00
|
|
|
if (OpPHI->getNumOperands() == 1) {
|
|
|
|
OpPHI = nullptr;
|
2017-05-20 03:01:27 +08:00
|
|
|
continue;
|
2018-04-21 00:37:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!OpPHI)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
SmallVector<ValPair, 4> PHIOps;
|
|
|
|
SmallPtrSet<Value *, 4> Deps;
|
|
|
|
auto *PHIBlock = getBlockForValue(OpPHI);
|
|
|
|
RevisitOnReachabilityChange[PHIBlock].reset(InstrToDFSNum(I));
|
|
|
|
for (unsigned PredNum = 0; PredNum < OpPHI->getNumOperands(); ++PredNum) {
|
|
|
|
auto *PredBB = OpPHI->getIncomingBlock(PredNum);
|
|
|
|
Value *FoundVal = nullptr;
|
|
|
|
SmallPtrSet<Value *, 4> CurrentDeps;
|
|
|
|
// We could just skip unreachable edges entirely but it's tricky to do
|
|
|
|
// with rewriting existing phi nodes.
|
|
|
|
if (ReachableEdges.count({PredBB, PHIBlock})) {
|
|
|
|
// Clone the instruction, create an expression from it that is
|
|
|
|
// translated back into the predecessor, and see if we have a leader.
|
|
|
|
Instruction *ValueOp = I->clone();
|
|
|
|
if (MemAccess)
|
|
|
|
TempToMemory.insert({ValueOp, MemAccess});
|
|
|
|
bool SafeForPHIOfOps = true;
|
|
|
|
VisitedOps.clear();
|
|
|
|
for (auto &Op : ValueOp->operands()) {
|
|
|
|
auto *OrigOp = &*Op;
|
|
|
|
// When these operand changes, it could change whether there is a
|
|
|
|
// leader for us or not, so we have to add additional users.
|
|
|
|
if (isa<PHINode>(Op)) {
|
|
|
|
Op = Op->DoPHITranslation(PHIBlock, PredBB);
|
|
|
|
if (Op != OrigOp && Op != I)
|
|
|
|
CurrentDeps.insert(Op);
|
|
|
|
} else if (auto *ValuePHI = RealToTemp.lookup(Op)) {
|
|
|
|
if (getBlockForValue(ValuePHI) == PHIBlock)
|
|
|
|
Op = ValuePHI->getIncomingValueForBlock(PredBB);
|
2018-04-19 23:05:47 +08:00
|
|
|
}
|
2018-04-21 00:37:13 +08:00
|
|
|
// If we phi-translated the op, it must be safe.
|
|
|
|
SafeForPHIOfOps =
|
|
|
|
SafeForPHIOfOps &&
|
|
|
|
(Op != OrigOp || OpIsSafeForPHIOfOps(Op, PHIBlock, VisitedOps));
|
2017-05-20 03:01:27 +08:00
|
|
|
}
|
2018-04-21 00:37:13 +08:00
|
|
|
// FIXME: For those things that are not safe we could generate
|
|
|
|
// expressions all the way down, and see if this comes out to a
|
|
|
|
// constant. For anything where that is true, and unsafe, we should
|
|
|
|
// have made a phi-of-ops (or value numbered it equivalent to something)
|
|
|
|
// for the pieces already.
|
|
|
|
FoundVal = !SafeForPHIOfOps ? nullptr
|
|
|
|
: findLeaderForInst(ValueOp, Visited,
|
|
|
|
MemAccess, I, PredBB);
|
|
|
|
ValueOp->deleteValue();
|
|
|
|
if (!FoundVal) {
|
|
|
|
// We failed to find a leader for the current ValueOp, but this might
|
|
|
|
// change in case of the translated operands change.
|
|
|
|
if (SafeForPHIOfOps)
|
|
|
|
for (auto Dep : CurrentDeps)
|
|
|
|
addAdditionalUsers(Dep, I);
|
|
|
|
|
|
|
|
return nullptr;
|
2017-05-20 03:01:27 +08:00
|
|
|
}
|
2018-04-21 00:37:13 +08:00
|
|
|
Deps.insert(CurrentDeps.begin(), CurrentDeps.end());
|
|
|
|
} else {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Skipping phi of ops operand for incoming block "
|
|
|
|
<< getBlockName(PredBB)
|
|
|
|
<< " because the block is unreachable\n");
|
2018-04-21 00:37:13 +08:00
|
|
|
FoundVal = UndefValue::get(I->getType());
|
|
|
|
RevisitOnReachabilityChange[PHIBlock].set(InstrToDFSNum(I));
|
2017-05-20 03:01:27 +08:00
|
|
|
}
|
2017-10-01 07:51:54 +08:00
|
|
|
|
2018-04-21 00:37:13 +08:00
|
|
|
PHIOps.push_back({FoundVal, PredBB});
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Found phi of ops operand " << *FoundVal << " in "
|
|
|
|
<< getBlockName(PredBB) << "\n");
|
2018-04-21 00:37:13 +08:00
|
|
|
}
|
|
|
|
for (auto Dep : Deps)
|
|
|
|
addAdditionalUsers(Dep, I);
|
|
|
|
sortPHIOps(PHIOps);
|
|
|
|
auto *E = performSymbolicPHIEvaluation(PHIOps, I, PHIBlock);
|
|
|
|
if (isa<ConstantExpression>(E) || isa<VariableExpression>(E)) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(
|
|
|
|
dbgs()
|
|
|
|
<< "Not creating real PHI of ops because it simplified to existing "
|
|
|
|
"value or constant\n");
|
2017-10-01 07:51:54 +08:00
|
|
|
return E;
|
2017-05-20 03:01:27 +08:00
|
|
|
}
|
2018-04-21 00:37:13 +08:00
|
|
|
auto *ValuePHI = RealToTemp.lookup(I);
|
|
|
|
bool NewPHI = false;
|
|
|
|
if (!ValuePHI) {
|
|
|
|
ValuePHI =
|
|
|
|
PHINode::Create(I->getType(), OpPHI->getNumOperands(), "phiofops");
|
|
|
|
addPhiOfOps(ValuePHI, PHIBlock, I);
|
|
|
|
NewPHI = true;
|
|
|
|
NumGVNPHIOfOpsCreated++;
|
|
|
|
}
|
|
|
|
if (NewPHI) {
|
|
|
|
for (auto PHIOp : PHIOps)
|
|
|
|
ValuePHI->addIncoming(PHIOp.first, PHIOp.second);
|
|
|
|
} else {
|
|
|
|
TempToBlock[ValuePHI] = PHIBlock;
|
|
|
|
unsigned int i = 0;
|
|
|
|
for (auto PHIOp : PHIOps) {
|
|
|
|
ValuePHI->setIncomingValue(i, PHIOp.first);
|
|
|
|
ValuePHI->setIncomingBlock(i, PHIOp.second);
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RevisitOnReachabilityChange[PHIBlock].set(InstrToDFSNum(I));
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Created phi of ops " << *ValuePHI << " for " << *I
|
|
|
|
<< "\n");
|
2018-04-21 00:37:13 +08:00
|
|
|
|
|
|
|
return E;
|
2017-05-20 03:01:27 +08:00
|
|
|
}
|
|
|
|
|
2017-03-11 03:05:04 +08:00
|
|
|
// The algorithm initially places the values of the routine in the TOP
|
|
|
|
// congruence class. The leader of TOP is the undetermined value `undef`.
|
|
|
|
// When the algorithm has finished, values still in TOP are unreachable.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
void NewGVN::initializeCongruenceClasses(Function &F) {
|
2017-04-07 02:52:50 +08:00
|
|
|
NextCongruenceNum = 0;
|
|
|
|
|
|
|
|
// Note that even though we use the live on entry def as a representative
|
|
|
|
// MemoryAccess, it is *not* the same as the actual live on entry def. We
|
|
|
|
// have no real equivalemnt to undef for MemoryAccesses, and so we really
|
|
|
|
// should be checking whether the MemoryAccess is top if we want to know if it
|
|
|
|
// is equivalent to everything. Otherwise, what this really signifies is that
|
|
|
|
// the access "it reaches all the way back to the beginning of the function"
|
|
|
|
|
2017-03-11 03:05:04 +08:00
|
|
|
// Initialize all other instructions to be in TOP class.
|
|
|
|
TOPClass = createCongruenceClass(nullptr, nullptr);
|
2017-04-08 02:38:09 +08:00
|
|
|
TOPClass->setMemoryLeader(MSSA->getLiveOnEntryDef());
|
2017-04-07 02:52:50 +08:00
|
|
|
// The live on entry def gets put into it's own class
|
|
|
|
MemoryAccessToClass[MSSA->getLiveOnEntryDef()] =
|
|
|
|
createMemoryClass(MSSA->getLiveOnEntryDef());
|
|
|
|
|
2017-04-19 01:06:11 +08:00
|
|
|
for (auto DTN : nodes(DT)) {
|
|
|
|
BasicBlock *BB = DTN->getBlock();
|
2017-04-07 02:52:50 +08:00
|
|
|
// All MemoryAccesses are equivalent to live on entry to start. They must
|
|
|
|
// be initialized to something so that initial changes are noticed. For
|
|
|
|
// the maximal answer, we initialize them all to be the same as
|
|
|
|
// liveOnEntry.
|
2017-04-19 01:06:11 +08:00
|
|
|
auto *MemoryBlockDefs = MSSA->getBlockDefs(BB);
|
2017-04-07 02:52:50 +08:00
|
|
|
if (MemoryBlockDefs)
|
|
|
|
for (const auto &Def : *MemoryBlockDefs) {
|
|
|
|
MemoryAccessToClass[&Def] = TOPClass;
|
|
|
|
auto *MD = dyn_cast<MemoryDef>(&Def);
|
|
|
|
// Insert the memory phis into the member list.
|
|
|
|
if (!MD) {
|
|
|
|
const MemoryPhi *MP = cast<MemoryPhi>(&Def);
|
2017-04-08 02:38:09 +08:00
|
|
|
TOPClass->memory_insert(MP);
|
2017-04-07 02:52:50 +08:00
|
|
|
MemoryPhiState.insert({MP, MPS_TOP});
|
|
|
|
}
|
2017-01-03 02:00:46 +08:00
|
|
|
|
2017-04-07 02:52:50 +08:00
|
|
|
if (MD && isa<StoreInst>(MD->getMemoryInst()))
|
2017-04-08 02:38:09 +08:00
|
|
|
TOPClass->incStoreCount();
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
2017-10-01 07:51:53 +08:00
|
|
|
|
|
|
|
// FIXME: This is trying to discover which instructions are uses of phi
|
|
|
|
// nodes. We should move this into one of the myriad of places that walk
|
|
|
|
// all the operands already.
|
2017-04-19 01:06:11 +08:00
|
|
|
for (auto &I : *BB) {
|
2017-05-20 03:01:27 +08:00
|
|
|
if (isa<PHINode>(&I))
|
|
|
|
for (auto *U : I.users())
|
|
|
|
if (auto *UInst = dyn_cast<Instruction>(U))
|
|
|
|
if (InstrToDFSNum(UInst) != 0 && okayForPHIOfOps(UInst))
|
|
|
|
PHINodeUses.insert(UInst);
|
2017-02-11 23:20:15 +08:00
|
|
|
// Don't insert void terminators into the class. We don't value number
|
2017-03-11 03:05:04 +08:00
|
|
|
// them, and they just end up sitting in TOP.
|
2018-08-26 17:51:22 +08:00
|
|
|
if (I.isTerminator() && I.getType()->isVoidTy())
|
2017-02-11 23:20:15 +08:00
|
|
|
continue;
|
2017-04-08 02:38:09 +08:00
|
|
|
TOPClass->insert(&I);
|
2017-03-11 03:05:04 +08:00
|
|
|
ValueToClass[&I] = TOPClass;
|
2016-12-27 03:57:25 +08:00
|
|
|
}
|
2017-01-03 02:00:46 +08:00
|
|
|
}
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Initialize arguments to be in their own unique congruence classes
|
|
|
|
for (auto &FA : F.args())
|
|
|
|
createSingletonCongruenceClass(&FA);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NewGVN::cleanupTables() {
|
|
|
|
for (unsigned i = 0, e = CongruenceClasses.size(); i != e; ++i) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Congruence class " << CongruenceClasses[i]->getID()
|
|
|
|
<< " has " << CongruenceClasses[i]->size()
|
|
|
|
<< " members\n");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Make sure we delete the congruence class (probably worth switching to
|
|
|
|
// a unique_ptr at some point.
|
|
|
|
delete CongruenceClasses[i];
|
2016-12-28 22:00:11 +08:00
|
|
|
CongruenceClasses[i] = nullptr;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
// Destroy the value expressions
|
|
|
|
SmallVector<Instruction *, 8> TempInst(AllTempInstructions.begin(),
|
|
|
|
AllTempInstructions.end());
|
|
|
|
AllTempInstructions.clear();
|
|
|
|
|
|
|
|
// We have to drop all references for everything first, so there are no uses
|
|
|
|
// left as we delete them.
|
|
|
|
for (auto *I : TempInst) {
|
|
|
|
I->dropAllReferences();
|
|
|
|
}
|
|
|
|
|
|
|
|
while (!TempInst.empty()) {
|
|
|
|
auto *I = TempInst.back();
|
|
|
|
TempInst.pop_back();
|
|
|
|
I->deleteValue();
|
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested 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();
|
2017-05-20 03:01:27 +08:00
|
|
|
RealToTemp.clear();
|
|
|
|
AdditionalUsers.clear();
|
|
|
|
ExpressionToPhiOfOps.clear();
|
|
|
|
TempToBlock.clear();
|
|
|
|
TempToMemory.clear();
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
PHINodeUses.clear();
|
|
|
|
OpSafeForPHIOfOps.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
|
|
|
ReachableBlocks.clear();
|
|
|
|
ReachableEdges.clear();
|
|
|
|
#ifndef NDEBUG
|
|
|
|
ProcessedCount.clear();
|
|
|
|
#endif
|
|
|
|
InstrDFS.clear();
|
|
|
|
InstructionsToErase.clear();
|
|
|
|
DFSToInstr.clear();
|
|
|
|
BlockInstRange.clear();
|
|
|
|
TouchedInstructions.clear();
|
2017-01-27 06:21:48 +08:00
|
|
|
MemoryAccessToClass.clear();
|
2017-02-19 07:06:50 +08:00
|
|
|
PredicateToUsers.clear();
|
2017-04-07 02:52:50 +08:00
|
|
|
MemoryToUsers.clear();
|
2017-10-01 07:51:53 +08:00
|
|
|
RevisitOnReachabilityChange.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
|
|
|
}
|
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
// Assign local DFS number mapping to instructions, and leave space for Value
|
|
|
|
// PHI'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
|
|
|
std::pair<unsigned, unsigned> NewGVN::assignDFSNumbers(BasicBlock *B,
|
|
|
|
unsigned Start) {
|
|
|
|
unsigned End = Start;
|
2017-05-20 03:01:27 +08:00
|
|
|
if (MemoryAccess *MemPhi = getMemoryAccess(B)) {
|
2016-12-26 06:23:49 +08:00
|
|
|
InstrDFS[MemPhi] = End++;
|
2016-12-29 07:24:02 +08:00
|
|
|
DFSToInstr.emplace_back(MemPhi);
|
2016-12-26 06:23:49 +08:00
|
|
|
}
|
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
// Then the real block goes next.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
for (auto &I : *B) {
|
2017-03-07 02:42:27 +08:00
|
|
|
// There's no need to call isInstructionTriviallyDead more than once on
|
|
|
|
// an instruction. Therefore, once we know that an instruction is dead
|
|
|
|
// we change its DFS number so that it doesn't get value numbered.
|
|
|
|
if (isInstructionTriviallyDead(&I, TLI)) {
|
|
|
|
InstrDFS[&I] = 0;
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Skipping trivially dead instruction " << I << "\n");
|
2017-03-07 02:42:27 +08:00
|
|
|
markInstructionForDeletion(&I);
|
|
|
|
continue;
|
|
|
|
}
|
2017-10-01 07:51:53 +08:00
|
|
|
if (isa<PHINode>(&I))
|
|
|
|
RevisitOnReachabilityChange[B].set(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
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
void NewGVN::updateProcessedCount(const Value *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
|
|
|
#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
|
|
|
|
}
|
2017-10-21 05:47:29 +08:00
|
|
|
|
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
|
2017-05-22 07:41:58 +08:00
|
|
|
// argument. Filter out unreachable blocks and self phis from our operands.
|
|
|
|
// TODO: We could do cycle-checking on the memory phis to allow valueizing for
|
|
|
|
// self-phi checking.
|
2017-03-18 23:41:36 +08:00
|
|
|
const BasicBlock *PHIBlock = MP->getBlock();
|
2016-12-26 06:23:49 +08:00
|
|
|
auto Filtered = make_filter_range(MP->operands(), [&](const Use &U) {
|
2017-05-22 07:41:58 +08:00
|
|
|
return cast<MemoryAccess>(U) != MP &&
|
2017-05-20 03:01:27 +08:00
|
|
|
!isMemoryAccessTOP(cast<MemoryAccess>(U)) &&
|
2017-03-18 23:41:36 +08:00
|
|
|
ReachableEdges.count({MP->getIncomingBlock(U), PHIBlock});
|
2016-12-26 06:23:49 +08:00
|
|
|
});
|
2017-01-27 10:37:11 +08:00
|
|
|
// If all that is left is nothing, our memoryphi is undef. We keep it as
|
|
|
|
// InitialClass. Note: The only case this should happen is if we have at
|
|
|
|
// least one self-argument.
|
|
|
|
if (Filtered.begin() == Filtered.end()) {
|
2017-04-07 02:52:50 +08:00
|
|
|
if (setMemoryClass(MP, TOPClass))
|
2017-01-27 10:37:11 +08:00
|
|
|
markMemoryUsersTouched(MP);
|
|
|
|
return;
|
|
|
|
}
|
2016-12-26 06:23:49 +08:00
|
|
|
|
|
|
|
// Transform the remaining operands into operand leaders.
|
|
|
|
// FIXME: mapped_iterator should have a range version.
|
|
|
|
auto LookupFunc = [&](const Use &U) {
|
2017-04-07 02:52:50 +08:00
|
|
|
return lookupMemoryLeader(cast<MemoryAccess>(U));
|
2016-12-26 06:23:49 +08:00
|
|
|
};
|
|
|
|
auto MappedBegin = map_iterator(Filtered.begin(), LookupFunc);
|
|
|
|
auto MappedEnd = map_iterator(Filtered.end(), LookupFunc);
|
|
|
|
|
|
|
|
// and now check if all the elements are equal.
|
|
|
|
// Sadly, we can't use std::equals since these are random access iterators.
|
2017-04-07 02:52:50 +08:00
|
|
|
const auto *AllSameValue = *MappedBegin;
|
2016-12-26 06:23:49 +08:00
|
|
|
++MappedBegin;
|
|
|
|
bool AllEqual = std::all_of(
|
|
|
|
MappedBegin, MappedEnd,
|
|
|
|
[&AllSameValue](const MemoryAccess *V) { return V == AllSameValue; });
|
|
|
|
|
|
|
|
if (AllEqual)
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Memory Phi value numbered to " << *AllSameValue
|
|
|
|
<< "\n");
|
2016-12-26 06:23:49 +08:00
|
|
|
else
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Memory Phi value numbered to itself\n");
|
2017-04-07 02:52:50 +08:00
|
|
|
// If it's equal to something, it's in that class. Otherwise, it has to be in
|
|
|
|
// a class where it is the leader (other things may be equivalent to it, but
|
|
|
|
// it needs to start off in its own class, which means it must have been the
|
|
|
|
// leader, and it can't have stopped being the leader because it was never
|
|
|
|
// removed).
|
|
|
|
CongruenceClass *CC =
|
|
|
|
AllEqual ? getMemoryClass(AllSameValue) : ensureLeaderOfMemoryClass(MP);
|
|
|
|
auto OldState = MemoryPhiState.lookup(MP);
|
|
|
|
assert(OldState != MPS_Invalid && "Invalid memory phi state");
|
|
|
|
auto NewState = AllEqual ? MPS_Equivalent : MPS_Unique;
|
|
|
|
MemoryPhiState[MP] = NewState;
|
|
|
|
if (setMemoryClass(MP, CC) || OldState != NewState)
|
2016-12-26 06:23:49 +08:00
|
|
|
markMemoryUsersTouched(MP);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Value number a single instruction, symbolically evaluating, performing
|
|
|
|
// congruence finding, and updating mappings.
|
|
|
|
void NewGVN::valueNumberInstruction(Instruction *I) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Processing instruction " << *I << "\n");
|
2016-12-26 06:23:49 +08:00
|
|
|
if (!I->isTerminator()) {
|
2017-03-02 03:59:26 +08:00
|
|
|
const Expression *Symbolized = nullptr;
|
2017-05-20 03:01:27 +08:00
|
|
|
SmallPtrSet<Value *, 2> Visited;
|
2017-03-02 03:59:26 +08:00
|
|
|
if (DebugCounter::shouldExecute(VNCounter)) {
|
2017-05-20 03:01:27 +08:00
|
|
|
Symbolized = performSymbolicEvaluation(I, Visited);
|
|
|
|
// Make a phi of ops if necessary
|
|
|
|
if (Symbolized && !isa<ConstantExpression>(Symbolized) &&
|
|
|
|
!isa<VariableExpression>(Symbolized) && PHINodeUses.count(I)) {
|
2017-10-01 07:51:53 +08:00
|
|
|
auto *PHIE = makePossiblePHIOfOps(I, Visited);
|
2017-08-04 05:17:49 +08:00
|
|
|
// If we created a phi of ops, use it.
|
|
|
|
// If we couldn't create one, make sure we don't leave one lying around
|
|
|
|
if (PHIE) {
|
2017-05-20 03:01:27 +08:00
|
|
|
Symbolized = PHIE;
|
2017-08-04 05:17:49 +08:00
|
|
|
} else if (auto *Op = RealToTemp.lookup(I)) {
|
|
|
|
removePhiOfOps(I, Op);
|
|
|
|
}
|
2017-05-20 03:01:27 +08:00
|
|
|
}
|
2017-03-02 03:59:26 +08:00
|
|
|
} else {
|
2017-03-07 02:42:39 +08:00
|
|
|
// Mark the instruction as unused so we don't value number it again.
|
|
|
|
InstrDFS[I] = 0;
|
2017-03-02 03:59:26 +08:00
|
|
|
}
|
2017-01-03 02:00:53 +08:00
|
|
|
// If we couldn't come up with a symbolic expression, use the unknown
|
|
|
|
// expression
|
2017-05-20 03:01:27 +08:00
|
|
|
if (Symbolized == nullptr)
|
2017-01-03 02:00:53 +08:00
|
|
|
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
|
2017-02-11 20:48:50 +08:00
|
|
|
// don't currently understand. We don't place non-value producing
|
|
|
|
// terminators in a class.
|
2017-01-03 02:22:38 +08:00
|
|
|
if (!I->getType()->isVoidTy()) {
|
2017-01-03 02:00:53 +08:00
|
|
|
auto *Symbolized = createUnknownExpression(I);
|
|
|
|
performCongruenceFinding(I, Symbolized);
|
|
|
|
}
|
2018-10-18 08:39:46 +08:00
|
|
|
processOutgoingEdges(I, I->getParent());
|
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
|
|
|
|
2017-01-12 04:22:36 +08:00
|
|
|
// Check if there is a path, using single or equal argument phi nodes, from
|
|
|
|
// First to Second.
|
2017-05-19 07:22:44 +08:00
|
|
|
bool NewGVN::singleReachablePHIPath(
|
|
|
|
SmallPtrSet<const MemoryAccess *, 8> &Visited, const MemoryAccess *First,
|
|
|
|
const MemoryAccess *Second) const {
|
2017-01-12 04:22:36 +08:00
|
|
|
if (First == Second)
|
|
|
|
return true;
|
2017-04-01 17:44:24 +08:00
|
|
|
if (MSSA->isLiveOnEntryDef(First))
|
2017-01-12 04:22:36 +08:00
|
|
|
return false;
|
2017-04-07 02:52:50 +08:00
|
|
|
|
2017-05-19 07:22:44 +08:00
|
|
|
// This is not perfect, but as we're just verifying here, we can live with
|
|
|
|
// the loss of precision. The real solution would be that of doing strongly
|
|
|
|
// connected component finding in this routine, and it's probably not worth
|
|
|
|
// the complexity for the time being. So, we just keep a set of visited
|
|
|
|
// MemoryAccess and return true when we hit a cycle.
|
|
|
|
if (Visited.count(First))
|
|
|
|
return true;
|
|
|
|
Visited.insert(First);
|
|
|
|
|
2017-04-01 17:44:24 +08:00
|
|
|
const auto *EndDef = First;
|
2017-04-06 01:26:25 +08:00
|
|
|
for (auto *ChainDef : optimized_def_chain(First)) {
|
2017-04-01 17:44:24 +08:00
|
|
|
if (ChainDef == Second)
|
|
|
|
return true;
|
|
|
|
if (MSSA->isLiveOnEntryDef(ChainDef))
|
|
|
|
return false;
|
|
|
|
EndDef = ChainDef;
|
2017-01-12 04:22:36 +08:00
|
|
|
}
|
2017-04-01 17:44:24 +08:00
|
|
|
auto *MP = cast<MemoryPhi>(EndDef);
|
|
|
|
auto ReachableOperandPred = [&](const Use &U) {
|
|
|
|
return ReachableEdges.count({MP->getIncomingBlock(U), MP->getBlock()});
|
|
|
|
};
|
|
|
|
auto FilteredPhiArgs =
|
|
|
|
make_filter_range(MP->operands(), ReachableOperandPred);
|
|
|
|
SmallVector<const Value *, 32> OperandList;
|
2018-11-17 09:44:25 +08:00
|
|
|
llvm::copy(FilteredPhiArgs, std::back_inserter(OperandList));
|
2018-08-17 15:51:01 +08:00
|
|
|
bool Okay = is_splat(OperandList);
|
2017-04-01 17:44:24 +08:00
|
|
|
if (Okay)
|
2017-05-19 07:22:44 +08:00
|
|
|
return singleReachablePHIPath(Visited, cast<MemoryAccess>(OperandList[0]),
|
|
|
|
Second);
|
2017-04-01 17:44:24 +08:00
|
|
|
return false;
|
2017-01-12 04:22:36 +08:00
|
|
|
}
|
|
|
|
|
2017-01-03 02:00:46 +08:00
|
|
|
// Verify the that the memory equivalence table makes sense relative to the
|
2017-01-12 04:22:36 +08:00
|
|
|
// congruence classes. Note that this checking is not perfect, and is currently
|
2017-01-15 04:15:04 +08:00
|
|
|
// subject to very rare false negatives. It is only useful for
|
|
|
|
// testing/debugging.
|
2017-01-12 04:22:36 +08:00
|
|
|
void NewGVN::verifyMemoryCongruency() const {
|
2017-03-25 10:40:02 +08:00
|
|
|
#ifndef NDEBUG
|
2017-04-07 02:52:50 +08:00
|
|
|
// Verify that the memory table equivalence and memory member set match
|
|
|
|
for (const auto *CC : CongruenceClasses) {
|
|
|
|
if (CC == TOPClass || CC->isDead())
|
|
|
|
continue;
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC->getStoreCount() != 0) {
|
2017-04-11 07:08:35 +08:00
|
|
|
assert((CC->getStoredValue() || !isa<StoreInst>(CC->getLeader())) &&
|
2017-05-05 01:26:15 +08:00
|
|
|
"Any class with a store as a leader should have a "
|
|
|
|
"representative stored value");
|
2017-04-08 02:38:09 +08:00
|
|
|
assert(CC->getMemoryLeader() &&
|
2017-05-05 01:26:15 +08:00
|
|
|
"Any congruence class with a store should have a "
|
|
|
|
"representative access");
|
2017-04-07 02:52:50 +08:00
|
|
|
}
|
|
|
|
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC->getMemoryLeader())
|
|
|
|
assert(MemoryAccessToClass.lookup(CC->getMemoryLeader()) == CC &&
|
2017-04-07 02:52:50 +08:00
|
|
|
"Representative MemoryAccess does not appear to be reverse "
|
|
|
|
"mapped properly");
|
2017-04-08 02:38:09 +08:00
|
|
|
for (auto M : CC->memory())
|
2017-04-07 02:52:50 +08:00
|
|
|
assert(MemoryAccessToClass.lookup(M) == CC &&
|
|
|
|
"Memory member does not appear to be reverse mapped properly");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Anything equivalent in the MemoryAccess table should be in the same
|
2017-01-03 02:00:46 +08:00
|
|
|
// congruence class.
|
|
|
|
|
|
|
|
// Filter out the unreachable and trivially dead entries, because they may
|
|
|
|
// never have been updated if the instructions were not processed.
|
|
|
|
auto ReachableAccessPred =
|
2017-01-27 06:21:48 +08:00
|
|
|
[&](const std::pair<const MemoryAccess *, CongruenceClass *> Pair) {
|
2017-01-03 02:00:46 +08:00
|
|
|
bool Result = ReachableBlocks.count(Pair.first->getBlock());
|
2017-04-19 04:15:47 +08:00
|
|
|
if (!Result || MSSA->isLiveOnEntryDef(Pair.first) ||
|
|
|
|
MemoryToDFSNum(Pair.first) == 0)
|
2017-01-03 02:00:46 +08:00
|
|
|
return false;
|
|
|
|
if (auto *MemDef = dyn_cast<MemoryDef>(Pair.first))
|
|
|
|
return !isInstructionTriviallyDead(MemDef->getMemoryInst());
|
2017-05-16 02:50:53 +08:00
|
|
|
|
|
|
|
// We could have phi nodes which operands are all trivially dead,
|
|
|
|
// so we don't process them.
|
|
|
|
if (auto *MemPHI = dyn_cast<MemoryPhi>(Pair.first)) {
|
|
|
|
for (auto &U : MemPHI->incoming_values()) {
|
2017-10-01 07:51:54 +08:00
|
|
|
if (auto *I = dyn_cast<Instruction>(&*U)) {
|
2017-05-16 02:50:53 +08:00
|
|
|
if (!isInstructionTriviallyDead(I))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-01-03 02:00:46 +08:00
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
2017-01-27 06:21:48 +08:00
|
|
|
auto Filtered = make_filter_range(MemoryAccessToClass, ReachableAccessPred);
|
2017-01-03 02:00:46 +08:00
|
|
|
for (auto KV : Filtered) {
|
|
|
|
if (auto *FirstMUD = dyn_cast<MemoryUseOrDef>(KV.first)) {
|
2017-04-08 02:38:09 +08:00
|
|
|
auto *SecondMUD = dyn_cast<MemoryUseOrDef>(KV.second->getMemoryLeader());
|
2017-05-19 07:22:44 +08:00
|
|
|
if (FirstMUD && SecondMUD) {
|
|
|
|
SmallPtrSet<const MemoryAccess *, 8> VisitedMAS;
|
|
|
|
assert((singleReachablePHIPath(VisitedMAS, FirstMUD, SecondMUD) ||
|
2017-01-15 04:15:04 +08:00
|
|
|
ValueToClass.lookup(FirstMUD->getMemoryInst()) ==
|
|
|
|
ValueToClass.lookup(SecondMUD->getMemoryInst())) &&
|
|
|
|
"The instructions for these memory operations should have "
|
|
|
|
"been in the same congruence class or reachable through"
|
|
|
|
"a single argument phi");
|
2017-05-19 07:22:44 +08:00
|
|
|
}
|
2017-01-03 02:00:46 +08:00
|
|
|
} else if (auto *FirstMP = dyn_cast<MemoryPhi>(KV.first)) {
|
|
|
|
// We can only sanely verify that MemoryDefs in the operand list all have
|
|
|
|
// the same class.
|
|
|
|
auto ReachableOperandPred = [&](const Use &U) {
|
2017-03-18 23:41:36 +08:00
|
|
|
return ReachableEdges.count(
|
|
|
|
{FirstMP->getIncomingBlock(U), FirstMP->getBlock()}) &&
|
2017-01-03 02:00:46 +08:00
|
|
|
isa<MemoryDef>(U);
|
|
|
|
|
|
|
|
};
|
|
|
|
// All arguments should in the same class, ignoring unreachable arguments
|
|
|
|
auto FilteredPhiArgs =
|
|
|
|
make_filter_range(FirstMP->operands(), ReachableOperandPred);
|
|
|
|
SmallVector<const CongruenceClass *, 16> PhiOpClasses;
|
|
|
|
std::transform(FilteredPhiArgs.begin(), FilteredPhiArgs.end(),
|
|
|
|
std::back_inserter(PhiOpClasses), [&](const Use &U) {
|
|
|
|
const MemoryDef *MD = cast<MemoryDef>(U);
|
|
|
|
return ValueToClass.lookup(MD->getMemoryInst());
|
|
|
|
});
|
2018-08-17 15:51:01 +08:00
|
|
|
assert(is_splat(PhiOpClasses) &&
|
2017-01-03 02:00:46 +08:00
|
|
|
"All MemoryPhi arguments should be in the same class");
|
|
|
|
}
|
|
|
|
}
|
2017-03-25 10:40:02 +08:00
|
|
|
#endif
|
2017-01-03 02:00:46 +08:00
|
|
|
}
|
|
|
|
|
2017-03-18 23:41:40 +08:00
|
|
|
// Verify that the sparse propagation we did actually found the maximal fixpoint
|
|
|
|
// We do this by storing the value to class mapping, touching all instructions,
|
|
|
|
// and redoing the iteration to see if anything changed.
|
|
|
|
void NewGVN::verifyIterationSettled(Function &F) {
|
2017-02-19 07:06:50 +08:00
|
|
|
#ifndef NDEBUG
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Beginning iteration verification\n");
|
2017-03-18 23:41:40 +08:00
|
|
|
if (DebugCounter::isCounterSet(VNCounter))
|
|
|
|
DebugCounter::setCounterValue(VNCounter, StartingVNCounter);
|
|
|
|
|
|
|
|
// Note that we have to store the actual classes, as we may change existing
|
|
|
|
// classes during iteration. This is because our memory iteration propagation
|
|
|
|
// is not perfect, and so may waste a little work. But it should generate
|
|
|
|
// exactly the same congruence classes we have now, with different IDs.
|
|
|
|
std::map<const Value *, CongruenceClass> BeforeIteration;
|
|
|
|
|
|
|
|
for (auto &KV : ValueToClass) {
|
|
|
|
if (auto *I = dyn_cast<Instruction>(KV.first))
|
|
|
|
// Skip unused/dead instructions.
|
2017-04-07 02:52:58 +08:00
|
|
|
if (InstrToDFSNum(I) == 0)
|
2017-02-19 07:06:50 +08:00
|
|
|
continue;
|
2017-03-18 23:41:40 +08:00
|
|
|
BeforeIteration.insert({KV.first, *KV.second});
|
|
|
|
}
|
|
|
|
|
|
|
|
TouchedInstructions.set();
|
|
|
|
TouchedInstructions.reset(0);
|
|
|
|
iterateTouchedInstructions();
|
|
|
|
DenseSet<std::pair<const CongruenceClass *, const CongruenceClass *>>
|
|
|
|
EqualClasses;
|
|
|
|
for (const auto &KV : ValueToClass) {
|
|
|
|
if (auto *I = dyn_cast<Instruction>(KV.first))
|
|
|
|
// Skip unused/dead instructions.
|
2017-04-07 02:52:58 +08:00
|
|
|
if (InstrToDFSNum(I) == 0)
|
2017-03-18 23:41:40 +08:00
|
|
|
continue;
|
|
|
|
// We could sink these uses, but i think this adds a bit of clarity here as
|
|
|
|
// to what we are comparing.
|
|
|
|
auto *BeforeCC = &BeforeIteration.find(KV.first)->second;
|
|
|
|
auto *AfterCC = KV.second;
|
|
|
|
// Note that the classes can't change at this point, so we memoize the set
|
|
|
|
// that are equal.
|
|
|
|
if (!EqualClasses.count({BeforeCC, AfterCC})) {
|
2017-04-08 02:38:09 +08:00
|
|
|
assert(BeforeCC->isEquivalentTo(AfterCC) &&
|
2017-03-18 23:41:40 +08:00
|
|
|
"Value number changed after main loop completed!");
|
|
|
|
EqualClasses.insert({BeforeCC, AfterCC});
|
2017-02-19 07:06:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-05-17 03:58:47 +08:00
|
|
|
// Verify that for each store expression in the expression to class mapping,
|
|
|
|
// only the latest appears, and multiple ones do not appear.
|
|
|
|
// Because loads do not use the stored value when doing equality with stores,
|
|
|
|
// if we don't erase the old store expressions from the table, a load can find
|
|
|
|
// a no-longer valid StoreExpression.
|
|
|
|
void NewGVN::verifyStoreExpressions() const {
|
2017-05-17 04:02:45 +08:00
|
|
|
#ifndef NDEBUG
|
2017-06-19 08:24:00 +08:00
|
|
|
// This is the only use of this, and it's not worth defining a complicated
|
|
|
|
// densemapinfo hash/equality function for it.
|
|
|
|
std::set<
|
|
|
|
std::pair<const Value *,
|
|
|
|
std::tuple<const Value *, const CongruenceClass *, Value *>>>
|
|
|
|
StoreExpressionSet;
|
2017-05-17 03:58:47 +08:00
|
|
|
for (const auto &KV : ExpressionToClass) {
|
|
|
|
if (auto *SE = dyn_cast<StoreExpression>(KV.first)) {
|
|
|
|
// Make sure a version that will conflict with loads is not already there
|
2017-06-19 08:24:00 +08:00
|
|
|
auto Res = StoreExpressionSet.insert(
|
|
|
|
{SE->getOperand(0), std::make_tuple(SE->getMemoryLeader(), KV.second,
|
|
|
|
SE->getStoredValue())});
|
|
|
|
bool Okay = Res.second;
|
|
|
|
// It's okay to have the same expression already in there if it is
|
|
|
|
// identical in nature.
|
|
|
|
// This can happen when the leader of the stored value changes over time.
|
2017-06-21 06:57:40 +08:00
|
|
|
if (!Okay)
|
|
|
|
Okay = (std::get<1>(Res.first->second) == KV.second) &&
|
|
|
|
(lookupOperandLeader(std::get<2>(Res.first->second)) ==
|
|
|
|
lookupOperandLeader(SE->getStoredValue()));
|
2017-06-19 08:24:00 +08:00
|
|
|
assert(Okay && "Stored expression conflict exists in expression table");
|
2017-05-17 03:58:47 +08:00
|
|
|
auto *ValueExpr = ValueToExpression.lookup(SE->getStoreInst());
|
|
|
|
assert(ValueExpr && ValueExpr->equals(*SE) &&
|
|
|
|
"StoreExpression in ExpressionToClass is not latest "
|
|
|
|
"StoreExpression for value");
|
|
|
|
}
|
|
|
|
}
|
2017-05-17 04:02:45 +08:00
|
|
|
#endif
|
2017-05-17 03:58:47 +08:00
|
|
|
}
|
|
|
|
|
2017-03-18 23:41:40 +08:00
|
|
|
// This is the main value numbering loop, it iterates over the initial touched
|
|
|
|
// instruction set, propagating value numbers, marking things touched, etc,
|
|
|
|
// until the set of touched instructions is completely empty.
|
|
|
|
void NewGVN::iterateTouchedInstructions() {
|
|
|
|
unsigned int Iterations = 0;
|
|
|
|
// Figure out where touchedinstructions starts
|
|
|
|
int FirstInstr = TouchedInstructions.find_first();
|
|
|
|
// Nothing set, nothing to iterate, just return.
|
|
|
|
if (FirstInstr == -1)
|
|
|
|
return;
|
2017-05-20 03:01:27 +08:00
|
|
|
const BasicBlock *LastBlock = getBlockForValue(InstrFromDFSNum(FirstInstr));
|
2017-03-18 23:41:40 +08:00
|
|
|
while (TouchedInstructions.any()) {
|
|
|
|
++Iterations;
|
|
|
|
// Walk through all the instructions in all the blocks in RPO.
|
|
|
|
// TODO: As we hit a new block, we should push and pop equalities into a
|
|
|
|
// table lookupOperandLeader can use, to catch things PredicateInfo
|
|
|
|
// might miss, like edge-only equivalences.
|
2017-05-17 09:07:53 +08:00
|
|
|
for (unsigned InstrNum : TouchedInstructions.set_bits()) {
|
2017-03-18 23:41:40 +08:00
|
|
|
|
|
|
|
// This instruction was found to be dead. We don't bother looking
|
|
|
|
// at it again.
|
|
|
|
if (InstrNum == 0) {
|
|
|
|
TouchedInstructions.reset(InstrNum);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-04-07 02:52:58 +08:00
|
|
|
Value *V = InstrFromDFSNum(InstrNum);
|
2017-05-20 03:01:27 +08:00
|
|
|
const BasicBlock *CurrBlock = getBlockForValue(V);
|
2017-03-18 23:41:40 +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);
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Skipping instructions in block "
|
|
|
|
<< getBlockName(CurrBlock)
|
|
|
|
<< " because it is unreachable\n");
|
2017-03-18 23:41:40 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
updateProcessedCount(CurrBlock);
|
|
|
|
}
|
2017-06-07 01:15:28 +08:00
|
|
|
// Reset after processing (because we may mark ourselves as touched when
|
|
|
|
// we propagate equalities).
|
|
|
|
TouchedInstructions.reset(InstrNum);
|
2017-03-18 23:41:40 +08:00
|
|
|
|
|
|
|
if (auto *MP = dyn_cast<MemoryPhi>(V)) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Processing MemoryPhi " << *MP << "\n");
|
2017-03-18 23:41:40 +08:00
|
|
|
valueNumberMemoryPhi(MP);
|
|
|
|
} else if (auto *I = dyn_cast<Instruction>(V)) {
|
|
|
|
valueNumberInstruction(I);
|
|
|
|
} else {
|
|
|
|
llvm_unreachable("Should have been a MemoryPhi or Instruction");
|
|
|
|
}
|
|
|
|
updateProcessedCount(V);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NumGVNMaxIterations = std::max(NumGVNMaxIterations.getValue(), Iterations);
|
|
|
|
}
|
|
|
|
|
2016-12-27 04:06:58 +08:00
|
|
|
// This is the main transformation entry point.
|
2017-03-12 12:46:45 +08:00
|
|
|
bool NewGVN::runGVN() {
|
2017-03-18 23:41:40 +08:00
|
|
|
if (DebugCounter::isCounterSet(VNCounter))
|
|
|
|
StartingVNCounter = DebugCounter::getCounterValue(VNCounter);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
bool Changed = false;
|
2017-02-11 23:13:49 +08:00
|
|
|
NumFuncArgs = F.arg_size();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
MSSAWalker = MSSA->getWalker();
|
2017-05-20 04:22:20 +08:00
|
|
|
SingletonDeadExpression = new (ExpressionAllocator) DeadExpression();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Count number of instructions for sizing of hash tables, and come
|
|
|
|
// up with a global dfs numbering for instructions.
|
2016-12-30 06:15:12 +08:00
|
|
|
unsigned ICount = 1;
|
|
|
|
// Add an empty instruction to account for the fact that we start at 1
|
|
|
|
DFSToInstr.emplace_back(nullptr);
|
2017-02-19 07:06:50 +08:00
|
|
|
// Note: We want ideal RPO traversal of the blocks, which is not quite the
|
|
|
|
// same as dominator tree order, particularly with regard whether backedges
|
|
|
|
// get visited first or second, given a block with multiple successors.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// If we visit in the wrong order, we will end up performing N times as many
|
|
|
|
// iterations.
|
NewGVN: Sort Dominator Tree in RPO order, and use that for generating order.
Summary:
The optimal iteration order for this problem is RPO order. We want to
process as many preds of a backedge as we can before we process the
backedge.
At the same time, as we add predicate handling, we want to be able to
touch instructions that are dominated by a given block by
ranges (because a change in value numbering a predicate possibly
affects all users we dominate that are using that predicate).
If we don't do it this way, we can't do value inference over
backedges (the paper covers this in depth).
The newgvn branch currently overshoots the last part, and guarantees
that it will touch *at least* the right set of instructions, but it
does touch more. This is because the bitvector instruction ranges are
currently generated in RPO order (so we take the max and the min of
the ranges of dominated blocks, which means there are some in the
middle we didn't have to touch that we did).
We can do better by sorting the dominator tree, and then just using
dominator tree order.
As a preliminary, the dominator tree has some RPO guarantees, but not
enough. It guarantees that for a given node, your idom must come
before you in the RPO ordering. It guarantees no relative RPO ordering
for siblings. We add siblings in whatever order they appear in the module.
So that is what we fix.
We sort the children array of the domtree into RPO order, and then use
the dominator tree for ordering, instead of RPO, since the dominator
tree is now a valid RPO ordering.
Note: This would help any other pass that iterates a forward problem
in dominator tree order. Most of them are single pass. It will still
maximize whatever result they compute. We could also build the
dominator tree in this order, but our incremental updates would still
put it out of sort order, and recomputing the sort order is almost as
hard as general incremental updates of the domtree.
Also note that the sorting does not affect any tests, etc. Nothing
depends on domtree order, including the verifier, the equals
functions for domtree nodes, etc.
How much could this matter, you ask?
Here are the current numbers.
This is generated by running NewGVN over all files in LLVM.
Note that once we propagate equalities, the differences go up by an
order of magnitude or two (IE instead of 29, the max ends up in the
thousands, since the worst case we add a factor of N, where N is the
number of branch predicates). So while it doesn't look that stark for
the default ordering, it gets *much much* worse. There are also
programs in the wild where the difference is already pretty stark
(2 iterations vs hundreds).
RPO ordering:
759040 Number of iterations is 1
112908 Number of iterations is 2
Default dominator tree ordering:
755081 Number of iterations is 1
116234 Number of iterations is 2
603 Number of iterations is 3
27 Number of iterations is 4
2 Number of iterations is 5
1 Number of iterations is 7
Dominator tree sorted:
759040 Number of iterations is 1
112908 Number of iterations is 2
<yay!>
Really bad ordering (sort domtree siblings in postorder. not quite the
worst possible, but yeah):
754008 Number of iterations is 1
21 Number of iterations is 10
8 Number of iterations is 11
6 Number of iterations is 12
5 Number of iterations is 13
2 Number of iterations is 14
2 Number of iterations is 15
3 Number of iterations is 16
1 Number of iterations is 17
2 Number of iterations is 18
96642 Number of iterations is 2
1 Number of iterations is 20
2 Number of iterations is 21
1 Number of iterations is 22
1 Number of iterations is 29
17266 Number of iterations is 3
2598 Number of iterations is 4
798 Number of iterations is 5
273 Number of iterations is 6
186 Number of iterations is 7
80 Number of iterations is 8
42 Number of iterations is 9
Reviewers: chandlerc, davide
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D28129
llvm-svn: 290699
2016-12-29 09:12:36 +08:00
|
|
|
// The dominator tree does guarantee that, for a given dom tree node, it's
|
|
|
|
// parent must occur before it in the RPO ordering. Thus, we only need to sort
|
|
|
|
// the siblings.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
ReversePostOrderTraversal<Function *> RPOT(&F);
|
NewGVN: Sort Dominator Tree in RPO order, and use that for generating order.
Summary:
The optimal iteration order for this problem is RPO order. We want to
process as many preds of a backedge as we can before we process the
backedge.
At the same time, as we add predicate handling, we want to be able to
touch instructions that are dominated by a given block by
ranges (because a change in value numbering a predicate possibly
affects all users we dominate that are using that predicate).
If we don't do it this way, we can't do value inference over
backedges (the paper covers this in depth).
The newgvn branch currently overshoots the last part, and guarantees
that it will touch *at least* the right set of instructions, but it
does touch more. This is because the bitvector instruction ranges are
currently generated in RPO order (so we take the max and the min of
the ranges of dominated blocks, which means there are some in the
middle we didn't have to touch that we did).
We can do better by sorting the dominator tree, and then just using
dominator tree order.
As a preliminary, the dominator tree has some RPO guarantees, but not
enough. It guarantees that for a given node, your idom must come
before you in the RPO ordering. It guarantees no relative RPO ordering
for siblings. We add siblings in whatever order they appear in the module.
So that is what we fix.
We sort the children array of the domtree into RPO order, and then use
the dominator tree for ordering, instead of RPO, since the dominator
tree is now a valid RPO ordering.
Note: This would help any other pass that iterates a forward problem
in dominator tree order. Most of them are single pass. It will still
maximize whatever result they compute. We could also build the
dominator tree in this order, but our incremental updates would still
put it out of sort order, and recomputing the sort order is almost as
hard as general incremental updates of the domtree.
Also note that the sorting does not affect any tests, etc. Nothing
depends on domtree order, including the verifier, the equals
functions for domtree nodes, etc.
How much could this matter, you ask?
Here are the current numbers.
This is generated by running NewGVN over all files in LLVM.
Note that once we propagate equalities, the differences go up by an
order of magnitude or two (IE instead of 29, the max ends up in the
thousands, since the worst case we add a factor of N, where N is the
number of branch predicates). So while it doesn't look that stark for
the default ordering, it gets *much much* worse. There are also
programs in the wild where the difference is already pretty stark
(2 iterations vs hundreds).
RPO ordering:
759040 Number of iterations is 1
112908 Number of iterations is 2
Default dominator tree ordering:
755081 Number of iterations is 1
116234 Number of iterations is 2
603 Number of iterations is 3
27 Number of iterations is 4
2 Number of iterations is 5
1 Number of iterations is 7
Dominator tree sorted:
759040 Number of iterations is 1
112908 Number of iterations is 2
<yay!>
Really bad ordering (sort domtree siblings in postorder. not quite the
worst possible, but yeah):
754008 Number of iterations is 1
21 Number of iterations is 10
8 Number of iterations is 11
6 Number of iterations is 12
5 Number of iterations is 13
2 Number of iterations is 14
2 Number of iterations is 15
3 Number of iterations is 16
1 Number of iterations is 17
2 Number of iterations is 18
96642 Number of iterations is 2
1 Number of iterations is 20
2 Number of iterations is 21
1 Number of iterations is 22
1 Number of iterations is 29
17266 Number of iterations is 3
2598 Number of iterations is 4
798 Number of iterations is 5
273 Number of iterations is 6
186 Number of iterations is 7
80 Number of iterations is 8
42 Number of iterations is 9
Reviewers: chandlerc, davide
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D28129
llvm-svn: 290699
2016-12-29 09:12:36 +08:00
|
|
|
unsigned Counter = 0;
|
|
|
|
for (auto &B : RPOT) {
|
|
|
|
auto *Node = DT->getNode(B);
|
|
|
|
assert(Node && "RPO and Dominator tree should have same reachability");
|
|
|
|
RPOOrdering[Node] = ++Counter;
|
|
|
|
}
|
|
|
|
// Sort dominator tree children arrays into RPO.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
for (auto &B : RPOT) {
|
NewGVN: Sort Dominator Tree in RPO order, and use that for generating order.
Summary:
The optimal iteration order for this problem is RPO order. We want to
process as many preds of a backedge as we can before we process the
backedge.
At the same time, as we add predicate handling, we want to be able to
touch instructions that are dominated by a given block by
ranges (because a change in value numbering a predicate possibly
affects all users we dominate that are using that predicate).
If we don't do it this way, we can't do value inference over
backedges (the paper covers this in depth).
The newgvn branch currently overshoots the last part, and guarantees
that it will touch *at least* the right set of instructions, but it
does touch more. This is because the bitvector instruction ranges are
currently generated in RPO order (so we take the max and the min of
the ranges of dominated blocks, which means there are some in the
middle we didn't have to touch that we did).
We can do better by sorting the dominator tree, and then just using
dominator tree order.
As a preliminary, the dominator tree has some RPO guarantees, but not
enough. It guarantees that for a given node, your idom must come
before you in the RPO ordering. It guarantees no relative RPO ordering
for siblings. We add siblings in whatever order they appear in the module.
So that is what we fix.
We sort the children array of the domtree into RPO order, and then use
the dominator tree for ordering, instead of RPO, since the dominator
tree is now a valid RPO ordering.
Note: This would help any other pass that iterates a forward problem
in dominator tree order. Most of them are single pass. It will still
maximize whatever result they compute. We could also build the
dominator tree in this order, but our incremental updates would still
put it out of sort order, and recomputing the sort order is almost as
hard as general incremental updates of the domtree.
Also note that the sorting does not affect any tests, etc. Nothing
depends on domtree order, including the verifier, the equals
functions for domtree nodes, etc.
How much could this matter, you ask?
Here are the current numbers.
This is generated by running NewGVN over all files in LLVM.
Note that once we propagate equalities, the differences go up by an
order of magnitude or two (IE instead of 29, the max ends up in the
thousands, since the worst case we add a factor of N, where N is the
number of branch predicates). So while it doesn't look that stark for
the default ordering, it gets *much much* worse. There are also
programs in the wild where the difference is already pretty stark
(2 iterations vs hundreds).
RPO ordering:
759040 Number of iterations is 1
112908 Number of iterations is 2
Default dominator tree ordering:
755081 Number of iterations is 1
116234 Number of iterations is 2
603 Number of iterations is 3
27 Number of iterations is 4
2 Number of iterations is 5
1 Number of iterations is 7
Dominator tree sorted:
759040 Number of iterations is 1
112908 Number of iterations is 2
<yay!>
Really bad ordering (sort domtree siblings in postorder. not quite the
worst possible, but yeah):
754008 Number of iterations is 1
21 Number of iterations is 10
8 Number of iterations is 11
6 Number of iterations is 12
5 Number of iterations is 13
2 Number of iterations is 14
2 Number of iterations is 15
3 Number of iterations is 16
1 Number of iterations is 17
2 Number of iterations is 18
96642 Number of iterations is 2
1 Number of iterations is 20
2 Number of iterations is 21
1 Number of iterations is 22
1 Number of iterations is 29
17266 Number of iterations is 3
2598 Number of iterations is 4
798 Number of iterations is 5
273 Number of iterations is 6
186 Number of iterations is 7
80 Number of iterations is 8
42 Number of iterations is 9
Reviewers: chandlerc, davide
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D28129
llvm-svn: 290699
2016-12-29 09:12:36 +08:00
|
|
|
auto *Node = DT->getNode(B);
|
|
|
|
if (Node->getChildren().size() > 1)
|
2018-04-14 03:47:57 +08:00
|
|
|
llvm::sort(Node->begin(), Node->end(),
|
|
|
|
[&](const DomTreeNode *A, const DomTreeNode *B) {
|
|
|
|
return RPOOrdering[A] < RPOOrdering[B];
|
|
|
|
});
|
NewGVN: Sort Dominator Tree in RPO order, and use that for generating order.
Summary:
The optimal iteration order for this problem is RPO order. We want to
process as many preds of a backedge as we can before we process the
backedge.
At the same time, as we add predicate handling, we want to be able to
touch instructions that are dominated by a given block by
ranges (because a change in value numbering a predicate possibly
affects all users we dominate that are using that predicate).
If we don't do it this way, we can't do value inference over
backedges (the paper covers this in depth).
The newgvn branch currently overshoots the last part, and guarantees
that it will touch *at least* the right set of instructions, but it
does touch more. This is because the bitvector instruction ranges are
currently generated in RPO order (so we take the max and the min of
the ranges of dominated blocks, which means there are some in the
middle we didn't have to touch that we did).
We can do better by sorting the dominator tree, and then just using
dominator tree order.
As a preliminary, the dominator tree has some RPO guarantees, but not
enough. It guarantees that for a given node, your idom must come
before you in the RPO ordering. It guarantees no relative RPO ordering
for siblings. We add siblings in whatever order they appear in the module.
So that is what we fix.
We sort the children array of the domtree into RPO order, and then use
the dominator tree for ordering, instead of RPO, since the dominator
tree is now a valid RPO ordering.
Note: This would help any other pass that iterates a forward problem
in dominator tree order. Most of them are single pass. It will still
maximize whatever result they compute. We could also build the
dominator tree in this order, but our incremental updates would still
put it out of sort order, and recomputing the sort order is almost as
hard as general incremental updates of the domtree.
Also note that the sorting does not affect any tests, etc. Nothing
depends on domtree order, including the verifier, the equals
functions for domtree nodes, etc.
How much could this matter, you ask?
Here are the current numbers.
This is generated by running NewGVN over all files in LLVM.
Note that once we propagate equalities, the differences go up by an
order of magnitude or two (IE instead of 29, the max ends up in the
thousands, since the worst case we add a factor of N, where N is the
number of branch predicates). So while it doesn't look that stark for
the default ordering, it gets *much much* worse. There are also
programs in the wild where the difference is already pretty stark
(2 iterations vs hundreds).
RPO ordering:
759040 Number of iterations is 1
112908 Number of iterations is 2
Default dominator tree ordering:
755081 Number of iterations is 1
116234 Number of iterations is 2
603 Number of iterations is 3
27 Number of iterations is 4
2 Number of iterations is 5
1 Number of iterations is 7
Dominator tree sorted:
759040 Number of iterations is 1
112908 Number of iterations is 2
<yay!>
Really bad ordering (sort domtree siblings in postorder. not quite the
worst possible, but yeah):
754008 Number of iterations is 1
21 Number of iterations is 10
8 Number of iterations is 11
6 Number of iterations is 12
5 Number of iterations is 13
2 Number of iterations is 14
2 Number of iterations is 15
3 Number of iterations is 16
1 Number of iterations is 17
2 Number of iterations is 18
96642 Number of iterations is 2
1 Number of iterations is 20
2 Number of iterations is 21
1 Number of iterations is 22
1 Number of iterations is 29
17266 Number of iterations is 3
2598 Number of iterations is 4
798 Number of iterations is 5
273 Number of iterations is 6
186 Number of iterations is 7
80 Number of iterations is 8
42 Number of iterations is 9
Reviewers: chandlerc, davide
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D28129
llvm-svn: 290699
2016-12-29 09:12:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now a standard depth first ordering of the domtree is equivalent to RPO.
|
2017-04-19 01:06:11 +08:00
|
|
|
for (auto DTN : depth_first(DT->getRootNode())) {
|
|
|
|
BasicBlock *B = DTN->getBlock();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
const auto &BlockRange = assignDFSNumbers(B, ICount);
|
|
|
|
BlockInstRange.insert({B, BlockRange});
|
|
|
|
ICount += BlockRange.second - BlockRange.first;
|
|
|
|
}
|
2017-05-20 03:01:27 +08:00
|
|
|
initializeCongruenceClasses(F);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2016-12-30 06:15:12 +08:00
|
|
|
TouchedInstructions.resize(ICount);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Ensure we don't end up resizing the expressionToClass map, as
|
|
|
|
// that can be quite expensive. At most, we have one expression per
|
|
|
|
// instruction.
|
2016-12-30 06:15:12 +08:00
|
|
|
ExpressionToClass.reserve(ICount);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Initialize the touched instructions to include the entry block.
|
|
|
|
const auto &InstRange = BlockInstRange.lookup(&F.getEntryBlock());
|
|
|
|
TouchedInstructions.set(InstRange.first, InstRange.second);
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Block " << getBlockName(&F.getEntryBlock())
|
|
|
|
<< " marked reachable\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
|
|
|
ReachableBlocks.insert(&F.getEntryBlock());
|
|
|
|
|
2017-03-18 23:41:40 +08:00
|
|
|
iterateTouchedInstructions();
|
2017-01-03 02:00:46 +08:00
|
|
|
verifyMemoryCongruency();
|
2017-03-18 23:41:40 +08:00
|
|
|
verifyIterationSettled(F);
|
2017-05-17 03:58:47 +08:00
|
|
|
verifyStoreExpressions();
|
2017-02-19 07:06:50 +08:00
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
Changed |= eliminateInstructions(F);
|
|
|
|
|
|
|
|
// Delete all instructions marked for deletion.
|
|
|
|
for (Instruction *ToErase : InstructionsToErase) {
|
|
|
|
if (!ToErase->use_empty())
|
|
|
|
ToErase->replaceAllUsesWith(UndefValue::get(ToErase->getType()));
|
|
|
|
|
2018-09-07 19:41:34 +08:00
|
|
|
assert(ToErase->getParent() &&
|
|
|
|
"BB containing ToErase deleted unexpectedly!");
|
|
|
|
ToErase->eraseFromParent();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
2019-03-12 22:48:32 +08:00
|
|
|
Changed |= !InstructionsToErase.empty();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// 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)) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "We believe block " << getBlockName(&BB)
|
|
|
|
<< " 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct NewGVN::ValueDFS {
|
2016-12-29 03:17:17 +08:00
|
|
|
int DFSIn = 0;
|
|
|
|
int DFSOut = 0;
|
|
|
|
int LocalNum = 0;
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-03-10 08:32:26 +08:00
|
|
|
// Only one of Def and U will be set.
|
2017-04-01 17:44:33 +08:00
|
|
|
// The bool in the Def tells us whether the Def is the stored value of a
|
|
|
|
// store.
|
|
|
|
PointerIntPair<Value *, 1, bool> Def;
|
2016-12-29 03:17:17 +08:00
|
|
|
Use *U = nullptr;
|
2017-10-21 05:47: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
|
|
|
bool operator<(const ValueDFS &Other) const {
|
|
|
|
// It's not enough that any given field be less than - we have sets
|
|
|
|
// of fields that need to be evaluated together to give a proper ordering.
|
|
|
|
// For example, if you have;
|
|
|
|
// DFS (1, 3)
|
|
|
|
// Val 0
|
|
|
|
// DFS (1, 2)
|
|
|
|
// Val 50
|
|
|
|
// We want the second to be less than the first, but if we just go field
|
|
|
|
// by field, we will get to Val 0 < Val 50 and say the first is less than
|
|
|
|
// the second. We only want it to be less than if the DFS orders are equal.
|
|
|
|
//
|
|
|
|
// Each LLVM instruction only produces one value, and thus the lowest-level
|
|
|
|
// differentiator that really matters for the stack (and what we use as as a
|
|
|
|
// replacement) is the local dfs number.
|
2016-12-27 04:06:58 +08:00
|
|
|
// Everything else in the structure is instruction level, and only affects
|
|
|
|
// the order in which we will replace operands of a given instruction.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
//
|
|
|
|
// For a given instruction (IE things with equal dfsin, dfsout, localnum),
|
|
|
|
// the order of replacement of uses does not matter.
|
|
|
|
// IE given,
|
|
|
|
// a = 5
|
|
|
|
// b = a + a
|
2016-12-27 04:06:58 +08:00
|
|
|
// When you hit b, you will have two valuedfs with the same dfsin, out, and
|
|
|
|
// localnum.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// The .val will be the same as well.
|
|
|
|
// The .u's will be different.
|
2016-12-27 04:06:58 +08:00
|
|
|
// You will replace both, and it does not matter what order you replace them
|
|
|
|
// in (IE whether you replace operand 2, then operand 1, or operand 1, then
|
|
|
|
// operand 2).
|
|
|
|
// Similarly for the case of same dfsin, dfsout, localnum, but different
|
|
|
|
// .val's
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// a = 5
|
|
|
|
// b = 6
|
|
|
|
// c = a + b
|
2016-12-27 04:06:58 +08:00
|
|
|
// in c, we will a valuedfs for a, and one for b,with everything the same
|
|
|
|
// but .val and .u.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// It does not matter what order we replace these operands in.
|
|
|
|
// You will always end up with the same IR, and this is guaranteed.
|
2017-03-10 08:32:26 +08:00
|
|
|
return std::tie(DFSIn, DFSOut, LocalNum, Def, U) <
|
|
|
|
std::tie(Other.DFSIn, Other.DFSOut, Other.LocalNum, Other.Def,
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
Other.U);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-01-27 10:37:11 +08:00
|
|
|
// This function converts the set of members for a congruence class from values,
|
2017-03-10 08:32:26 +08:00
|
|
|
// to sets of defs and uses with associated DFS info. The total number of
|
2017-03-10 08:32:33 +08:00
|
|
|
// reachable uses for each value is stored in UseCount, and instructions that
|
|
|
|
// seem
|
|
|
|
// dead (have no non-dead uses) are stored in ProbablyDead.
|
|
|
|
void NewGVN::convertClassToDFSOrdered(
|
2017-04-08 02:38:09 +08:00
|
|
|
const CongruenceClass &Dense, SmallVectorImpl<ValueDFS> &DFSOrderedSet,
|
2017-03-10 08:32:33 +08:00
|
|
|
DenseMap<const Value *, unsigned int> &UseCounts,
|
2017-04-08 02:38:09 +08:00
|
|
|
SmallPtrSetImpl<Instruction *> &ProbablyDead) const {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
for (auto D : Dense) {
|
|
|
|
// First add the value.
|
|
|
|
BasicBlock *BB = getBlockForValue(D);
|
|
|
|
// Constants are handled prior to ever calling this function, so
|
|
|
|
// we should only be left with instructions as members.
|
2016-12-23 09:38:06 +08:00
|
|
|
assert(BB && "Should have figured out a basic block for value");
|
2017-03-10 08:32:26 +08:00
|
|
|
ValueDFS VDDef;
|
2017-01-14 08:24:23 +08:00
|
|
|
DomTreeNode *DomNode = DT->getNode(BB);
|
2017-03-10 08:32:26 +08:00
|
|
|
VDDef.DFSIn = DomNode->getDFSNumIn();
|
|
|
|
VDDef.DFSOut = DomNode->getDFSNumOut();
|
2017-04-01 17:44:33 +08:00
|
|
|
// If it's a store, use the leader of the value operand, if it's always
|
|
|
|
// available, or the value operand. TODO: We could do dominance checks to
|
|
|
|
// find a dominating leader, but not worth it ATM.
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
if (auto *SI = dyn_cast<StoreInst>(D)) {
|
2017-02-01 06:31:56 +08:00
|
|
|
auto Leader = lookupOperandLeader(SI->getValueOperand());
|
2017-04-01 17:44:33 +08:00
|
|
|
if (alwaysAvailable(Leader)) {
|
|
|
|
VDDef.Def.setPointer(Leader);
|
|
|
|
} else {
|
|
|
|
VDDef.Def.setPointer(SI->getValueOperand());
|
|
|
|
VDDef.Def.setInt(true);
|
|
|
|
}
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
} else {
|
2017-04-01 17:44:33 +08:00
|
|
|
VDDef.Def.setPointer(D);
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
}
|
2017-03-10 08:32:26 +08:00
|
|
|
assert(isa<Instruction>(D) &&
|
|
|
|
"The dense set member should always be an instruction");
|
2017-03-10 08:32:33 +08:00
|
|
|
Instruction *Def = cast<Instruction>(D);
|
2017-05-20 03:01:27 +08:00
|
|
|
VDDef.LocalNum = InstrToDFSNum(D);
|
|
|
|
DFSOrderedSet.push_back(VDDef);
|
|
|
|
// If there is a phi node equivalent, add it
|
|
|
|
if (auto *PN = RealToTemp.lookup(Def)) {
|
|
|
|
auto *PHIE =
|
|
|
|
dyn_cast_or_null<PHIExpression>(ValueToExpression.lookup(Def));
|
|
|
|
if (PHIE) {
|
|
|
|
VDDef.Def.setInt(false);
|
|
|
|
VDDef.Def.setPointer(PN);
|
|
|
|
VDDef.LocalNum = 0;
|
|
|
|
DFSOrderedSet.push_back(VDDef);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-10 08:32:33 +08:00
|
|
|
unsigned int UseCount = 0;
|
2017-01-14 08:24:23 +08:00
|
|
|
// Now add the uses.
|
2017-03-10 08:32:33 +08:00
|
|
|
for (auto &U : Def->uses()) {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (auto *I = dyn_cast<Instruction>(U.getUser())) {
|
2017-03-10 08:32:33 +08:00
|
|
|
// Don't try to replace into dead uses
|
|
|
|
if (InstructionsToErase.count(I))
|
|
|
|
continue;
|
2017-03-10 08:32:26 +08:00
|
|
|
ValueDFS VDUse;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Put the phi node uses in the incoming block.
|
|
|
|
BasicBlock *IBlock;
|
|
|
|
if (auto *P = dyn_cast<PHINode>(I)) {
|
|
|
|
IBlock = P->getIncomingBlock(U);
|
|
|
|
// Make phi node users appear last in the incoming block
|
|
|
|
// they are from.
|
2017-03-10 08:32:26 +08:00
|
|
|
VDUse.LocalNum = InstrDFS.size() + 1;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
} else {
|
2017-05-20 03:01:27 +08:00
|
|
|
IBlock = getBlockForValue(I);
|
2017-04-07 02:52:58 +08:00
|
|
|
VDUse.LocalNum = InstrToDFSNum(I);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
2017-01-26 08:42:42 +08:00
|
|
|
|
|
|
|
// Skip uses in unreachable blocks, as we're going
|
|
|
|
// to delete them.
|
|
|
|
if (ReachableBlocks.count(IBlock) == 0)
|
|
|
|
continue;
|
|
|
|
|
2017-01-14 08:24:23 +08:00
|
|
|
DomTreeNode *DomNode = DT->getNode(IBlock);
|
2017-03-10 08:32:26 +08:00
|
|
|
VDUse.DFSIn = DomNode->getDFSNumIn();
|
|
|
|
VDUse.DFSOut = DomNode->getDFSNumOut();
|
|
|
|
VDUse.U = &U;
|
2017-03-10 08:32:33 +08:00
|
|
|
++UseCount;
|
2017-03-10 08:32:26 +08:00
|
|
|
DFSOrderedSet.emplace_back(VDUse);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
2017-03-10 08:32:33 +08:00
|
|
|
|
|
|
|
// If there are no uses, it's probably dead (but it may have side-effects,
|
|
|
|
// so not definitely dead. Otherwise, store the number of uses so we can
|
|
|
|
// track if it becomes dead later).
|
|
|
|
if (UseCount == 0)
|
|
|
|
ProbablyDead.insert(Def);
|
|
|
|
else
|
|
|
|
UseCounts[Def] = UseCount;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-27 10:37:11 +08:00
|
|
|
// This function converts the set of members for a congruence class from values,
|
|
|
|
// to the set of defs for loads and stores, with associated DFS info.
|
2017-03-10 08:32:33 +08:00
|
|
|
void NewGVN::convertClassToLoadsAndStores(
|
2017-04-08 02:38:09 +08:00
|
|
|
const CongruenceClass &Dense,
|
|
|
|
SmallVectorImpl<ValueDFS> &LoadsAndStores) const {
|
2017-01-27 10:37:11 +08:00
|
|
|
for (auto D : Dense) {
|
|
|
|
if (!isa<LoadInst>(D) && !isa<StoreInst>(D))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
BasicBlock *BB = getBlockForValue(D);
|
|
|
|
ValueDFS VD;
|
|
|
|
DomTreeNode *DomNode = DT->getNode(BB);
|
|
|
|
VD.DFSIn = DomNode->getDFSNumIn();
|
|
|
|
VD.DFSOut = DomNode->getDFSNumOut();
|
2017-04-01 17:44:33 +08:00
|
|
|
VD.Def.setPointer(D);
|
2017-01-27 10:37:11 +08:00
|
|
|
|
|
|
|
// If it's an instruction, use the real local dfs number.
|
|
|
|
if (auto *I = dyn_cast<Instruction>(D))
|
2017-04-07 02:52:58 +08:00
|
|
|
VD.LocalNum = InstrToDFSNum(I);
|
2017-01-27 10:37:11 +08:00
|
|
|
else
|
|
|
|
llvm_unreachable("Should have been an instruction");
|
|
|
|
|
|
|
|
LoadsAndStores.emplace_back(VD);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
static void patchAndReplaceAllUsesWith(Instruction *I, Value *Repl) {
|
|
|
|
patchReplacementInstruction(I, Repl);
|
|
|
|
I->replaceAllUsesWith(Repl);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NewGVN::deleteInstructionsInBlock(BasicBlock *BB) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << " BasicBlock Dead:" << *BB);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
++NumGVNBlocksDeleted;
|
|
|
|
|
2017-01-31 01:06:55 +08:00
|
|
|
// Delete the instructions backwards, as it has a reduced likelihood of having
|
|
|
|
// to update as many def-use and use-def chains. Start after the terminator.
|
|
|
|
auto StartPoint = BB->rbegin();
|
|
|
|
++StartPoint;
|
|
|
|
// Note that we explicitly recalculate BB->rend() on each iteration,
|
|
|
|
// as it may change when we remove the first instruction.
|
|
|
|
for (BasicBlock::reverse_iterator I(StartPoint); I != BB->rend();) {
|
|
|
|
Instruction &Inst = *I++;
|
|
|
|
if (!Inst.use_empty())
|
|
|
|
Inst.replaceAllUsesWith(UndefValue::get(Inst.getType()));
|
|
|
|
if (isa<LandingPadInst>(Inst))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
Inst.eraseFromParent();
|
|
|
|
++NumGVNInstrDeleted;
|
|
|
|
}
|
2017-01-31 02:12:56 +08:00
|
|
|
// Now insert something that simplifycfg will turn into an unreachable.
|
|
|
|
Type *Int8Ty = Type::getInt8Ty(BB->getContext());
|
|
|
|
new StoreInst(UndefValue::get(Int8Ty),
|
|
|
|
Constant::getNullValue(Int8Ty->getPointerTo()),
|
|
|
|
BB->getTerminator());
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void NewGVN::markInstructionForDeletion(Instruction *I) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Marking " << *I << " for deletion\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
|
|
|
InstructionsToErase.insert(I);
|
|
|
|
}
|
|
|
|
|
|
|
|
void NewGVN::replaceInstruction(Instruction *I, Value *V) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Replacing " << *I << " with " << *V << "\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
|
|
|
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);
|
|
|
|
}
|
2017-10-21 05:47: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
|
|
|
bool empty() const { return DFSStack.empty(); }
|
2017-10-21 05:47: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
|
|
|
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-10-21 05:47:29 +08:00
|
|
|
|
|
|
|
} // end anonymous namespace
|
2017-01-07 11:23:47 +08:00
|
|
|
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
// Given an expression, get the congruence class for it.
|
|
|
|
CongruenceClass *NewGVN::getClassForExpression(const Expression *E) const {
|
|
|
|
if (auto *VE = dyn_cast<VariableExpression>(E))
|
|
|
|
return ValueToClass.lookup(VE->getVariableValue());
|
|
|
|
else if (isa<DeadExpression>(E))
|
|
|
|
return TOPClass;
|
|
|
|
return ExpressionToClass.lookup(E);
|
|
|
|
}
|
|
|
|
|
2017-05-20 03:01:27 +08:00
|
|
|
// Given a value and a basic block we are trying to see if it is available in,
|
|
|
|
// see if the value has a leader available in that block.
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
Value *NewGVN::findPHIOfOpsLeader(const Expression *E,
|
2017-09-05 10:17:40 +08:00
|
|
|
const Instruction *OrigInst,
|
2017-05-20 03:01:27 +08:00
|
|
|
const BasicBlock *BB) const {
|
|
|
|
// It would already be constant if we could make it constant
|
|
|
|
if (auto *CE = dyn_cast<ConstantExpression>(E))
|
|
|
|
return CE->getConstantValue();
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
if (auto *VE = dyn_cast<VariableExpression>(E)) {
|
|
|
|
auto *V = VE->getVariableValue();
|
|
|
|
if (alwaysAvailable(V) || DT->dominates(getBlockForValue(V), BB))
|
|
|
|
return VE->getVariableValue();
|
|
|
|
}
|
2017-05-20 03:01:27 +08:00
|
|
|
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
auto *CC = getClassForExpression(E);
|
2017-05-20 03:01:27 +08:00
|
|
|
if (!CC)
|
|
|
|
return nullptr;
|
|
|
|
if (alwaysAvailable(CC->getLeader()))
|
|
|
|
return CC->getLeader();
|
|
|
|
|
|
|
|
for (auto Member : *CC) {
|
|
|
|
auto *MemberInst = dyn_cast<Instruction>(Member);
|
2017-09-05 10:17:40 +08:00
|
|
|
if (MemberInst == OrigInst)
|
|
|
|
continue;
|
2017-05-20 03:01:27 +08:00
|
|
|
// Anything that isn't an instruction is always available.
|
|
|
|
if (!MemberInst)
|
|
|
|
return Member;
|
Fix PR/33305. caused by trying to simplify expressions in phi of ops that should have no leaders.
Summary:
After a discussion with Rekka, i believe this (or a small variant)
should fix the remaining phi-of-ops problems.
Rekka's algorithm for completeness relies on looking up expressions
that should have no leader, and expecting it to fail (IE looking up
expressions that can't exist in a predecessor, and expecting it to
find nothing).
Unfortunately, sometimes these expressions can be simplified to
constants, but we need the lookup to fail anyway. Additionally, our
simplifier outsmarts this by taking these "not quite right"
expressions, and simplifying them into other expressions or walking
through phis, etc. In the past, we've sometimes been able to find
leaders for these expressions, incorrectly.
This change causes us to not to try to phi of ops such expressions.
We determine safety by seeing if they depend on a phi node in our
block.
This is not perfect, we can do a bit better, but this should be a
"correctness start" that we can then improve. It also requires a
bunch of caching that i'll eventually like to eliminate.
The right solution, longer term, to the simplifier issues, is to make
the query interface for the instruction simplifier/constant folder
have the flags we need, so that we can keep most things going, but
turn off the possibly-invalid parts (threading through phis, etc).
This is an issue in another wrong code bug as well.
Reviewers: davide, mcrosier
Subscribers: sanjoy, llvm-commits
Differential Revision: https://reviews.llvm.org/D37175
llvm-svn: 312401
2017-09-02 10:18:44 +08:00
|
|
|
if (DT->dominates(getBlockForValue(MemberInst), BB))
|
2017-05-20 03:01:27 +08:00
|
|
|
return Member;
|
|
|
|
}
|
|
|
|
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
|
|
|
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();
|
|
|
|
|
2017-05-22 07:41:56 +08:00
|
|
|
// Go through all of our phi nodes, and kill the arguments associated with
|
|
|
|
// unreachable edges.
|
2017-10-01 07:51:53 +08:00
|
|
|
auto ReplaceUnreachablePHIArgs = [&](PHINode *PHI, BasicBlock *BB) {
|
|
|
|
for (auto &Operand : PHI->incoming_values())
|
|
|
|
if (!ReachableEdges.count({PHI->getIncomingBlock(Operand), BB})) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Replacing incoming value of " << PHI
|
|
|
|
<< " for block "
|
|
|
|
<< getBlockName(PHI->getIncomingBlock(Operand))
|
|
|
|
<< " with undef due to it being unreachable\n");
|
2017-10-01 07:51:53 +08:00
|
|
|
Operand.set(UndefValue::get(PHI->getType()));
|
2017-05-20 03:01:27 +08:00
|
|
|
}
|
|
|
|
};
|
2017-10-01 07:51:53 +08:00
|
|
|
// Replace unreachable phi arguments.
|
|
|
|
// At this point, RevisitOnReachabilityChange only contains:
|
|
|
|
//
|
|
|
|
// 1. PHIs
|
|
|
|
// 2. Temporaries that will convert to PHIs
|
|
|
|
// 3. Operations that are affected by an unreachable edge but do not fit into
|
|
|
|
// 1 or 2 (rare).
|
|
|
|
// So it is a slight overshoot of what we want. We could make it exact by
|
|
|
|
// using two SparseBitVectors per block.
|
2017-05-20 03:01:27 +08:00
|
|
|
DenseMap<const BasicBlock *, unsigned> ReachablePredCount;
|
2017-10-01 07:51:53 +08:00
|
|
|
for (auto &KV : ReachableEdges)
|
2017-05-20 03:01:27 +08:00
|
|
|
ReachablePredCount[KV.getEnd()]++;
|
2017-10-01 07:51:53 +08:00
|
|
|
for (auto &BBPair : RevisitOnReachabilityChange) {
|
|
|
|
for (auto InstNum : BBPair.second) {
|
|
|
|
auto *Inst = InstrFromDFSNum(InstNum);
|
|
|
|
auto *PHI = dyn_cast<PHINode>(Inst);
|
|
|
|
PHI = PHI ? PHI : dyn_cast_or_null<PHINode>(RealToTemp.lookup(Inst));
|
|
|
|
if (!PHI)
|
|
|
|
continue;
|
|
|
|
auto *BB = BBPair.first;
|
|
|
|
if (ReachablePredCount.lookup(BB) != PHI->getNumIncomingValues())
|
2017-05-20 03:01:27 +08:00
|
|
|
ReplaceUnreachablePHIArgs(PHI, BB);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested 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-10-01 07:51:53 +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
|
|
|
|
2017-03-10 08:32:33 +08:00
|
|
|
// Map to store the use counts
|
|
|
|
DenseMap<const Value *, unsigned int> UseCounts;
|
2017-05-20 03:01:27 +08:00
|
|
|
for (auto *CC : reverse(CongruenceClasses)) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Eliminating in congruence class " << CC->getID()
|
|
|
|
<< "\n");
|
2017-01-27 10:37:11 +08:00
|
|
|
// Track the equivalent store info so we can decide whether to try
|
|
|
|
// dead store elimination.
|
|
|
|
SmallVector<ValueDFS, 8> PossibleDeadStores;
|
2017-03-10 08:32:33 +08:00
|
|
|
SmallPtrSet<Instruction *, 8> ProbablyDead;
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC->isDead() || CC->empty())
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
continue;
|
2017-03-11 03:05:04 +08:00
|
|
|
// Everything still in the TOP class is unreachable or dead.
|
|
|
|
if (CC == TOPClass) {
|
2017-05-20 04:22:20 +08:00
|
|
|
for (auto M : *CC) {
|
|
|
|
auto *VTE = ValueToExpression.lookup(M);
|
|
|
|
if (VTE && isa<DeadExpression>(VTE))
|
|
|
|
markInstructionForDeletion(cast<Instruction>(M));
|
2017-02-11 20:48:50 +08:00
|
|
|
assert((!ReachableBlocks.count(cast<Instruction>(M)->getParent()) ||
|
|
|
|
InstructionsToErase.count(cast<Instruction>(M))) &&
|
2017-03-11 03:05:04 +08:00
|
|
|
"Everything in TOP should be unreachable or dead at this "
|
2017-02-11 20:48:50 +08:00
|
|
|
"point");
|
2017-05-20 04:22:20 +08:00
|
|
|
}
|
2017-02-11 20:48:50 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-04-08 02:38:09 +08:00
|
|
|
assert(CC->getLeader() && "We should have had a leader");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// If this is a leader that is always available, and it's a
|
|
|
|
// constant or has no equivalences, just replace everything with
|
|
|
|
// it. We then update the congruence class with whatever members
|
|
|
|
// are left.
|
2017-04-08 02:38:09 +08:00
|
|
|
Value *Leader =
|
|
|
|
CC->getStoredValue() ? CC->getStoredValue() : CC->getLeader();
|
NewGVN: Fix PR 31686 and PR 31698 by rewriting store leader handling.
Summary:
This rewrites store expression/leader handling. We no longer use the
value operand as the leader, instead, we store it separately. We also
now store the stored value as part of the expression, and compare it
when comparing stores for equality. This enables us to get rid of a
bunch of our previous hacks and machinations, as the existing
machinery takes care of everything *except* updating the stored value
on classes. The only time we have to update it is if the storecount
goes to 0, and when we do, we destroy it.
Since we no longer use the value operand as the leader, during elimination, we have to use the value operand. Doing this also fixes a bunch of store forwarding cases we were missing.
Any value operand we use is guaranteed to either be updated by previous eliminations, or minimized by future ones.
(IE the fact that we don't use the most dominating value operand when it's not a constant does not affect anything).
Sadly, this change also exposes that we didn't pay attention to the
output of the pr31594.ll test, as it also very clearly exposes the
same store leader bug we are fixing here.
(I added pr31682.ll anyway, but maybe we think that's too large to be useful)
On the plus side, propagate-ir-flags.ll now passes due to the
corrected store forwarding.
This change was 3 stage'd on darwin and linux, with the full test-suite.
Reviewers:
davide
Subscribers:
llvm-commits
llvm-svn: 292648
2017-01-21 05:04:30 +08:00
|
|
|
if (alwaysAvailable(Leader)) {
|
2017-04-07 02:52:55 +08:00
|
|
|
CongruenceClass::MemberSet MembersLeft;
|
2017-04-08 02:38:09 +08:00
|
|
|
for (auto M : *CC) {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
Value *Member = M;
|
|
|
|
// Void things have no uses we can replace.
|
2017-04-07 02:52:55 +08:00
|
|
|
if (Member == Leader || !isa<Instruction>(Member) ||
|
|
|
|
Member->getType()->isVoidTy()) {
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
MembersLeft.insert(Member);
|
|
|
|
continue;
|
|
|
|
}
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Found replacement " << *(Leader) << " for "
|
|
|
|
<< *Member << "\n");
|
2017-04-07 02:52:55 +08:00
|
|
|
auto *I = cast<Instruction>(Member);
|
|
|
|
assert(Leader != I && "About to accidentally remove our leader");
|
|
|
|
replaceInstruction(I, Leader);
|
|
|
|
AnythingReplaced = true;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
2017-04-08 02:38:09 +08:00
|
|
|
CC->swap(MembersLeft);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
} else {
|
|
|
|
// If this is a singleton, we can skip it.
|
2017-08-04 05:17:49 +08:00
|
|
|
if (CC->size() != 1 || RealToTemp.count(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
|
|
|
// This is a stack because equality replacement/etc may place
|
|
|
|
// constants in the middle of the member list, and we want to use
|
|
|
|
// those constant values in preference to the current leader, over
|
|
|
|
// the scope of those constants.
|
|
|
|
ValueDFSStack EliminationStack;
|
|
|
|
|
|
|
|
// Convert the members to DFS ordered sets and then merge them.
|
2017-01-09 13:34:19 +08:00
|
|
|
SmallVector<ValueDFS, 8> DFSOrderedSet;
|
2017-04-08 02:38:09 +08:00
|
|
|
convertClassToDFSOrdered(*CC, DFSOrderedSet, UseCounts, ProbablyDead);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// Sort the whole thing.
|
llvm::sort(C.begin(), C.end(), ...) -> llvm::sort(C, ...)
Summary: The convenience wrapper in STLExtras is available since rL342102.
Reviewers: dblaikie, javed.absar, JDevlieghere, andreadb
Subscribers: MatzeB, sanjoy, arsenm, dschuff, mehdi_amini, sdardis, nemanjai, jvesely, nhaehnle, sbc100, jgravelle-google, eraman, aheejin, kbarton, JDevlieghere, javed.absar, gbedwell, jrtc27, mgrang, atanasyan, steven_wu, george.burgess.iv, dexonsmith, kristina, jsji, llvm-commits
Differential Revision: https://reviews.llvm.org/D52573
llvm-svn: 343163
2018-09-27 10:13:45 +08:00
|
|
|
llvm::sort(DFSOrderedSet);
|
2017-01-09 13:34:19 +08:00
|
|
|
for (auto &VD : DFSOrderedSet) {
|
|
|
|
int MemberDFSIn = VD.DFSIn;
|
|
|
|
int MemberDFSOut = VD.DFSOut;
|
2017-04-01 17:44:33 +08:00
|
|
|
Value *Def = VD.Def.getPointer();
|
|
|
|
bool FromStore = VD.Def.getInt();
|
2017-03-10 08:32:33 +08:00
|
|
|
Use *U = VD.U;
|
2017-01-27 10:37:11 +08:00
|
|
|
// We ignore void things because we can't get a value from them.
|
2017-03-10 08:32:33 +08:00
|
|
|
if (Def && Def->getType()->isVoidTy())
|
2017-01-27 10:37:11 +08:00
|
|
|
continue;
|
2017-05-20 03:01:27 +08:00
|
|
|
auto *DefInst = dyn_cast_or_null<Instruction>(Def);
|
|
|
|
if (DefInst && AllTempInstructions.count(DefInst)) {
|
|
|
|
auto *PN = cast<PHINode>(DefInst);
|
|
|
|
|
|
|
|
// If this is a value phi and that's the expression we used, insert
|
|
|
|
// it into the program
|
|
|
|
// remove from temp instruction list.
|
|
|
|
AllTempInstructions.erase(PN);
|
|
|
|
auto *DefBlock = getBlockForValue(Def);
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Inserting fully real phi of ops" << *Def
|
|
|
|
<< " into block "
|
|
|
|
<< getBlockName(getBlockForValue(Def)) << "\n");
|
2017-05-20 03:01:27 +08:00
|
|
|
PN->insertBefore(&DefBlock->front());
|
|
|
|
Def = PN;
|
|
|
|
NumGVNPHIOfOpsEliminations++;
|
|
|
|
}
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested 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()) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Elimination Stack is empty\n");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
} else {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Elimination Stack Top DFS numbers are ("
|
|
|
|
<< EliminationStack.dfs_back().first << ","
|
|
|
|
<< EliminationStack.dfs_back().second << ")\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
|
|
|
}
|
|
|
|
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Current DFS numbers are (" << MemberDFSIn << ","
|
|
|
|
<< MemberDFSOut << ")\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
|
|
|
// First, we see if we are out of scope or empty. If so,
|
|
|
|
// and there equivalences, we try to replace the top of
|
|
|
|
// stack with equivalences (if it's on the stack, it must
|
|
|
|
// not have been eliminated yet).
|
|
|
|
// Then we synchronize to our current scope, by
|
|
|
|
// popping until we are back within a DFS scope that
|
|
|
|
// dominates the current member.
|
|
|
|
// Then, what happens depends on a few factors
|
|
|
|
// If the stack is now empty, we need to push
|
|
|
|
// If we have a constant or a local equivalence we want to
|
|
|
|
// start using, we also push.
|
|
|
|
// Otherwise, we walk along, processing members who are
|
|
|
|
// dominated by this scope, and eliminate them.
|
2017-03-10 08:32:33 +08:00
|
|
|
bool ShouldPush = Def && EliminationStack.empty();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
bool OutOfScope =
|
|
|
|
!EliminationStack.isInScope(MemberDFSIn, MemberDFSOut);
|
|
|
|
|
|
|
|
if (OutOfScope || ShouldPush) {
|
|
|
|
// Sync to our current scope.
|
|
|
|
EliminationStack.popUntilDFSScope(MemberDFSIn, MemberDFSOut);
|
2017-03-10 08:32:33 +08:00
|
|
|
bool ShouldPush = Def && EliminationStack.empty();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (ShouldPush) {
|
2017-03-10 08:32:33 +08:00
|
|
|
EliminationStack.push_back(Def, MemberDFSIn, MemberDFSOut);
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-10 08:32:33 +08:00
|
|
|
// Skip the Def's, we only want to eliminate on their uses. But mark
|
|
|
|
// dominated defs as dead.
|
|
|
|
if (Def) {
|
|
|
|
// For anything in this case, what and how we value number
|
|
|
|
// guarantees that any side-effets that would have occurred (ie
|
|
|
|
// throwing, etc) can be proven to either still occur (because it's
|
|
|
|
// dominated by something that has the same side-effects), or never
|
|
|
|
// occur. Otherwise, we would not have been able to prove it value
|
|
|
|
// equivalent to something else. For these things, we can just mark
|
|
|
|
// it all dead. Note that this is different from the "ProbablyDead"
|
|
|
|
// set, which may not be dominated by anything, and thus, are only
|
2017-04-01 17:44:33 +08:00
|
|
|
// easy to prove dead if they are also side-effect free. Note that
|
|
|
|
// because stores are put in terms of the stored value, we skip
|
|
|
|
// stored values here. If the stored value is really dead, it will
|
|
|
|
// still be marked for deletion when we process it in its own class.
|
2017-03-10 08:32:33 +08:00
|
|
|
if (!EliminationStack.empty() && Def != EliminationStack.back() &&
|
2017-04-01 17:44:33 +08:00
|
|
|
isa<Instruction>(Def) && !FromStore)
|
2017-03-10 08:32:33 +08:00
|
|
|
markInstructionForDeletion(cast<Instruction>(Def));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// At this point, we know it is a Use we are trying to possibly
|
|
|
|
// replace.
|
|
|
|
|
|
|
|
assert(isa<Instruction>(U->get()) &&
|
|
|
|
"Current def should have been an instruction");
|
|
|
|
assert(isa<Instruction>(U->getUser()) &&
|
|
|
|
"Current user should have been an instruction");
|
|
|
|
|
|
|
|
// If the thing we are replacing into is already marked to be dead,
|
|
|
|
// this use is dead. Note that this is true regardless of whether
|
|
|
|
// we have anything dominating the use or not. We do this here
|
|
|
|
// because we are already walking all the uses anyway.
|
|
|
|
Instruction *InstUse = cast<Instruction>(U->getUser());
|
|
|
|
if (InstructionsToErase.count(InstUse)) {
|
|
|
|
auto &UseCount = UseCounts[U->get()];
|
|
|
|
if (--UseCount == 0) {
|
|
|
|
ProbablyDead.insert(cast<Instruction>(U->get()));
|
|
|
|
}
|
2017-03-10 08:32:26 +08:00
|
|
|
}
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// If we get to this point, and the stack is empty we must have a use
|
2017-03-10 08:32:33 +08:00
|
|
|
// with nothing we can use to eliminate this use, so just skip it.
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
if (EliminationStack.empty())
|
|
|
|
continue;
|
|
|
|
|
2017-03-10 08:32:26 +08:00
|
|
|
Value *DominatingLeader = EliminationStack.back();
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
2017-05-19 05:43:23 +08:00
|
|
|
auto *II = dyn_cast<IntrinsicInst>(DominatingLeader);
|
2018-01-10 04:12:42 +08:00
|
|
|
bool isSSACopy = II && II->getIntrinsicID() == Intrinsic::ssa_copy;
|
|
|
|
if (isSSACopy)
|
2017-05-19 05:43:23 +08:00
|
|
|
DominatingLeader = II->getOperand(0);
|
|
|
|
|
2017-01-07 08:01:42 +08:00
|
|
|
// Don't replace our existing users with ourselves.
|
2017-03-10 08:32:33 +08:00
|
|
|
if (U->get() == DominatingLeader)
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
continue;
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs()
|
|
|
|
<< "Found replacement " << *DominatingLeader << " for "
|
|
|
|
<< *U->get() << " in " << *(U->getUser()) << "\n");
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
|
|
|
|
// If we replaced something in an instruction, handle the patching of
|
2017-03-10 08:32:33 +08:00
|
|
|
// metadata. Skip this if we are replacing predicateinfo with its
|
|
|
|
// original operand, as we already know we can just drop it.
|
|
|
|
auto *ReplacedInst = cast<Instruction>(U->get());
|
2017-03-10 08:32:26 +08:00
|
|
|
auto *PI = PredInfo->getPredicateInfoFor(ReplacedInst);
|
|
|
|
if (!PI || DominatingLeader != PI->OriginalOp)
|
|
|
|
patchReplacementInstruction(ReplacedInst, DominatingLeader);
|
2017-03-10 08:32:33 +08:00
|
|
|
U->set(DominatingLeader);
|
|
|
|
// This is now a use of the dominating leader, which means if the
|
|
|
|
// dominating leader was dead, it's now live!
|
|
|
|
auto &LeaderUseCount = UseCounts[DominatingLeader];
|
|
|
|
// It's about to be alive again.
|
|
|
|
if (LeaderUseCount == 0 && isa<Instruction>(DominatingLeader))
|
|
|
|
ProbablyDead.erase(cast<Instruction>(DominatingLeader));
|
2018-12-15 08:32:38 +08:00
|
|
|
// For copy instructions, we use their operand as a leader,
|
|
|
|
// which means we remove a user of the copy and it may become dead.
|
|
|
|
if (isSSACopy) {
|
|
|
|
unsigned &IIUseCount = UseCounts[II];
|
|
|
|
if (--IIUseCount == 0)
|
|
|
|
ProbablyDead.insert(II);
|
|
|
|
}
|
2017-03-10 08:32:33 +08:00
|
|
|
++LeaderUseCount;
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
AnythingReplaced = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-10 08:32:33 +08:00
|
|
|
// At this point, anything still in the ProbablyDead set is actually dead if
|
|
|
|
// would be trivially dead.
|
|
|
|
for (auto *I : ProbablyDead)
|
|
|
|
if (wouldInstructionBeTriviallyDead(I))
|
|
|
|
markInstructionForDeletion(I);
|
|
|
|
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
// Cleanup the congruence class.
|
2017-04-07 02:52:55 +08:00
|
|
|
CongruenceClass::MemberSet MembersLeft;
|
2017-04-08 02:38:09 +08:00
|
|
|
for (auto *Member : *CC)
|
2017-04-07 02:52:55 +08:00
|
|
|
if (!isa<Instruction>(Member) ||
|
|
|
|
!InstructionsToErase.count(cast<Instruction>(Member)))
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
MembersLeft.insert(Member);
|
2017-04-08 02:38:09 +08:00
|
|
|
CC->swap(MembersLeft);
|
2017-01-27 10:37:11 +08:00
|
|
|
|
|
|
|
// If we have possible dead stores to look at, try to eliminate them.
|
2017-04-08 02:38:09 +08:00
|
|
|
if (CC->getStoreCount() > 0) {
|
|
|
|
convertClassToLoadsAndStores(*CC, PossibleDeadStores);
|
llvm::sort(C.begin(), C.end(), ...) -> llvm::sort(C, ...)
Summary: The convenience wrapper in STLExtras is available since rL342102.
Reviewers: dblaikie, javed.absar, JDevlieghere, andreadb
Subscribers: MatzeB, sanjoy, arsenm, dschuff, mehdi_amini, sdardis, nemanjai, jvesely, nhaehnle, sbc100, jgravelle-google, eraman, aheejin, kbarton, JDevlieghere, javed.absar, gbedwell, jrtc27, mgrang, atanasyan, steven_wu, george.burgess.iv, dexonsmith, kristina, jsji, llvm-commits
Differential Revision: https://reviews.llvm.org/D52573
llvm-svn: 343163
2018-09-27 10:13:45 +08:00
|
|
|
llvm::sort(PossibleDeadStores);
|
2017-01-27 10:37:11 +08:00
|
|
|
ValueDFSStack EliminationStack;
|
|
|
|
for (auto &VD : PossibleDeadStores) {
|
|
|
|
int MemberDFSIn = VD.DFSIn;
|
|
|
|
int MemberDFSOut = VD.DFSOut;
|
2017-04-01 17:44:33 +08:00
|
|
|
Instruction *Member = cast<Instruction>(VD.Def.getPointer());
|
2017-01-27 10:37:11 +08:00
|
|
|
if (EliminationStack.empty() ||
|
|
|
|
!EliminationStack.isInScope(MemberDFSIn, MemberDFSOut)) {
|
|
|
|
// Sync to our current scope.
|
|
|
|
EliminationStack.popUntilDFSScope(MemberDFSIn, MemberDFSOut);
|
|
|
|
if (EliminationStack.empty()) {
|
|
|
|
EliminationStack.push_back(Member, MemberDFSIn, MemberDFSOut);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// We already did load elimination, so nothing to do here.
|
|
|
|
if (isa<LoadInst>(Member))
|
|
|
|
continue;
|
|
|
|
assert(!EliminationStack.empty());
|
|
|
|
Instruction *Leader = cast<Instruction>(EliminationStack.back());
|
2017-01-27 14:06:05 +08:00
|
|
|
(void)Leader;
|
2017-01-27 10:37:11 +08:00
|
|
|
assert(DT->dominates(Leader->getParent(), Member->getParent()));
|
|
|
|
// Member is dominater by Leader, and thus dead
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Marking dead store " << *Member
|
|
|
|
<< " that is dominated by " << *Leader << "\n");
|
2017-01-27 10:37:11 +08:00
|
|
|
markInstructionForDeletion(Member);
|
2017-04-08 02:38:09 +08:00
|
|
|
CC->erase(Member);
|
2017-01-27 10:37:11 +08:00
|
|
|
++NumGVNDeadStores;
|
|
|
|
}
|
|
|
|
}
|
[GVN] Initial check-in of a new global value numbering algorithm.
The code have been developed by Daniel Berlin over the years, and
the new implementation goal is that of addressing shortcomings of
the current GVN infrastructure, i.e. long compile time for large
testcases, lack of phi predication, no load/store value numbering
etc...
The current code just implements the "core" GVN algorithm, although
other pieces (load coercion, phi handling, predicate system) are
already implemented in a branch out of tree. Once the core is stable,
we'll start adding pieces on top of the base framework.
The test currently living in test/Transform/NewGVN are a copy
of the ones in GVN, with proper `XFAIL` (missing features in NewGVN).
A flag will be added in a future commit to enable NewGVN, so that
interested parties can exercise this code easily.
Differential Revision: https://reviews.llvm.org/D26224
llvm-svn: 290346
2016-12-23 00:03:48 +08:00
|
|
|
}
|
|
|
|
return AnythingReplaced;
|
|
|
|
}
|
2017-02-11 23:07:01 +08:00
|
|
|
|
|
|
|
// This function provides global ranking of operations so that we can place them
|
|
|
|
// in a canonical order. Note that rank alone is not necessarily enough for a
|
|
|
|
// complete ordering, as constants all have the same rank. However, generally,
|
|
|
|
// we will simplify an operation with all constants so that it doesn't matter
|
|
|
|
// what order they appear in.
|
|
|
|
unsigned int NewGVN::getRank(const Value *V) const {
|
2017-05-20 03:01:27 +08:00
|
|
|
// Prefer constants to undef to anything else
|
|
|
|
// Undef is a constant, have to check it first.
|
|
|
|
// Prefer smaller constants to constantexprs
|
|
|
|
if (isa<ConstantExpr>(V))
|
|
|
|
return 2;
|
2017-02-19 07:06:47 +08:00
|
|
|
if (isa<UndefValue>(V))
|
|
|
|
return 1;
|
2017-05-20 03:01:27 +08:00
|
|
|
if (isa<Constant>(V))
|
|
|
|
return 0;
|
2017-02-11 23:07:01 +08:00
|
|
|
else if (auto *A = dyn_cast<Argument>(V))
|
2017-05-20 03:01:27 +08:00
|
|
|
return 3 + A->getArgNo();
|
2017-02-11 23:07:01 +08:00
|
|
|
|
2017-02-19 07:06:47 +08:00
|
|
|
// Need to shift the instruction DFS by number of arguments + 3 to account for
|
2017-02-11 23:07:01 +08:00
|
|
|
// the constant and argument ranking above.
|
2017-04-07 02:52:58 +08:00
|
|
|
unsigned Result = InstrToDFSNum(V);
|
2017-02-11 23:07:01 +08:00
|
|
|
if (Result > 0)
|
2017-05-20 03:01:27 +08:00
|
|
|
return 4 + NumFuncArgs + Result;
|
2017-02-11 23:07:01 +08:00
|
|
|
// Unreachable or something else, just return a really large number.
|
|
|
|
return ~0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is a function that says whether two commutative operations should
|
|
|
|
// have their order swapped when canonicalizing.
|
|
|
|
bool NewGVN::shouldSwapOperands(const Value *A, const Value *B) const {
|
|
|
|
// Because we only care about a total ordering, and don't rewrite expressions
|
|
|
|
// in this order, we order by rank, which will give a strict weak ordering to
|
2017-02-19 07:06:47 +08:00
|
|
|
// everything but constants, and then we order by pointer address.
|
2017-02-19 07:06:50 +08:00
|
|
|
return std::make_pair(getRank(A), A) > std::make_pair(getRank(B), B);
|
2017-02-11 23:07:01 +08:00
|
|
|
}
|
2017-03-12 12:46:45 +08:00
|
|
|
|
2017-05-27 04:09:00 +08:00
|
|
|
namespace {
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-03-12 12:46:45 +08:00
|
|
|
class NewGVNLegacyPass : public FunctionPass {
|
|
|
|
public:
|
2017-10-21 05:47:29 +08:00
|
|
|
// Pass identification, replacement for typeid.
|
|
|
|
static char ID;
|
|
|
|
|
2017-03-12 12:46:45 +08:00
|
|
|
NewGVNLegacyPass() : FunctionPass(ID) {
|
|
|
|
initializeNewGVNLegacyPassPass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
2017-10-21 05:47:29 +08:00
|
|
|
|
2017-03-12 12:46:45 +08:00
|
|
|
bool runOnFunction(Function &F) override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
|
|
|
AU.addRequired<AssumptionCacheTracker>();
|
|
|
|
AU.addRequired<DominatorTreeWrapperPass>();
|
|
|
|
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
|
|
|
AU.addRequired<MemorySSAWrapperPass>();
|
|
|
|
AU.addRequired<AAResultsWrapperPass>();
|
|
|
|
AU.addPreserved<DominatorTreeWrapperPass>();
|
|
|
|
AU.addPreserved<GlobalsAAWrapperPass>();
|
|
|
|
}
|
|
|
|
};
|
2017-10-21 05:47:29 +08:00
|
|
|
|
|
|
|
} // end anonymous namespace
|
2017-03-12 12:46:45 +08:00
|
|
|
|
|
|
|
bool NewGVNLegacyPass::runOnFunction(Function &F) {
|
|
|
|
if (skipFunction(F))
|
|
|
|
return false;
|
|
|
|
return NewGVN(F, &getAnalysis<DominatorTreeWrapperPass>().getDomTree(),
|
|
|
|
&getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F),
|
|
|
|
&getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(),
|
|
|
|
&getAnalysis<AAResultsWrapperPass>().getAAResults(),
|
|
|
|
&getAnalysis<MemorySSAWrapperPass>().getMSSA(),
|
|
|
|
F.getParent()->getDataLayout())
|
|
|
|
.runGVN();
|
|
|
|
}
|
|
|
|
|
2017-10-21 05:47:29 +08:00
|
|
|
char NewGVNLegacyPass::ID = 0;
|
|
|
|
|
2017-03-12 12:46:45 +08:00
|
|
|
INITIALIZE_PASS_BEGIN(NewGVNLegacyPass, "newgvn", "Global Value Numbering",
|
|
|
|
false, false)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
|
|
|
|
INITIALIZE_PASS_END(NewGVNLegacyPass, "newgvn", "Global Value Numbering", false,
|
|
|
|
false)
|
|
|
|
|
|
|
|
// createGVNPass - The public interface to this file.
|
|
|
|
FunctionPass *llvm::createNewGVNPass() { return new NewGVNLegacyPass(); }
|
|
|
|
|
|
|
|
PreservedAnalyses NewGVNPass::run(Function &F, AnalysisManager<Function> &AM) {
|
|
|
|
// Apparently the order in which we get these results matter for
|
|
|
|
// the old GVN (see Chandler's comment in GVN.cpp). I'll keep
|
|
|
|
// the same order here, just in case.
|
|
|
|
auto &AC = AM.getResult<AssumptionAnalysis>(F);
|
|
|
|
auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
|
|
|
|
auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
|
|
|
|
auto &AA = AM.getResult<AAManager>(F);
|
|
|
|
auto &MSSA = AM.getResult<MemorySSAAnalysis>(F).getMSSA();
|
|
|
|
bool Changed =
|
|
|
|
NewGVN(F, &DT, &AC, &TLI, &AA, &MSSA, F.getParent()->getDataLayout())
|
|
|
|
.runGVN();
|
|
|
|
if (!Changed)
|
|
|
|
return PreservedAnalyses::all();
|
|
|
|
PreservedAnalyses PA;
|
|
|
|
PA.preserve<DominatorTreeAnalysis>();
|
|
|
|
PA.preserve<GlobalsAA>();
|
|
|
|
return PA;
|
|
|
|
}
|