mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-02 00:16:25 +00:00
[EarlyCSE] Add debug counter for debugging mis-optimizations. NFC.
Reviewers: reames, spatel, davide, dberlin Subscribers: mcrosier, llvm-commits Differential Revision: https://reviews.llvm.org/D45162 llvm-svn: 329443
This commit is contained in:
parent
398e5f03a7
commit
18fcd57acc
@ -50,6 +50,7 @@
|
||||
#include "llvm/Support/AtomicOrdering.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/DebugCounter.h"
|
||||
#include "llvm/Support/RecyclingAllocator.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
@ -70,6 +71,9 @@ STATISTIC(NumCSELoad, "Number of load instructions CSE'd");
|
||||
STATISTIC(NumCSECall, "Number of call instructions CSE'd");
|
||||
STATISTIC(NumDSE, "Number of trivial dead stores removed");
|
||||
|
||||
DEBUG_COUNTER(CSECounter, "early-cse",
|
||||
"Controls which instructions are removed");
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SimpleValue
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -727,11 +731,15 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
|
||||
DEBUG(dbgs() << "EarlyCSE CVP: Add conditional value for '"
|
||||
<< CondInst->getName() << "' as " << *TorF << " in "
|
||||
<< BB->getName() << "\n");
|
||||
// Replace all dominated uses with the known value.
|
||||
if (unsigned Count = replaceDominatedUsesWith(
|
||||
CondInst, TorF, DT, BasicBlockEdge(Pred, BB))) {
|
||||
Changed = true;
|
||||
NumCSECVP += Count;
|
||||
if (!DebugCounter::shouldExecute(CSECounter)) {
|
||||
DEBUG(dbgs() << "Skipping due to debug counter\n");
|
||||
} else {
|
||||
// Replace all dominated uses with the known value.
|
||||
if (unsigned Count = replaceDominatedUsesWith(
|
||||
CondInst, TorF, DT, BasicBlockEdge(Pred, BB))) {
|
||||
Changed = true;
|
||||
NumCSECVP += Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -751,6 +759,10 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
|
||||
// Dead instructions should just be removed.
|
||||
if (isInstructionTriviallyDead(Inst, &TLI)) {
|
||||
DEBUG(dbgs() << "EarlyCSE DCE: " << *Inst << '\n');
|
||||
if (!DebugCounter::shouldExecute(CSECounter)) {
|
||||
DEBUG(dbgs() << "Skipping due to debug counter\n");
|
||||
continue;
|
||||
}
|
||||
salvageDebugInfo(*Inst);
|
||||
removeMSSA(Inst);
|
||||
Inst->eraseFromParent();
|
||||
@ -840,21 +852,25 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
|
||||
// its simpler value.
|
||||
if (Value *V = SimplifyInstruction(Inst, SQ)) {
|
||||
DEBUG(dbgs() << "EarlyCSE Simplify: " << *Inst << " to: " << *V << '\n');
|
||||
bool Killed = false;
|
||||
if (!Inst->use_empty()) {
|
||||
Inst->replaceAllUsesWith(V);
|
||||
Changed = true;
|
||||
if (!DebugCounter::shouldExecute(CSECounter)) {
|
||||
DEBUG(dbgs() << "Skipping due to debug counter\n");
|
||||
} else {
|
||||
bool Killed = false;
|
||||
if (!Inst->use_empty()) {
|
||||
Inst->replaceAllUsesWith(V);
|
||||
Changed = true;
|
||||
}
|
||||
if (isInstructionTriviallyDead(Inst, &TLI)) {
|
||||
removeMSSA(Inst);
|
||||
Inst->eraseFromParent();
|
||||
Changed = true;
|
||||
Killed = true;
|
||||
}
|
||||
if (Changed)
|
||||
++NumSimplify;
|
||||
if (Killed)
|
||||
continue;
|
||||
}
|
||||
if (isInstructionTriviallyDead(Inst, &TLI)) {
|
||||
removeMSSA(Inst);
|
||||
Inst->eraseFromParent();
|
||||
Changed = true;
|
||||
Killed = true;
|
||||
}
|
||||
if (Changed)
|
||||
++NumSimplify;
|
||||
if (Killed)
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this is a simple instruction that we can value number, process it.
|
||||
@ -862,6 +878,10 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
|
||||
// See if the instruction has an available value. If so, use it.
|
||||
if (Value *V = AvailableValues.lookup(Inst)) {
|
||||
DEBUG(dbgs() << "EarlyCSE CSE: " << *Inst << " to: " << *V << '\n');
|
||||
if (!DebugCounter::shouldExecute(CSECounter)) {
|
||||
DEBUG(dbgs() << "Skipping due to debug counter\n");
|
||||
continue;
|
||||
}
|
||||
if (auto *I = dyn_cast<Instruction>(V))
|
||||
I->andIRFlags(Inst);
|
||||
Inst->replaceAllUsesWith(V);
|
||||
@ -919,6 +939,10 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
|
||||
if (Op != nullptr) {
|
||||
DEBUG(dbgs() << "EarlyCSE CSE LOAD: " << *Inst
|
||||
<< " to: " << *InVal.DefInst << '\n');
|
||||
if (!DebugCounter::shouldExecute(CSECounter)) {
|
||||
DEBUG(dbgs() << "Skipping due to debug counter\n");
|
||||
continue;
|
||||
}
|
||||
if (!Inst->use_empty())
|
||||
Inst->replaceAllUsesWith(Op);
|
||||
removeMSSA(Inst);
|
||||
@ -958,6 +982,10 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
|
||||
Inst)) {
|
||||
DEBUG(dbgs() << "EarlyCSE CSE CALL: " << *Inst
|
||||
<< " to: " << *InVal.first << '\n');
|
||||
if (!DebugCounter::shouldExecute(CSECounter)) {
|
||||
DEBUG(dbgs() << "Skipping due to debug counter\n");
|
||||
continue;
|
||||
}
|
||||
if (!Inst->use_empty())
|
||||
Inst->replaceAllUsesWith(InVal.first);
|
||||
removeMSSA(Inst);
|
||||
@ -1009,6 +1037,10 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
|
||||
MSSA) &&
|
||||
"can't have an intervening store if not using MemorySSA!");
|
||||
DEBUG(dbgs() << "EarlyCSE DSE (writeback): " << *Inst << '\n');
|
||||
if (!DebugCounter::shouldExecute(CSECounter)) {
|
||||
DEBUG(dbgs() << "Skipping due to debug counter\n");
|
||||
continue;
|
||||
}
|
||||
removeMSSA(Inst);
|
||||
Inst->eraseFromParent();
|
||||
Changed = true;
|
||||
@ -1041,11 +1073,15 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
|
||||
if (LastStoreMemInst.isMatchingMemLoc(MemInst)) {
|
||||
DEBUG(dbgs() << "EarlyCSE DEAD STORE: " << *LastStore
|
||||
<< " due to: " << *Inst << '\n');
|
||||
removeMSSA(LastStore);
|
||||
LastStore->eraseFromParent();
|
||||
Changed = true;
|
||||
++NumDSE;
|
||||
LastStore = nullptr;
|
||||
if (!DebugCounter::shouldExecute(CSECounter)) {
|
||||
DEBUG(dbgs() << "Skipping due to debug counter\n");
|
||||
} else {
|
||||
removeMSSA(LastStore);
|
||||
LastStore->eraseFromParent();
|
||||
Changed = true;
|
||||
++NumDSE;
|
||||
LastStore = nullptr;
|
||||
}
|
||||
}
|
||||
// fallthrough - we can exploit information about this store
|
||||
}
|
||||
|
27
test/Other/debugcounter-earlycse.ll
Normal file
27
test/Other/debugcounter-earlycse.ll
Normal file
@ -0,0 +1,27 @@
|
||||
; REQUIRES: asserts
|
||||
; RUN: opt -S -debug-counter=early-cse-skip=1,early-cse-count=1 -early-cse < %s 2>&1 | FileCheck %s
|
||||
;; Test that, with debug counters on, we only optimize the second CSE opportunity.
|
||||
define i32 @test(i32 %a, i32 %b) {
|
||||
; CHECK-LABEL: @test(
|
||||
; CHECK-NEXT: bb:
|
||||
; CHECK-NEXT: %add1 = add i32 %a, %b
|
||||
; CHECK-NEXT: %add2 = add i32 %a, %b
|
||||
; CHECK-NEXT: %add4 = add i32 %a, %b
|
||||
; CHECK-NEXT: %ret1 = add i32 %add1, %add2
|
||||
; CHECK-NEXT: %ret2 = add i32 %add1, %add4
|
||||
; CHECK-NEXT: %ret = add i32 %ret1, %ret2
|
||||
; CHECK-NEXT: ret i32 %ret
|
||||
;
|
||||
bb:
|
||||
%add1 = add i32 %a, %b
|
||||
%add2 = add i32 %a, %b
|
||||
%add3 = add i32 %a, %b
|
||||
%add4 = add i32 %a, %b
|
||||
%ret1 = add i32 %add1, %add2
|
||||
%ret2 = add i32 %add3, %add4
|
||||
%ret = add i32 %ret1, %ret2
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user