2016-03-11 09:50:55 +01:00
|
|
|
//===- GVN.h - Eliminate redundant values and loads -------------*- C++ -*-===//
|
|
|
|
//
|
2019-01-19 09:50:56 +01: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
|
2016-03-11 09:50:55 +01:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// \file
|
|
|
|
/// This file provides the interface for LLVM's Global Value Numbering pass
|
|
|
|
/// which eliminates fully redundant instructions. It also does somewhat Ad-Hoc
|
|
|
|
/// PRE and dead load elimination.
|
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLVM_TRANSFORMS_SCALAR_GVN_H
|
|
|
|
#define LLVM_TRANSFORMS_SCALAR_GVN_H
|
|
|
|
|
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
|
|
#include "llvm/ADT/MapVector.h"
|
2017-10-31 06:07:56 +01:00
|
|
|
#include "llvm/ADT/PostOrderIterator.h"
|
2016-03-11 09:50:55 +01:00
|
|
|
#include "llvm/ADT/SetVector.h"
|
2017-09-13 23:43:53 +02:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2018-08-30 06:49:03 +02:00
|
|
|
#include "llvm/Analysis/InstructionPrecedenceTracking.h"
|
2016-03-11 09:50:55 +01:00
|
|
|
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
|
|
|
|
#include "llvm/IR/Dominators.h"
|
2017-09-13 23:43:53 +02:00
|
|
|
#include "llvm/IR/InstrTypes.h"
|
2016-03-11 09:50:55 +01:00
|
|
|
#include "llvm/IR/PassManager.h"
|
[GVN] Update BlockRPONumber prior to use.
Summary:
The original patch addressed the use of BlockRPONumber by forcing a sequence point when accessing that map in a conditional. In short we found cases where that map was being accessed with blocks that had not yet been added to that structure. For context, I've kept the wall of text below, to what we are trying to fix, by always ensuring a updated BlockRPONumber.
== Backstory ==
I was investigating an ICE (segfault accessing a DenseMap item). This failure happened non-deterministically, with no apparent reason and only on a Windows build of LLVM (from October 2018).
After looking into the crashes (multiple core files) and running DynamoRio, the cores and DynamoRio (DR) log pointed to the same code in `GVN::performScalarPRE()`. The values in the map are unsigned integers, the keys are `llvm::BasicBlock*`. Our test case that triggered this warning and periodic crash is rather involved. But the problematic line looks to be:
GVN.cpp: Line 2197
```
if (BlockRPONumber[P] >= BlockRPONumber[CurrentBlock] &&
```
To test things out, I cooked up a patch that accessed the items in the map outside of the condition, by forcing a sequence point between accesses. DynamoRio stopped warning of the issue, and the test didn't seem to crash after 1000+ runs.
My investigation was on an older version of LLVM, (source from October this year). What it looks like was occurring is the following, and the assembly from the latest pull of llvm in December seems to confirm this might still be an issue; however, I have not witnessed the crash on more recent builds. Of course the asm in question is generated from the host compiler on that Windows box (not clang), but it hints that we might want to consider how we access the BlockRPONumber map in this conditional (line 2197, listed above). In any case, I don't think the host compiler is wrong, rather I think it is pointing out a possibly latent bug in llvm.
1) There is no sequence point for the `>=` operation.
2) A call to a `DenseMapBase::operator[]` can have the side effect of the map reallocating a larger store (more Buckets, via a call to `DenseMap::grow`).
3) It seems perfectly legal for a host compiler to generate assembly that stores the result of a call to `operator[]` on the stack (that's what my host compile of GVN.cpp is doing) . A second call to `operator[]` //might// encourage the map to 'grow' thus making any pointers to the map's store invalid. The `>=` compares the first and second values. If the first happens to be a pointer produced from operator[], it could be invalid when dereferenced at the time of comparison.
The assembly generated from the Window's host compiler does show the result of the first access to the map via `operator[]` produces a pointer to an unsigned int. And that pointer is being stored on the stack. If a second call to the map (which does occur) causes the map to grow, that address (on the stack) is now invalid.
Reviewers: t.p.northover, efriedma
Reviewed By: efriedma
Subscribers: efriedma, llvm-commits
Differential Revision: https://reviews.llvm.org/D55974
llvm-svn: 350880
2019-01-10 20:56:03 +01:00
|
|
|
#include "llvm/IR/ValueHandle.h"
|
2017-09-13 23:43:53 +02:00
|
|
|
#include "llvm/Support/Allocator.h"
|
|
|
|
#include "llvm/Support/Compiler.h"
|
|
|
|
#include <cstdint>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
2016-03-11 09:50:55 +01:00
|
|
|
|
|
|
|
namespace llvm {
|
2017-09-13 23:43:53 +02:00
|
|
|
|
2020-06-25 17:37:06 +02:00
|
|
|
class AAResults;
|
2021-04-06 21:45:20 +02:00
|
|
|
class AssumeInst;
|
2017-09-13 23:43:53 +02:00
|
|
|
class AssumptionCache;
|
|
|
|
class BasicBlock;
|
|
|
|
class BranchInst;
|
|
|
|
class CallInst;
|
|
|
|
class Constant;
|
|
|
|
class ExtractValueInst;
|
|
|
|
class Function;
|
|
|
|
class FunctionPass;
|
2017-09-08 01:27:44 +02:00
|
|
|
class IntrinsicInst;
|
2017-09-13 23:43:53 +02:00
|
|
|
class LoadInst;
|
|
|
|
class LoopInfo;
|
2020-09-03 13:16:17 +02:00
|
|
|
class MemorySSA;
|
|
|
|
class MemorySSAUpdater;
|
2016-12-01 17:40:32 +01:00
|
|
|
class OptimizationRemarkEmitter;
|
2017-09-13 23:43:53 +02:00
|
|
|
class PHINode;
|
|
|
|
class TargetLibraryInfo;
|
|
|
|
class Value;
|
2016-03-11 09:50:55 +01:00
|
|
|
/// A private "module" namespace for types and utilities used by GVN. These
|
|
|
|
/// are implementation details and should not be used by clients.
|
|
|
|
namespace gvn LLVM_LIBRARY_VISIBILITY {
|
2017-09-13 23:43:53 +02:00
|
|
|
|
2016-03-11 09:50:55 +01:00
|
|
|
struct AvailableValue;
|
|
|
|
struct AvailableValueInBlock;
|
|
|
|
class GVNLegacyPass;
|
2017-09-13 23:43:53 +02:00
|
|
|
|
|
|
|
} // end namespace gvn
|
2016-03-11 09:50:55 +01:00
|
|
|
|
2020-01-16 17:02:44 +01:00
|
|
|
/// A set of parameters to control various transforms performed by GVN pass.
|
|
|
|
// Each of the optional boolean parameters can be set to:
|
|
|
|
/// true - enabling the transformation.
|
|
|
|
/// false - disabling the transformation.
|
|
|
|
/// None - relying on a global default.
|
|
|
|
/// Intended use is to create a default object, modify parameters with
|
|
|
|
/// additional setters and then pass it to GVN.
|
|
|
|
struct GVNOptions {
|
|
|
|
Optional<bool> AllowPRE = None;
|
|
|
|
Optional<bool> AllowLoadPRE = None;
|
2020-02-04 07:24:12 +01:00
|
|
|
Optional<bool> AllowLoadInLoopPRE = None;
|
2020-10-20 12:32:08 +02:00
|
|
|
Optional<bool> AllowLoadPRESplitBackedge = None;
|
2020-01-16 17:02:44 +01:00
|
|
|
Optional<bool> AllowMemDep = None;
|
|
|
|
|
|
|
|
GVNOptions() = default;
|
|
|
|
|
|
|
|
/// Enables or disables PRE in GVN.
|
|
|
|
GVNOptions &setPRE(bool PRE) {
|
|
|
|
AllowPRE = PRE;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Enables or disables PRE of loads in GVN.
|
|
|
|
GVNOptions &setLoadPRE(bool LoadPRE) {
|
|
|
|
AllowLoadPRE = LoadPRE;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2020-02-04 07:24:12 +01:00
|
|
|
GVNOptions &setLoadInLoopPRE(bool LoadInLoopPRE) {
|
|
|
|
AllowLoadInLoopPRE = LoadInLoopPRE;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2020-10-20 12:32:08 +02:00
|
|
|
/// Enables or disables PRE of loads in GVN.
|
|
|
|
GVNOptions &setLoadPRESplitBackedge(bool LoadPRESplitBackedge) {
|
|
|
|
AllowLoadPRESplitBackedge = LoadPRESplitBackedge;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2020-01-16 17:02:44 +01:00
|
|
|
/// Enables or disables use of MemDepAnalysis.
|
|
|
|
GVNOptions &setMemDep(bool MemDep) {
|
|
|
|
AllowMemDep = MemDep;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-03-11 09:50:55 +01:00
|
|
|
/// The core GVN pass object.
|
|
|
|
///
|
|
|
|
/// FIXME: We should have a good summary of the GVN algorithm implemented by
|
|
|
|
/// this particular pass here.
|
2016-03-11 11:33:22 +01:00
|
|
|
class GVN : public PassInfoMixin<GVN> {
|
2020-01-16 17:02:44 +01:00
|
|
|
GVNOptions Options;
|
|
|
|
|
2016-03-11 09:50:55 +01:00
|
|
|
public:
|
2017-09-13 23:43:53 +02:00
|
|
|
struct Expression;
|
2016-03-11 09:50:55 +01:00
|
|
|
|
2020-01-16 17:02:44 +01:00
|
|
|
GVN(GVNOptions Options = {}) : Options(Options) {}
|
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Run the pass over the function.
|
2016-08-09 02:28:15 +02:00
|
|
|
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
|
2016-03-11 09:50:55 +01:00
|
|
|
|
|
|
|
/// This removes the specified instruction from
|
|
|
|
/// our various maps and marks it for deletion.
|
|
|
|
void markInstructionForDeletion(Instruction *I) {
|
|
|
|
VN.erase(I);
|
|
|
|
InstrsToErase.push_back(I);
|
|
|
|
}
|
|
|
|
|
|
|
|
DominatorTree &getDominatorTree() const { return *DT; }
|
2020-06-25 17:37:06 +02:00
|
|
|
AAResults *getAliasAnalysis() const { return VN.getAliasAnalysis(); }
|
2016-03-11 09:50:55 +01:00
|
|
|
MemoryDependenceResults &getMemDep() const { return *MD; }
|
|
|
|
|
2020-01-16 17:02:44 +01:00
|
|
|
bool isPREEnabled() const;
|
|
|
|
bool isLoadPREEnabled() const;
|
2020-02-04 07:24:12 +01:00
|
|
|
bool isLoadInLoopPREEnabled() const;
|
2020-10-20 12:32:08 +02:00
|
|
|
bool isLoadPRESplitBackedgeEnabled() const;
|
2020-01-16 17:02:44 +01:00
|
|
|
bool isMemDepEnabled() const;
|
|
|
|
|
2016-03-11 09:50:55 +01:00
|
|
|
/// This class holds the mapping between values and value numbers. It is used
|
|
|
|
/// as an efficient mechanism to determine the expression-wise equivalence of
|
|
|
|
/// two values.
|
|
|
|
class ValueTable {
|
|
|
|
DenseMap<Value *, uint32_t> valueNumbering;
|
2016-03-11 17:25:19 +01:00
|
|
|
DenseMap<Expression, uint32_t> expressionNumbering;
|
[GVN] Recommit the patch "Add phi-translate support in scalarpre"
Recommit after workaround the bug PR31652.
Three bugs fixed in previous recommits: The first one is to use CurrentBlock
instead of PREInstr's Parent as param of performScalarPREInsertion because
the Parent of a clone instruction may be uninitialized. The second one is stop
PRE when CurrentBlock to its predecessor is a backedge and an operand of CurInst
is defined inside of CurrentBlock. The same value defined inside of loop in last
iteration can not be regarded as available. The third one is an out-of-bound
array access in a flipped if guard.
Right now scalarpre doesn't have phi-translate support, so it will miss some
simple pre opportunities. Like the following testcase, current scalarpre cannot
recognize the last "a * b" is fully redundent because a and b used by the last
"a * b" expr are both defined by phis.
long a[100], b[100], g1, g2, g3;
__attribute__((pure)) long goo();
void foo(long a, long b, long c, long d) {
g1 = a * b;
if (__builtin_expect(g2 > 3, 0)) {
a = c;
b = d;
g2 = a * b;
}
g3 = a * b; // fully redundant.
}
The patch adds phi-translate support in scalarpre. This is only a temporary
solution before the newpre based on newgvn is available.
Differential Revision: https://reviews.llvm.org/D32252
llvm-svn: 309397
2017-07-28 17:47:25 +02:00
|
|
|
|
|
|
|
// Expressions is the vector of Expression. ExprIdx is the mapping from
|
|
|
|
// value number to the index of Expression in Expressions. We use it
|
|
|
|
// instead of a DenseMap because filling such mapping is faster than
|
|
|
|
// filling a DenseMap and the compile time is a little better.
|
2019-11-05 15:10:32 +01:00
|
|
|
uint32_t nextExprNumber = 0;
|
2017-09-13 23:43:53 +02:00
|
|
|
|
[GVN] Recommit the patch "Add phi-translate support in scalarpre"
Recommit after workaround the bug PR31652.
Three bugs fixed in previous recommits: The first one is to use CurrentBlock
instead of PREInstr's Parent as param of performScalarPREInsertion because
the Parent of a clone instruction may be uninitialized. The second one is stop
PRE when CurrentBlock to its predecessor is a backedge and an operand of CurInst
is defined inside of CurrentBlock. The same value defined inside of loop in last
iteration can not be regarded as available. The third one is an out-of-bound
array access in a flipped if guard.
Right now scalarpre doesn't have phi-translate support, so it will miss some
simple pre opportunities. Like the following testcase, current scalarpre cannot
recognize the last "a * b" is fully redundent because a and b used by the last
"a * b" expr are both defined by phis.
long a[100], b[100], g1, g2, g3;
__attribute__((pure)) long goo();
void foo(long a, long b, long c, long d) {
g1 = a * b;
if (__builtin_expect(g2 > 3, 0)) {
a = c;
b = d;
g2 = a * b;
}
g3 = a * b; // fully redundant.
}
The patch adds phi-translate support in scalarpre. This is only a temporary
solution before the newpre based on newgvn is available.
Differential Revision: https://reviews.llvm.org/D32252
llvm-svn: 309397
2017-07-28 17:47:25 +02:00
|
|
|
std::vector<Expression> Expressions;
|
|
|
|
std::vector<uint32_t> ExprIdx;
|
2017-09-13 23:43:53 +02:00
|
|
|
|
[GVN] Recommit the patch "Add phi-translate support in scalarpre"
Recommit after workaround the bug PR31652.
Three bugs fixed in previous recommits: The first one is to use CurrentBlock
instead of PREInstr's Parent as param of performScalarPREInsertion because
the Parent of a clone instruction may be uninitialized. The second one is stop
PRE when CurrentBlock to its predecessor is a backedge and an operand of CurInst
is defined inside of CurrentBlock. The same value defined inside of loop in last
iteration can not be regarded as available. The third one is an out-of-bound
array access in a flipped if guard.
Right now scalarpre doesn't have phi-translate support, so it will miss some
simple pre opportunities. Like the following testcase, current scalarpre cannot
recognize the last "a * b" is fully redundent because a and b used by the last
"a * b" expr are both defined by phis.
long a[100], b[100], g1, g2, g3;
__attribute__((pure)) long goo();
void foo(long a, long b, long c, long d) {
g1 = a * b;
if (__builtin_expect(g2 > 3, 0)) {
a = c;
b = d;
g2 = a * b;
}
g3 = a * b; // fully redundant.
}
The patch adds phi-translate support in scalarpre. This is only a temporary
solution before the newpre based on newgvn is available.
Differential Revision: https://reviews.llvm.org/D32252
llvm-svn: 309397
2017-07-28 17:47:25 +02:00
|
|
|
// Value number to PHINode mapping. Used for phi-translate in scalarpre.
|
|
|
|
DenseMap<uint32_t, PHINode *> NumberingPhi;
|
2017-09-13 23:43:53 +02:00
|
|
|
|
[GVN] Recommit the patch "Add phi-translate support in scalarpre"
Recommit after workaround the bug PR31652.
Three bugs fixed in previous recommits: The first one is to use CurrentBlock
instead of PREInstr's Parent as param of performScalarPREInsertion because
the Parent of a clone instruction may be uninitialized. The second one is stop
PRE when CurrentBlock to its predecessor is a backedge and an operand of CurInst
is defined inside of CurrentBlock. The same value defined inside of loop in last
iteration can not be regarded as available. The third one is an out-of-bound
array access in a flipped if guard.
Right now scalarpre doesn't have phi-translate support, so it will miss some
simple pre opportunities. Like the following testcase, current scalarpre cannot
recognize the last "a * b" is fully redundent because a and b used by the last
"a * b" expr are both defined by phis.
long a[100], b[100], g1, g2, g3;
__attribute__((pure)) long goo();
void foo(long a, long b, long c, long d) {
g1 = a * b;
if (__builtin_expect(g2 > 3, 0)) {
a = c;
b = d;
g2 = a * b;
}
g3 = a * b; // fully redundant.
}
The patch adds phi-translate support in scalarpre. This is only a temporary
solution before the newpre based on newgvn is available.
Differential Revision: https://reviews.llvm.org/D32252
llvm-svn: 309397
2017-07-28 17:47:25 +02:00
|
|
|
// Cache for phi-translate in scalarpre.
|
2017-09-13 23:43:53 +02:00
|
|
|
using PhiTranslateMap =
|
|
|
|
DenseMap<std::pair<uint32_t, const BasicBlock *>, uint32_t>;
|
[GVN] Recommit the patch "Add phi-translate support in scalarpre"
Recommit after workaround the bug PR31652.
Three bugs fixed in previous recommits: The first one is to use CurrentBlock
instead of PREInstr's Parent as param of performScalarPREInsertion because
the Parent of a clone instruction may be uninitialized. The second one is stop
PRE when CurrentBlock to its predecessor is a backedge and an operand of CurInst
is defined inside of CurrentBlock. The same value defined inside of loop in last
iteration can not be regarded as available. The third one is an out-of-bound
array access in a flipped if guard.
Right now scalarpre doesn't have phi-translate support, so it will miss some
simple pre opportunities. Like the following testcase, current scalarpre cannot
recognize the last "a * b" is fully redundent because a and b used by the last
"a * b" expr are both defined by phis.
long a[100], b[100], g1, g2, g3;
__attribute__((pure)) long goo();
void foo(long a, long b, long c, long d) {
g1 = a * b;
if (__builtin_expect(g2 > 3, 0)) {
a = c;
b = d;
g2 = a * b;
}
g3 = a * b; // fully redundant.
}
The patch adds phi-translate support in scalarpre. This is only a temporary
solution before the newpre based on newgvn is available.
Differential Revision: https://reviews.llvm.org/D32252
llvm-svn: 309397
2017-07-28 17:47:25 +02:00
|
|
|
PhiTranslateMap PhiTranslateTable;
|
|
|
|
|
2020-06-25 17:37:06 +02:00
|
|
|
AAResults *AA = nullptr;
|
2019-11-05 15:10:32 +01:00
|
|
|
MemoryDependenceResults *MD = nullptr;
|
|
|
|
DominatorTree *DT = nullptr;
|
2016-03-11 09:50:55 +01:00
|
|
|
|
2017-09-13 23:43:53 +02:00
|
|
|
uint32_t nextValueNumber = 1;
|
2016-03-11 09:50:55 +01:00
|
|
|
|
2016-04-28 18:00:15 +02:00
|
|
|
Expression createExpr(Instruction *I);
|
|
|
|
Expression createCmpExpr(unsigned Opcode, CmpInst::Predicate Predicate,
|
|
|
|
Value *LHS, Value *RHS);
|
|
|
|
Expression createExtractvalueExpr(ExtractValueInst *EI);
|
|
|
|
uint32_t lookupOrAddCall(CallInst *C);
|
[GVN] Recommit the patch "Add phi-translate support in scalarpre"
Recommit after workaround the bug PR31652.
Three bugs fixed in previous recommits: The first one is to use CurrentBlock
instead of PREInstr's Parent as param of performScalarPREInsertion because
the Parent of a clone instruction may be uninitialized. The second one is stop
PRE when CurrentBlock to its predecessor is a backedge and an operand of CurInst
is defined inside of CurrentBlock. The same value defined inside of loop in last
iteration can not be regarded as available. The third one is an out-of-bound
array access in a flipped if guard.
Right now scalarpre doesn't have phi-translate support, so it will miss some
simple pre opportunities. Like the following testcase, current scalarpre cannot
recognize the last "a * b" is fully redundent because a and b used by the last
"a * b" expr are both defined by phis.
long a[100], b[100], g1, g2, g3;
__attribute__((pure)) long goo();
void foo(long a, long b, long c, long d) {
g1 = a * b;
if (__builtin_expect(g2 > 3, 0)) {
a = c;
b = d;
g2 = a * b;
}
g3 = a * b; // fully redundant.
}
The patch adds phi-translate support in scalarpre. This is only a temporary
solution before the newpre based on newgvn is available.
Differential Revision: https://reviews.llvm.org/D32252
llvm-svn: 309397
2017-07-28 17:47:25 +02:00
|
|
|
uint32_t phiTranslateImpl(const BasicBlock *BB, const BasicBlock *PhiBlock,
|
|
|
|
uint32_t Num, GVN &Gvn);
|
[GVN] Verify value equality before doing phi translation for call instruction
This is an updated version of https://reviews.llvm.org/D66909 to fix PR42605.
Basically, current phi translatation translates an old value number to an new
value number for a call instruction based on the literal equality of call
expression, without verifying there is no clobber in between. This is incorrect.
To get a finegrain check, use MachineDependence analysis to do the job. However,
this is still not ideal. Although given a call instruction,
`MemoryDependenceResults::getCallDependencyFrom` returns identical call
instructions without clobber in between using MemDepResult with its DepType to
be `Def`. However, identical is too strict here and we want it to be relaxed a
little to consider phi-translation -- callee is the same, param operands can be
different. That means changing the semantic of `MemDepResult::Def` and I don't
know the potential impact.
So currently the patch is still conservative to only handle
MemDepResult::NonFuncLocal, which means the current call has no function local
clobber. If there is clobber, even if the clobber doesn't stand in between the
current call and the call with the new value, we won't do phi-translate.
Differential Revision: https://reviews.llvm.org/D67013
llvm-svn: 370547
2019-08-31 01:01:22 +02:00
|
|
|
bool areCallValsEqual(uint32_t Num, uint32_t NewNum, const BasicBlock *Pred,
|
|
|
|
const BasicBlock *PhiBlock, GVN &Gvn);
|
[GVN] Recommit the patch "Add phi-translate support in scalarpre"
Recommit after workaround the bug PR31652.
Three bugs fixed in previous recommits: The first one is to use CurrentBlock
instead of PREInstr's Parent as param of performScalarPREInsertion because
the Parent of a clone instruction may be uninitialized. The second one is stop
PRE when CurrentBlock to its predecessor is a backedge and an operand of CurInst
is defined inside of CurrentBlock. The same value defined inside of loop in last
iteration can not be regarded as available. The third one is an out-of-bound
array access in a flipped if guard.
Right now scalarpre doesn't have phi-translate support, so it will miss some
simple pre opportunities. Like the following testcase, current scalarpre cannot
recognize the last "a * b" is fully redundent because a and b used by the last
"a * b" expr are both defined by phis.
long a[100], b[100], g1, g2, g3;
__attribute__((pure)) long goo();
void foo(long a, long b, long c, long d) {
g1 = a * b;
if (__builtin_expect(g2 > 3, 0)) {
a = c;
b = d;
g2 = a * b;
}
g3 = a * b; // fully redundant.
}
The patch adds phi-translate support in scalarpre. This is only a temporary
solution before the newpre based on newgvn is available.
Differential Revision: https://reviews.llvm.org/D32252
llvm-svn: 309397
2017-07-28 17:47:25 +02:00
|
|
|
std::pair<uint32_t, bool> assignExpNewValueNum(Expression &exp);
|
|
|
|
bool areAllValsInBB(uint32_t num, const BasicBlock *BB, GVN &Gvn);
|
2016-03-11 09:50:55 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
ValueTable();
|
|
|
|
ValueTable(const ValueTable &Arg);
|
|
|
|
ValueTable(ValueTable &&Arg);
|
|
|
|
~ValueTable();
|
2019-11-05 14:41:31 +01:00
|
|
|
ValueTable &operator=(const ValueTable &Arg);
|
2016-03-11 09:50:55 +01:00
|
|
|
|
2016-04-28 18:00:15 +02:00
|
|
|
uint32_t lookupOrAdd(Value *V);
|
[GVN] Recommit the patch "Add phi-translate support in scalarpre"
Recommit after workaround the bug PR31652.
Three bugs fixed in previous recommits: The first one is to use CurrentBlock
instead of PREInstr's Parent as param of performScalarPREInsertion because
the Parent of a clone instruction may be uninitialized. The second one is stop
PRE when CurrentBlock to its predecessor is a backedge and an operand of CurInst
is defined inside of CurrentBlock. The same value defined inside of loop in last
iteration can not be regarded as available. The third one is an out-of-bound
array access in a flipped if guard.
Right now scalarpre doesn't have phi-translate support, so it will miss some
simple pre opportunities. Like the following testcase, current scalarpre cannot
recognize the last "a * b" is fully redundent because a and b used by the last
"a * b" expr are both defined by phis.
long a[100], b[100], g1, g2, g3;
__attribute__((pure)) long goo();
void foo(long a, long b, long c, long d) {
g1 = a * b;
if (__builtin_expect(g2 > 3, 0)) {
a = c;
b = d;
g2 = a * b;
}
g3 = a * b; // fully redundant.
}
The patch adds phi-translate support in scalarpre. This is only a temporary
solution before the newpre based on newgvn is available.
Differential Revision: https://reviews.llvm.org/D32252
llvm-svn: 309397
2017-07-28 17:47:25 +02:00
|
|
|
uint32_t lookup(Value *V, bool Verify = true) const;
|
2016-04-28 18:00:15 +02:00
|
|
|
uint32_t lookupOrAddCmp(unsigned Opcode, CmpInst::Predicate Pred,
|
|
|
|
Value *LHS, Value *RHS);
|
[GVN] Recommit the patch "Add phi-translate support in scalarpre"
Recommit after workaround the bug PR31652.
Three bugs fixed in previous recommits: The first one is to use CurrentBlock
instead of PREInstr's Parent as param of performScalarPREInsertion because
the Parent of a clone instruction may be uninitialized. The second one is stop
PRE when CurrentBlock to its predecessor is a backedge and an operand of CurInst
is defined inside of CurrentBlock. The same value defined inside of loop in last
iteration can not be regarded as available. The third one is an out-of-bound
array access in a flipped if guard.
Right now scalarpre doesn't have phi-translate support, so it will miss some
simple pre opportunities. Like the following testcase, current scalarpre cannot
recognize the last "a * b" is fully redundent because a and b used by the last
"a * b" expr are both defined by phis.
long a[100], b[100], g1, g2, g3;
__attribute__((pure)) long goo();
void foo(long a, long b, long c, long d) {
g1 = a * b;
if (__builtin_expect(g2 > 3, 0)) {
a = c;
b = d;
g2 = a * b;
}
g3 = a * b; // fully redundant.
}
The patch adds phi-translate support in scalarpre. This is only a temporary
solution before the newpre based on newgvn is available.
Differential Revision: https://reviews.llvm.org/D32252
llvm-svn: 309397
2017-07-28 17:47:25 +02:00
|
|
|
uint32_t phiTranslate(const BasicBlock *BB, const BasicBlock *PhiBlock,
|
|
|
|
uint32_t Num, GVN &Gvn);
|
2017-08-08 23:40:14 +02:00
|
|
|
void eraseTranslateCacheEntry(uint32_t Num, const BasicBlock &CurrBlock);
|
2016-03-11 09:50:55 +01:00
|
|
|
bool exists(Value *V) const;
|
|
|
|
void add(Value *V, uint32_t num);
|
|
|
|
void clear();
|
|
|
|
void erase(Value *v);
|
2020-06-25 17:37:06 +02:00
|
|
|
void setAliasAnalysis(AAResults *A) { AA = A; }
|
|
|
|
AAResults *getAliasAnalysis() const { return AA; }
|
2016-03-11 09:50:55 +01:00
|
|
|
void setMemDep(MemoryDependenceResults *M) { MD = M; }
|
|
|
|
void setDomTree(DominatorTree *D) { DT = D; }
|
|
|
|
uint32_t getNextUnusedValueNumber() { return nextValueNumber; }
|
|
|
|
void verifyRemoved(const Value *) const;
|
|
|
|
};
|
|
|
|
|
2016-07-15 15:45:20 +02:00
|
|
|
private:
|
|
|
|
friend class gvn::GVNLegacyPass;
|
|
|
|
friend struct DenseMapInfo<Expression>;
|
|
|
|
|
2019-11-05 15:10:32 +01:00
|
|
|
MemoryDependenceResults *MD = nullptr;
|
|
|
|
DominatorTree *DT = nullptr;
|
|
|
|
const TargetLibraryInfo *TLI = nullptr;
|
|
|
|
AssumptionCache *AC = nullptr;
|
2016-03-11 09:50:55 +01:00
|
|
|
SetVector<BasicBlock *> DeadBlocks;
|
2019-11-05 15:10:32 +01:00
|
|
|
OptimizationRemarkEmitter *ORE = nullptr;
|
|
|
|
ImplicitControlFlowTracking *ICF = nullptr;
|
|
|
|
LoopInfo *LI = nullptr;
|
2020-09-03 13:16:17 +02:00
|
|
|
MemorySSAUpdater *MSSAU = nullptr;
|
2016-03-11 09:50:55 +01:00
|
|
|
|
|
|
|
ValueTable VN;
|
|
|
|
|
|
|
|
/// A mapping from value numbers to lists of Value*'s that
|
|
|
|
/// have that value number. Use findLeader to query it.
|
|
|
|
struct LeaderTableEntry {
|
|
|
|
Value *Val;
|
|
|
|
const BasicBlock *BB;
|
|
|
|
LeaderTableEntry *Next;
|
|
|
|
};
|
|
|
|
DenseMap<uint32_t, LeaderTableEntry> LeaderTable;
|
|
|
|
BumpPtrAllocator TableAllocator;
|
|
|
|
|
|
|
|
// Block-local map of equivalent values to their leader, does not
|
|
|
|
// propagate to any successors. Entries added mid-block are applied
|
|
|
|
// to the remaining instructions in the block.
|
2019-09-03 19:31:19 +02:00
|
|
|
SmallMapVector<Value *, Value *, 4> ReplaceOperandsWithMap;
|
2016-03-11 09:50:55 +01:00
|
|
|
SmallVector<Instruction *, 8> InstrsToErase;
|
|
|
|
|
[GVN] Recommit the patch "Add phi-translate support in scalarpre"
Recommit after workaround the bug PR31652.
Three bugs fixed in previous recommits: The first one is to use CurrentBlock
instead of PREInstr's Parent as param of performScalarPREInsertion because
the Parent of a clone instruction may be uninitialized. The second one is stop
PRE when CurrentBlock to its predecessor is a backedge and an operand of CurInst
is defined inside of CurrentBlock. The same value defined inside of loop in last
iteration can not be regarded as available. The third one is an out-of-bound
array access in a flipped if guard.
Right now scalarpre doesn't have phi-translate support, so it will miss some
simple pre opportunities. Like the following testcase, current scalarpre cannot
recognize the last "a * b" is fully redundent because a and b used by the last
"a * b" expr are both defined by phis.
long a[100], b[100], g1, g2, g3;
__attribute__((pure)) long goo();
void foo(long a, long b, long c, long d) {
g1 = a * b;
if (__builtin_expect(g2 > 3, 0)) {
a = c;
b = d;
g2 = a * b;
}
g3 = a * b; // fully redundant.
}
The patch adds phi-translate support in scalarpre. This is only a temporary
solution before the newpre based on newgvn is available.
Differential Revision: https://reviews.llvm.org/D32252
llvm-svn: 309397
2017-07-28 17:47:25 +02:00
|
|
|
// Map the block to reversed postorder traversal number. It is used to
|
|
|
|
// find back edge easily.
|
[GVN] Update BlockRPONumber prior to use.
Summary:
The original patch addressed the use of BlockRPONumber by forcing a sequence point when accessing that map in a conditional. In short we found cases where that map was being accessed with blocks that had not yet been added to that structure. For context, I've kept the wall of text below, to what we are trying to fix, by always ensuring a updated BlockRPONumber.
== Backstory ==
I was investigating an ICE (segfault accessing a DenseMap item). This failure happened non-deterministically, with no apparent reason and only on a Windows build of LLVM (from October 2018).
After looking into the crashes (multiple core files) and running DynamoRio, the cores and DynamoRio (DR) log pointed to the same code in `GVN::performScalarPRE()`. The values in the map are unsigned integers, the keys are `llvm::BasicBlock*`. Our test case that triggered this warning and periodic crash is rather involved. But the problematic line looks to be:
GVN.cpp: Line 2197
```
if (BlockRPONumber[P] >= BlockRPONumber[CurrentBlock] &&
```
To test things out, I cooked up a patch that accessed the items in the map outside of the condition, by forcing a sequence point between accesses. DynamoRio stopped warning of the issue, and the test didn't seem to crash after 1000+ runs.
My investigation was on an older version of LLVM, (source from October this year). What it looks like was occurring is the following, and the assembly from the latest pull of llvm in December seems to confirm this might still be an issue; however, I have not witnessed the crash on more recent builds. Of course the asm in question is generated from the host compiler on that Windows box (not clang), but it hints that we might want to consider how we access the BlockRPONumber map in this conditional (line 2197, listed above). In any case, I don't think the host compiler is wrong, rather I think it is pointing out a possibly latent bug in llvm.
1) There is no sequence point for the `>=` operation.
2) A call to a `DenseMapBase::operator[]` can have the side effect of the map reallocating a larger store (more Buckets, via a call to `DenseMap::grow`).
3) It seems perfectly legal for a host compiler to generate assembly that stores the result of a call to `operator[]` on the stack (that's what my host compile of GVN.cpp is doing) . A second call to `operator[]` //might// encourage the map to 'grow' thus making any pointers to the map's store invalid. The `>=` compares the first and second values. If the first happens to be a pointer produced from operator[], it could be invalid when dereferenced at the time of comparison.
The assembly generated from the Window's host compiler does show the result of the first access to the map via `operator[]` produces a pointer to an unsigned int. And that pointer is being stored on the stack. If a second call to the map (which does occur) causes the map to grow, that address (on the stack) is now invalid.
Reviewers: t.p.northover, efriedma
Reviewed By: efriedma
Subscribers: efriedma, llvm-commits
Differential Revision: https://reviews.llvm.org/D55974
llvm-svn: 350880
2019-01-10 20:56:03 +01:00
|
|
|
DenseMap<AssertingVH<BasicBlock>, uint32_t> BlockRPONumber;
|
|
|
|
|
|
|
|
// This is set 'true' initially and also when new blocks have been added to
|
|
|
|
// the function being analyzed. This boolean is used to control the updating
|
|
|
|
// of BlockRPONumber prior to accessing the contents of BlockRPONumber.
|
|
|
|
bool InvalidBlockRPONumbers = true;
|
[GVN] Recommit the patch "Add phi-translate support in scalarpre"
Recommit after workaround the bug PR31652.
Three bugs fixed in previous recommits: The first one is to use CurrentBlock
instead of PREInstr's Parent as param of performScalarPREInsertion because
the Parent of a clone instruction may be uninitialized. The second one is stop
PRE when CurrentBlock to its predecessor is a backedge and an operand of CurInst
is defined inside of CurrentBlock. The same value defined inside of loop in last
iteration can not be regarded as available. The third one is an out-of-bound
array access in a flipped if guard.
Right now scalarpre doesn't have phi-translate support, so it will miss some
simple pre opportunities. Like the following testcase, current scalarpre cannot
recognize the last "a * b" is fully redundent because a and b used by the last
"a * b" expr are both defined by phis.
long a[100], b[100], g1, g2, g3;
__attribute__((pure)) long goo();
void foo(long a, long b, long c, long d) {
g1 = a * b;
if (__builtin_expect(g2 > 3, 0)) {
a = c;
b = d;
g2 = a * b;
}
g3 = a * b; // fully redundant.
}
The patch adds phi-translate support in scalarpre. This is only a temporary
solution before the newpre based on newgvn is available.
Differential Revision: https://reviews.llvm.org/D32252
llvm-svn: 309397
2017-07-28 17:47:25 +02:00
|
|
|
|
2017-09-13 23:43:53 +02:00
|
|
|
using LoadDepVect = SmallVector<NonLocalDepResult, 64>;
|
|
|
|
using AvailValInBlkVect = SmallVector<gvn::AvailableValueInBlock, 64>;
|
|
|
|
using UnavailBlkVect = SmallVector<BasicBlock *, 64>;
|
2016-03-11 09:50:55 +01:00
|
|
|
|
2016-12-19 09:22:17 +01:00
|
|
|
bool runImpl(Function &F, AssumptionCache &RunAC, DominatorTree &RunDT,
|
2016-03-11 09:50:55 +01:00
|
|
|
const TargetLibraryInfo &RunTLI, AAResults &RunAA,
|
2016-12-01 17:40:32 +01:00
|
|
|
MemoryDependenceResults *RunMD, LoopInfo *LI,
|
2020-09-03 13:16:17 +02:00
|
|
|
OptimizationRemarkEmitter *ORE, MemorySSA *MSSA = nullptr);
|
2016-03-11 09:50:55 +01:00
|
|
|
|
|
|
|
/// Push a new Value to the LeaderTable onto the list for its value number.
|
|
|
|
void addToLeaderTable(uint32_t N, Value *V, const BasicBlock *BB) {
|
|
|
|
LeaderTableEntry &Curr = LeaderTable[N];
|
|
|
|
if (!Curr.Val) {
|
|
|
|
Curr.Val = V;
|
|
|
|
Curr.BB = BB;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
LeaderTableEntry *Node = TableAllocator.Allocate<LeaderTableEntry>();
|
|
|
|
Node->Val = V;
|
|
|
|
Node->BB = BB;
|
|
|
|
Node->Next = Curr.Next;
|
|
|
|
Curr.Next = Node;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Scan the list of values corresponding to a given
|
|
|
|
/// value number, and remove the given instruction if encountered.
|
|
|
|
void removeFromLeaderTable(uint32_t N, Instruction *I, BasicBlock *BB) {
|
|
|
|
LeaderTableEntry *Prev = nullptr;
|
|
|
|
LeaderTableEntry *Curr = &LeaderTable[N];
|
|
|
|
|
|
|
|
while (Curr && (Curr->Val != I || Curr->BB != BB)) {
|
|
|
|
Prev = Curr;
|
|
|
|
Curr = Curr->Next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Curr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (Prev) {
|
|
|
|
Prev->Next = Curr->Next;
|
|
|
|
} else {
|
|
|
|
if (!Curr->Next) {
|
|
|
|
Curr->Val = nullptr;
|
|
|
|
Curr->BB = nullptr;
|
|
|
|
} else {
|
|
|
|
LeaderTableEntry *Next = Curr->Next;
|
|
|
|
Curr->Val = Next->Val;
|
|
|
|
Curr->BB = Next->BB;
|
|
|
|
Curr->Next = Next->Next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// List of critical edges to be split between iterations.
|
2018-10-15 12:00:15 +02:00
|
|
|
SmallVector<std::pair<Instruction *, unsigned>, 4> toSplit;
|
2016-03-11 09:50:55 +01:00
|
|
|
|
|
|
|
// Helper functions of redundant load elimination
|
|
|
|
bool processLoad(LoadInst *L);
|
|
|
|
bool processNonLocalLoad(LoadInst *L);
|
2021-04-06 21:45:20 +02:00
|
|
|
bool processAssumeIntrinsic(AssumeInst *II);
|
2017-09-13 23:43:53 +02:00
|
|
|
|
2016-03-11 09:50:55 +01:00
|
|
|
/// Given a local dependency (Def or Clobber) determine if a value is
|
|
|
|
/// available for the load. Returns true if an value is known to be
|
|
|
|
/// available and populates Res. Returns false otherwise.
|
2021-04-01 07:31:57 +02:00
|
|
|
bool AnalyzeLoadAvailability(LoadInst *Load, MemDepResult DepInfo,
|
2016-03-11 09:50:55 +01:00
|
|
|
Value *Address, gvn::AvailableValue &Res);
|
2017-09-13 23:43:53 +02:00
|
|
|
|
2016-03-11 09:50:55 +01:00
|
|
|
/// Given a list of non-local dependencies, determine if a value is
|
|
|
|
/// available for the load in each specified block. If it is, add it to
|
|
|
|
/// ValuesPerBlock. If not, add it to UnavailableBlocks.
|
2021-04-01 07:31:57 +02:00
|
|
|
void AnalyzeLoadAvailability(LoadInst *Load, LoadDepVect &Deps,
|
2016-03-11 09:50:55 +01:00
|
|
|
AvailValInBlkVect &ValuesPerBlock,
|
|
|
|
UnavailBlkVect &UnavailableBlocks);
|
2017-09-13 23:43:53 +02:00
|
|
|
|
2021-04-01 07:31:57 +02:00
|
|
|
bool PerformLoadPRE(LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
|
2016-03-11 09:50:55 +01:00
|
|
|
UnavailBlkVect &UnavailableBlocks);
|
|
|
|
|
2021-04-09 10:22:47 +02:00
|
|
|
/// Eliminates partially redundant \p Load, replacing it with \p
|
|
|
|
/// AvailableLoads (connected by Phis if needed).
|
|
|
|
void eliminatePartiallyRedundantLoad(
|
|
|
|
LoadInst *Load, AvailValInBlkVect &ValuesPerBlock,
|
|
|
|
MapVector<BasicBlock *, Value *> &AvailableLoads);
|
|
|
|
|
2016-03-11 09:50:55 +01:00
|
|
|
// Other helper routines
|
|
|
|
bool processInstruction(Instruction *I);
|
|
|
|
bool processBlock(BasicBlock *BB);
|
2017-06-22 00:19:17 +02:00
|
|
|
void dump(DenseMap<uint32_t, Value *> &d) const;
|
2016-03-11 09:50:55 +01:00
|
|
|
bool iterateOnFunction(Function &F);
|
|
|
|
bool performPRE(Function &F);
|
|
|
|
bool performScalarPRE(Instruction *I);
|
|
|
|
bool performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
|
[GVN] Recommit the patch "Add phi-translate support in scalarpre"
Recommit after workaround the bug PR31652.
Three bugs fixed in previous recommits: The first one is to use CurrentBlock
instead of PREInstr's Parent as param of performScalarPREInsertion because
the Parent of a clone instruction may be uninitialized. The second one is stop
PRE when CurrentBlock to its predecessor is a backedge and an operand of CurInst
is defined inside of CurrentBlock. The same value defined inside of loop in last
iteration can not be regarded as available. The third one is an out-of-bound
array access in a flipped if guard.
Right now scalarpre doesn't have phi-translate support, so it will miss some
simple pre opportunities. Like the following testcase, current scalarpre cannot
recognize the last "a * b" is fully redundent because a and b used by the last
"a * b" expr are both defined by phis.
long a[100], b[100], g1, g2, g3;
__attribute__((pure)) long goo();
void foo(long a, long b, long c, long d) {
g1 = a * b;
if (__builtin_expect(g2 > 3, 0)) {
a = c;
b = d;
g2 = a * b;
}
g3 = a * b; // fully redundant.
}
The patch adds phi-translate support in scalarpre. This is only a temporary
solution before the newpre based on newgvn is available.
Differential Revision: https://reviews.llvm.org/D32252
llvm-svn: 309397
2017-07-28 17:47:25 +02:00
|
|
|
BasicBlock *Curr, unsigned int ValNo);
|
2016-03-11 09:50:55 +01:00
|
|
|
Value *findLeader(const BasicBlock *BB, uint32_t num);
|
|
|
|
void cleanupGlobalSets();
|
|
|
|
void verifyRemoved(const Instruction *I) const;
|
|
|
|
bool splitCriticalEdges();
|
|
|
|
BasicBlock *splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ);
|
2019-09-03 19:31:19 +02:00
|
|
|
bool replaceOperandsForInBlockEquality(Instruction *I) const;
|
2016-03-11 09:50:55 +01:00
|
|
|
bool propagateEquality(Value *LHS, Value *RHS, const BasicBlockEdge &Root,
|
|
|
|
bool DominatesByEdge);
|
|
|
|
bool processFoldableCondBr(BranchInst *BI);
|
|
|
|
void addDeadBlock(BasicBlock *BB);
|
|
|
|
void assignValNumForDeadCode();
|
[GVN] Recommit the patch "Add phi-translate support in scalarpre"
Recommit after workaround the bug PR31652.
Three bugs fixed in previous recommits: The first one is to use CurrentBlock
instead of PREInstr's Parent as param of performScalarPREInsertion because
the Parent of a clone instruction may be uninitialized. The second one is stop
PRE when CurrentBlock to its predecessor is a backedge and an operand of CurInst
is defined inside of CurrentBlock. The same value defined inside of loop in last
iteration can not be regarded as available. The third one is an out-of-bound
array access in a flipped if guard.
Right now scalarpre doesn't have phi-translate support, so it will miss some
simple pre opportunities. Like the following testcase, current scalarpre cannot
recognize the last "a * b" is fully redundent because a and b used by the last
"a * b" expr are both defined by phis.
long a[100], b[100], g1, g2, g3;
__attribute__((pure)) long goo();
void foo(long a, long b, long c, long d) {
g1 = a * b;
if (__builtin_expect(g2 > 3, 0)) {
a = c;
b = d;
g2 = a * b;
}
g3 = a * b; // fully redundant.
}
The patch adds phi-translate support in scalarpre. This is only a temporary
solution before the newpre based on newgvn is available.
Differential Revision: https://reviews.llvm.org/D32252
llvm-svn: 309397
2017-07-28 17:47:25 +02:00
|
|
|
void assignBlockRPONumber(Function &F);
|
2016-03-11 09:50:55 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Create a legacy GVN pass. This also allows parameterizing whether or not
|
2020-01-14 21:45:51 +01:00
|
|
|
/// MemDep is enabled.
|
|
|
|
FunctionPass *createGVNPass(bool NoMemDepAnalysis = false);
|
2016-03-11 09:50:55 +01:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// A simple and fast domtree-based GVN pass to hoist common expressions
|
2016-07-15 15:45:20 +02:00
|
|
|
/// from sibling branches.
|
|
|
|
struct GVNHoistPass : PassInfoMixin<GVNHoistPass> {
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Run the pass over the function.
|
2016-08-09 02:28:15 +02:00
|
|
|
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
|
2016-07-15 15:45:20 +02:00
|
|
|
};
|
2017-09-13 23:43:53 +02:00
|
|
|
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Uses an "inverted" value numbering to decide the similarity of
|
[GVNSink] GVNSink pass
This patch provides an initial prototype for a pass that sinks instructions based on GVN information, similar to GVNHoist. It is not yet ready for commiting but I've uploaded it to gather some initial thoughts.
This pass attempts to sink instructions into successors, reducing static
instruction count and enabling if-conversion.
We use a variant of global value numbering to decide what can be sunk.
Consider:
[ %a1 = add i32 %b, 1 ] [ %c1 = add i32 %d, 1 ]
[ %a2 = xor i32 %a1, 1 ] [ %c2 = xor i32 %c1, 1 ]
\ /
[ %e = phi i32 %a2, %c2 ]
[ add i32 %e, 4 ]
GVN would number %a1 and %c1 differently because they compute different
results - the VN of an instruction is a function of its opcode and the
transitive closure of its operands. This is the key property for hoisting
and CSE.
What we want when sinking however is for a numbering that is a function of
the *uses* of an instruction, which allows us to answer the question "if I
replace %a1 with %c1, will it contribute in an equivalent way to all
successive instructions?". The (new) PostValueTable class in GVN provides this
mapping.
This pass has some shown really impressive improvements especially for codesize already on internal benchmarks, so I have high hopes it can replace all the sinking logic in SimplifyCFG.
Differential revision: https://reviews.llvm.org/D24805
llvm-svn: 303850
2017-05-25 14:51:11 +02:00
|
|
|
/// expressions and sinks similar expressions into successors.
|
|
|
|
struct GVNSinkPass : PassInfoMixin<GVNSinkPass> {
|
2018-05-01 17:54:18 +02:00
|
|
|
/// Run the pass over the function.
|
[GVNSink] GVNSink pass
This patch provides an initial prototype for a pass that sinks instructions based on GVN information, similar to GVNHoist. It is not yet ready for commiting but I've uploaded it to gather some initial thoughts.
This pass attempts to sink instructions into successors, reducing static
instruction count and enabling if-conversion.
We use a variant of global value numbering to decide what can be sunk.
Consider:
[ %a1 = add i32 %b, 1 ] [ %c1 = add i32 %d, 1 ]
[ %a2 = xor i32 %a1, 1 ] [ %c2 = xor i32 %c1, 1 ]
\ /
[ %e = phi i32 %a2, %c2 ]
[ add i32 %e, 4 ]
GVN would number %a1 and %c1 differently because they compute different
results - the VN of an instruction is a function of its opcode and the
transitive closure of its operands. This is the key property for hoisting
and CSE.
What we want when sinking however is for a numbering that is a function of
the *uses* of an instruction, which allows us to answer the question "if I
replace %a1 with %c1, will it contribute in an equivalent way to all
successive instructions?". The (new) PostValueTable class in GVN provides this
mapping.
This pass has some shown really impressive improvements especially for codesize already on internal benchmarks, so I have high hopes it can replace all the sinking logic in SimplifyCFG.
Differential revision: https://reviews.llvm.org/D24805
llvm-svn: 303850
2017-05-25 14:51:11 +02:00
|
|
|
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
|
|
|
|
};
|
2016-03-11 09:50:55 +01:00
|
|
|
|
2017-09-13 23:43:53 +02:00
|
|
|
} // end namespace llvm
|
|
|
|
|
|
|
|
#endif // LLVM_TRANSFORMS_SCALAR_GVN_H
|