mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-30 02:32:08 +00:00
851b04c920
This change, which allows @llvm.assume to be used from within computeKnownBits (and other associated functions in ValueTracking), adds some (optional) parameters to computeKnownBits and friends. These functions now (optionally) take a "context" instruction pointer, an AssumptionTracker pointer, and also a DomTree pointer, and most of the changes are just to pass this new information when it is easily available from InstSimplify, InstCombine, etc. As explained below, the significant conceptual change is that known properties of a value might depend on the control-flow location of the use (because we care that the @llvm.assume dominates the use because assumptions have control-flow dependencies). This means that, when we ask if bits are known in a value, we might get different answers for different uses. The significant changes are all in ValueTracking. Two main changes: First, as with the rest of the code, new parameters need to be passed around. To make this easier, I grouped them into a structure, and I made internal static versions of the relevant functions that take this structure as a parameter. The new code does as you might expect, it looks for @llvm.assume calls that make use of the value we're trying to learn something about (often indirectly), attempts to pattern match that expression, and uses the result if successful. By making use of the AssumptionTracker, the process of finding @llvm.assume calls is not expensive. Part of the structure being passed around inside ValueTracking is a set of already-considered @llvm.assume calls. This is to prevent a query using, for example, the assume(a == b), to recurse on itself. The context and DT params are used to find applicable assumptions. An assumption needs to dominate the context instruction, or come after it deterministically. In this latter case we only handle the specific case where both the assumption and the context instruction are in the same block, and we need to exclude assumptions from being used to simplify their own ephemeral values (those which contribute only to the assumption) because otherwise the assumption would prove its feeding comparison trivial and would be removed. This commit adds the plumbing and the logic for a simple masked-bit propagation (just enough to write a regression test). Future commits add more patterns (and, correspondingly, more regression tests). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217342 91177308-0d34-0410-b5e6-96231b3b80d8
194 lines
6.7 KiB
C++
194 lines
6.7 KiB
C++
//===- LoopInstSimplify.cpp - Loop Instruction Simplification Pass --------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This pass performs lightweight instruction simplification on loop bodies.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Transforms/Scalar.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/ADT/Statistic.h"
|
|
#include "llvm/Analysis/AssumptionTracker.h"
|
|
#include "llvm/Analysis/InstructionSimplify.h"
|
|
#include "llvm/Analysis/LoopInfo.h"
|
|
#include "llvm/Analysis/LoopPass.h"
|
|
#include "llvm/IR/DataLayout.h"
|
|
#include "llvm/IR/Dominators.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Target/TargetLibraryInfo.h"
|
|
#include "llvm/Transforms/Utils/Local.h"
|
|
using namespace llvm;
|
|
|
|
#define DEBUG_TYPE "loop-instsimplify"
|
|
|
|
STATISTIC(NumSimplified, "Number of redundant instructions simplified");
|
|
|
|
namespace {
|
|
class LoopInstSimplify : public LoopPass {
|
|
public:
|
|
static char ID; // Pass ID, replacement for typeid
|
|
LoopInstSimplify() : LoopPass(ID) {
|
|
initializeLoopInstSimplifyPass(*PassRegistry::getPassRegistry());
|
|
}
|
|
|
|
bool runOnLoop(Loop*, LPPassManager&) override;
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
|
AU.setPreservesCFG();
|
|
AU.addRequired<AssumptionTracker>();
|
|
AU.addRequired<LoopInfo>();
|
|
AU.addRequiredID(LoopSimplifyID);
|
|
AU.addPreservedID(LoopSimplifyID);
|
|
AU.addPreservedID(LCSSAID);
|
|
AU.addPreserved("scalar-evolution");
|
|
AU.addRequired<TargetLibraryInfo>();
|
|
}
|
|
};
|
|
}
|
|
|
|
char LoopInstSimplify::ID = 0;
|
|
INITIALIZE_PASS_BEGIN(LoopInstSimplify, "loop-instsimplify",
|
|
"Simplify instructions in loops", false, false)
|
|
INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)
|
|
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo)
|
|
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
|
INITIALIZE_PASS_DEPENDENCY(LoopInfo)
|
|
INITIALIZE_PASS_DEPENDENCY(LCSSA)
|
|
INITIALIZE_PASS_END(LoopInstSimplify, "loop-instsimplify",
|
|
"Simplify instructions in loops", false, false)
|
|
|
|
Pass *llvm::createLoopInstSimplifyPass() {
|
|
return new LoopInstSimplify();
|
|
}
|
|
|
|
bool LoopInstSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
|
|
if (skipOptnoneFunction(L))
|
|
return false;
|
|
|
|
DominatorTreeWrapperPass *DTWP =
|
|
getAnalysisIfAvailable<DominatorTreeWrapperPass>();
|
|
DominatorTree *DT = DTWP ? &DTWP->getDomTree() : nullptr;
|
|
LoopInfo *LI = &getAnalysis<LoopInfo>();
|
|
DataLayoutPass *DLP = getAnalysisIfAvailable<DataLayoutPass>();
|
|
const DataLayout *DL = DLP ? &DLP->getDataLayout() : nullptr;
|
|
const TargetLibraryInfo *TLI = &getAnalysis<TargetLibraryInfo>();
|
|
AssumptionTracker *AT = &getAnalysis<AssumptionTracker>();
|
|
|
|
SmallVector<BasicBlock*, 8> ExitBlocks;
|
|
L->getUniqueExitBlocks(ExitBlocks);
|
|
array_pod_sort(ExitBlocks.begin(), ExitBlocks.end());
|
|
|
|
SmallPtrSet<const Instruction*, 8> S1, S2, *ToSimplify = &S1, *Next = &S2;
|
|
|
|
// The bit we are stealing from the pointer represents whether this basic
|
|
// block is the header of a subloop, in which case we only process its phis.
|
|
typedef PointerIntPair<BasicBlock*, 1> WorklistItem;
|
|
SmallVector<WorklistItem, 16> VisitStack;
|
|
SmallPtrSet<BasicBlock*, 32> Visited;
|
|
|
|
bool Changed = false;
|
|
bool LocalChanged;
|
|
do {
|
|
LocalChanged = false;
|
|
|
|
VisitStack.clear();
|
|
Visited.clear();
|
|
|
|
VisitStack.push_back(WorklistItem(L->getHeader(), false));
|
|
|
|
while (!VisitStack.empty()) {
|
|
WorklistItem Item = VisitStack.pop_back_val();
|
|
BasicBlock *BB = Item.getPointer();
|
|
bool IsSubloopHeader = Item.getInt();
|
|
|
|
// Simplify instructions in the current basic block.
|
|
for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) {
|
|
Instruction *I = BI++;
|
|
|
|
// The first time through the loop ToSimplify is empty and we try to
|
|
// simplify all instructions. On later iterations ToSimplify is not
|
|
// empty and we only bother simplifying instructions that are in it.
|
|
if (!ToSimplify->empty() && !ToSimplify->count(I))
|
|
continue;
|
|
|
|
// Don't bother simplifying unused instructions.
|
|
if (!I->use_empty()) {
|
|
Value *V = SimplifyInstruction(I, DL, TLI, DT, AT);
|
|
if (V && LI->replacementPreservesLCSSAForm(I, V)) {
|
|
// Mark all uses for resimplification next time round the loop.
|
|
for (User *U : I->users())
|
|
Next->insert(cast<Instruction>(U));
|
|
|
|
I->replaceAllUsesWith(V);
|
|
LocalChanged = true;
|
|
++NumSimplified;
|
|
}
|
|
}
|
|
bool res = RecursivelyDeleteTriviallyDeadInstructions(I, TLI);
|
|
if (res) {
|
|
// RecursivelyDeleteTriviallyDeadInstruction can remove
|
|
// more than one instruction, so simply incrementing the
|
|
// iterator does not work. When instructions get deleted
|
|
// re-iterate instead.
|
|
BI = BB->begin(); BE = BB->end();
|
|
LocalChanged |= res;
|
|
}
|
|
|
|
if (IsSubloopHeader && !isa<PHINode>(I))
|
|
break;
|
|
}
|
|
|
|
// Add all successors to the worklist, except for loop exit blocks and the
|
|
// bodies of subloops. We visit the headers of loops so that we can process
|
|
// their phis, but we contract the rest of the subloop body and only follow
|
|
// edges leading back to the original loop.
|
|
for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE;
|
|
++SI) {
|
|
BasicBlock *SuccBB = *SI;
|
|
if (!Visited.insert(SuccBB))
|
|
continue;
|
|
|
|
const Loop *SuccLoop = LI->getLoopFor(SuccBB);
|
|
if (SuccLoop && SuccLoop->getHeader() == SuccBB
|
|
&& L->contains(SuccLoop)) {
|
|
VisitStack.push_back(WorklistItem(SuccBB, true));
|
|
|
|
SmallVector<BasicBlock*, 8> SubLoopExitBlocks;
|
|
SuccLoop->getExitBlocks(SubLoopExitBlocks);
|
|
|
|
for (unsigned i = 0; i < SubLoopExitBlocks.size(); ++i) {
|
|
BasicBlock *ExitBB = SubLoopExitBlocks[i];
|
|
if (LI->getLoopFor(ExitBB) == L && Visited.insert(ExitBB))
|
|
VisitStack.push_back(WorklistItem(ExitBB, false));
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
bool IsExitBlock = std::binary_search(ExitBlocks.begin(),
|
|
ExitBlocks.end(), SuccBB);
|
|
if (IsExitBlock)
|
|
continue;
|
|
|
|
VisitStack.push_back(WorklistItem(SuccBB, false));
|
|
}
|
|
}
|
|
|
|
// Place the list of instructions to simplify on the next loop iteration
|
|
// into ToSimplify.
|
|
std::swap(ToSimplify, Next);
|
|
Next->clear();
|
|
|
|
Changed |= LocalChanged;
|
|
} while (LocalChanged);
|
|
|
|
return Changed;
|
|
}
|