2008-04-20 20:35:01 +00:00
|
|
|
//===- JumpThreading.cpp - Thread control through conditional blocks ------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2008-04-20 21:13:06 +00:00
|
|
|
// This file implements the Jump Threading pass.
|
2008-04-20 20:35:01 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "jump-threading"
|
|
|
|
#include "llvm/Transforms/Scalar.h"
|
2008-04-20 21:13:06 +00:00
|
|
|
#include "llvm/IntrinsicInst.h"
|
2009-07-03 00:54:20 +00:00
|
|
|
#include "llvm/LLVMContext.h"
|
2008-04-20 20:35:01 +00:00
|
|
|
#include "llvm/Pass.h"
|
2008-12-01 04:48:07 +00:00
|
|
|
#include "llvm/Analysis/ConstantFolding.h"
|
2008-04-21 02:57:57 +00:00
|
|
|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
2008-04-20 22:39:42 +00:00
|
|
|
#include "llvm/Transforms/Utils/Local.h"
|
2008-12-01 04:48:07 +00:00
|
|
|
#include "llvm/Target/TargetData.h"
|
2009-05-04 18:40:41 +00:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
|
|
#include "llvm/ADT/Statistic.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
|
|
|
#include "llvm/ADT/SmallSet.h"
|
2008-04-20 20:35:01 +00:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
#include "llvm/Support/Compiler.h"
|
2008-04-20 21:13:06 +00:00
|
|
|
#include "llvm/Support/Debug.h"
|
2009-05-04 18:40:41 +00:00
|
|
|
#include "llvm/Support/ValueHandle.h"
|
2008-04-20 20:35:01 +00:00
|
|
|
using namespace llvm;
|
|
|
|
|
2008-04-20 22:39:42 +00:00
|
|
|
STATISTIC(NumThreads, "Number of jumps threaded");
|
|
|
|
STATISTIC(NumFolds, "Number of terminators folded");
|
2008-04-20 20:35:01 +00:00
|
|
|
|
2008-04-20 21:13:06 +00:00
|
|
|
static cl::opt<unsigned>
|
|
|
|
Threshold("jump-threading-threshold",
|
|
|
|
cl::desc("Max block size to duplicate for jump threading"),
|
|
|
|
cl::init(6), cl::Hidden);
|
|
|
|
|
2008-04-20 20:35:01 +00:00
|
|
|
namespace {
|
2008-05-09 04:43:13 +00:00
|
|
|
/// This pass performs 'jump threading', which looks at blocks that have
|
|
|
|
/// multiple predecessors and multiple successors. If one or more of the
|
|
|
|
/// predecessors of the block can be proven to always jump to one of the
|
|
|
|
/// successors, we forward the edge from the predecessor to the successor by
|
|
|
|
/// duplicating the contents of this block.
|
|
|
|
///
|
|
|
|
/// An example of when this can occur is code like this:
|
|
|
|
///
|
|
|
|
/// if () { ...
|
|
|
|
/// X = 4;
|
|
|
|
/// }
|
|
|
|
/// if (X < 3) {
|
|
|
|
///
|
|
|
|
/// In this case, the unconditional branch at the end of the first if can be
|
|
|
|
/// revectored to the false side of the second if.
|
|
|
|
///
|
2008-04-20 20:35:01 +00:00
|
|
|
class VISIBILITY_HIDDEN JumpThreading : public FunctionPass {
|
2008-12-01 04:48:07 +00:00
|
|
|
TargetData *TD;
|
2009-05-04 18:40:41 +00:00
|
|
|
#ifdef NDEBUG
|
|
|
|
SmallPtrSet<BasicBlock*, 16> LoopHeaders;
|
|
|
|
#else
|
|
|
|
SmallSet<AssertingVH<BasicBlock>, 16> LoopHeaders;
|
|
|
|
#endif
|
2008-04-20 20:35:01 +00:00
|
|
|
public:
|
|
|
|
static char ID; // Pass identification
|
2008-09-04 17:05:41 +00:00
|
|
|
JumpThreading() : FunctionPass(&ID) {}
|
2008-04-20 20:35:01 +00:00
|
|
|
|
2008-12-01 04:48:07 +00:00
|
|
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
|
|
|
AU.addRequired<TargetData>();
|
|
|
|
}
|
|
|
|
|
2008-04-20 20:35:01 +00:00
|
|
|
bool runOnFunction(Function &F);
|
2009-05-04 18:40:41 +00:00
|
|
|
void FindLoopHeaders(Function &F);
|
|
|
|
|
2008-11-27 07:20:04 +00:00
|
|
|
bool ProcessBlock(BasicBlock *BB);
|
2009-05-04 18:40:41 +00:00
|
|
|
bool ThreadEdge(BasicBlock *BB, BasicBlock *PredBB, BasicBlock *SuccBB,
|
|
|
|
unsigned JumpThreadCost);
|
2009-06-19 04:56:29 +00:00
|
|
|
BasicBlock *FactorCommonPHIPreds(PHINode *PN, Value *Val);
|
2008-12-03 07:48:08 +00:00
|
|
|
bool ProcessBranchOnDuplicateCond(BasicBlock *PredBB, BasicBlock *DestBB);
|
2008-12-04 06:31:07 +00:00
|
|
|
bool ProcessSwitchOnDuplicateCond(BasicBlock *PredBB, BasicBlock *DestBB);
|
Teach jump threading to thread through blocks like:
br (and X, phi(Y, Z, false)), label L1, label L2
This triggers once on 252.eon and 6 times on 176.gcc. Blocks
in question often look like this:
bb262: ; preds = %bb261, %bb248
%iftmp.251.0 = phi i1 [ true, %bb261 ], [ false, %bb248 ] ; <i1> [#uses=4]
%tmp270 = icmp eq %struct.rtx_def* %tmp.0.i, null ; <i1> [#uses=1]
%bothcond = or i1 %iftmp.251.0, %tmp270 ; <i1> [#uses=1]
br i1 %bothcond, label %bb288, label %bb273
In this case, it is clear that it doesn't matter if tmp.0.i is null when coming from bb261. When coming from bb248, it is all that matters.
Another random example:
check_asm_operands.exit: ; preds = %check_asm_operands.exit.thr_comm, %bb30.i, %bb12.i, %bb6.i413
%tmp.0.i420 = phi i1 [ true, %bb6.i413 ], [ true, %bb12.i ], [ true, %bb30.i ], [ false, %check_asm_operands.exit.thr_comm ; <i1> [#uses=1]
call void @llvm.stackrestore( i8* %savedstack ) nounwind
%tmp4389 = icmp eq i32 %added_sets_1.0, 0 ; <i1> [#uses=1]
%tmp4394 = icmp eq i32 %added_sets_2.0, 0 ; <i1> [#uses=1]
%bothcond80 = and i1 %tmp4389, %tmp4394 ; <i1> [#uses=1]
%bothcond81 = and i1 %bothcond80, %tmp.0.i420 ; <i1> [#uses=1]
br i1 %bothcond81, label %bb4398, label %bb4397
Here is the case from 252.eon:
bb290.i.i: ; preds = %bb23.i57.i.i, %bb8.i39.i.i, %bb100.i.i, %bb100.i.i, %bb85.i.i110
%myEOF.1.i.i = phi i1 [ true, %bb100.i.i ], [ true, %bb100.i.i ], [ true, %bb85.i.i110 ], [ true, %bb8.i39.i.i ], [ false, %bb23.i57.i.i ] ; <i1> [#uses=2]
%i.4.i.i = phi i32 [ %i.1.i.i, %bb85.i.i110 ], [ %i.0.i.i, %bb100.i.i ], [ %i.0.i.i, %bb100.i.i ], [ %i.3.i.i, %bb8.i39.i.i ], [ %i.3.i.i, %bb23.i57.i.i ] ; <i32> [#uses=3]
%tmp292.i.i = load i8* %tmp16.i.i100, align 1 ; <i8> [#uses=1]
%tmp293.not.i.i = icmp ne i8 %tmp292.i.i, 0 ; <i1> [#uses=1]
%bothcond.i.i = and i1 %tmp293.not.i.i, %myEOF.1.i.i ; <i1> [#uses=1]
br i1 %bothcond.i.i, label %bb202.i.i, label %bb301.i.i
Factoring out 3 common predecessors.
On the path from any blocks other than bb23.i57.i.i, the load and compare
are dead.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50096 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 07:05:46 +00:00
|
|
|
|
2008-04-22 06:36:15 +00:00
|
|
|
bool ProcessJumpOnPHI(PHINode *PN);
|
2008-04-22 20:46:09 +00:00
|
|
|
bool ProcessBranchOnLogical(Value *V, BasicBlock *BB, bool isAnd);
|
Start doing the significantly useful part of jump threading: handle cases
where a comparison has a phi input and that phi is a constant. For example,
stuff like:
Threading edge through bool from 'bb2149' to 'bb2231' with cost: 1, across block:
bb2237: ; preds = %bb2231, %bb2149
%tmp2328.rle = phi i32 [ %tmp2232, %bb2231 ], [ %tmp2232439, %bb2149 ] ; <i32> [#uses=2]
%done.0 = phi i32 [ %done.2, %bb2231 ], [ 0, %bb2149 ] ; <i32> [#uses=1]
%tmp2239 = icmp eq i32 %done.0, 0 ; <i1> [#uses=1]
br i1 %tmp2239, label %bb2231, label %bb2327
or
bb38.i298: ; preds = %bb33.i295, %bb1693
%tmp39.i296.rle = phi %struct.ibox* [ null, %bb1693 ], [ %tmp39.i296.rle1109, %bb33.i295 ] ; <%struct.ibox*> [#uses=2]
%minspan.1.i291.reg2mem.1 = phi i32 [ 32000, %bb1693 ], [ %minspan.0.i288, %bb33.i295 ] ; <i32> [#uses=1]
%tmp40.i297 = icmp eq %struct.ibox* %tmp39.i296.rle, null ; <i1> [#uses=1]
br i1 %tmp40.i297, label %implfeeds.exit311, label %bb43.i301
This triggers thousands of times in spec.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50110 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 21:40:39 +00:00
|
|
|
bool ProcessBranchOnCompare(CmpInst *Cmp, BasicBlock *BB);
|
2008-11-27 05:07:53 +00:00
|
|
|
|
|
|
|
bool SimplifyPartiallyRedundantLoad(LoadInst *LI);
|
2008-04-20 20:35:01 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2008-05-13 00:00:25 +00:00
|
|
|
char JumpThreading::ID = 0;
|
|
|
|
static RegisterPass<JumpThreading>
|
|
|
|
X("jump-threading", "Jump Threading");
|
|
|
|
|
2008-04-20 20:35:01 +00:00
|
|
|
// Public interface to the Jump Threading pass
|
|
|
|
FunctionPass *llvm::createJumpThreadingPass() { return new JumpThreading(); }
|
|
|
|
|
|
|
|
/// runOnFunction - Top level algorithm.
|
|
|
|
///
|
|
|
|
bool JumpThreading::runOnFunction(Function &F) {
|
2008-04-20 21:13:06 +00:00
|
|
|
DOUT << "Jump threading on function '" << F.getNameStart() << "'\n";
|
2008-12-01 04:48:07 +00:00
|
|
|
TD = &getAnalysis<TargetData>();
|
2008-04-20 22:39:42 +00:00
|
|
|
|
2009-05-04 18:40:41 +00:00
|
|
|
FindLoopHeaders(F);
|
|
|
|
|
2008-04-20 22:39:42 +00:00
|
|
|
bool AnotherIteration = true, EverChanged = false;
|
|
|
|
while (AnotherIteration) {
|
|
|
|
AnotherIteration = false;
|
|
|
|
bool Changed = false;
|
2008-12-03 07:48:08 +00:00
|
|
|
for (Function::iterator I = F.begin(), E = F.end(); I != E;) {
|
|
|
|
BasicBlock *BB = I;
|
|
|
|
while (ProcessBlock(BB))
|
2008-04-20 22:39:42 +00:00
|
|
|
Changed = true;
|
2008-12-03 07:48:08 +00:00
|
|
|
|
|
|
|
++I;
|
|
|
|
|
|
|
|
// If the block is trivially dead, zap it. This eliminates the successor
|
|
|
|
// edges which simplifies the CFG.
|
|
|
|
if (pred_begin(BB) == pred_end(BB) &&
|
2008-12-08 22:44:07 +00:00
|
|
|
BB != &BB->getParent()->getEntryBlock()) {
|
2008-12-03 07:48:08 +00:00
|
|
|
DOUT << " JT: Deleting dead block '" << BB->getNameStart()
|
|
|
|
<< "' with terminator: " << *BB->getTerminator();
|
2009-05-04 18:40:41 +00:00
|
|
|
LoopHeaders.erase(BB);
|
2008-12-03 07:48:08 +00:00
|
|
|
DeleteDeadBlock(BB);
|
|
|
|
Changed = true;
|
|
|
|
}
|
|
|
|
}
|
2008-04-20 22:39:42 +00:00
|
|
|
AnotherIteration = Changed;
|
|
|
|
EverChanged |= Changed;
|
|
|
|
}
|
2009-05-04 18:40:41 +00:00
|
|
|
|
|
|
|
LoopHeaders.clear();
|
2008-04-20 22:39:42 +00:00
|
|
|
return EverChanged;
|
2008-04-20 20:35:01 +00:00
|
|
|
}
|
2008-04-20 21:13:06 +00:00
|
|
|
|
2009-05-04 18:40:41 +00:00
|
|
|
/// FindLoopHeaders - We do not want jump threading to turn proper loop
|
|
|
|
/// structures into irreducible loops. Doing this breaks up the loop nesting
|
|
|
|
/// hierarchy and pessimizes later transformations. To prevent this from
|
|
|
|
/// happening, we first have to find the loop headers. Here we approximate this
|
|
|
|
/// by finding targets of backedges in the CFG.
|
|
|
|
///
|
|
|
|
/// Note that there definitely are cases when we want to allow threading of
|
|
|
|
/// edges across a loop header. For example, threading a jump from outside the
|
|
|
|
/// loop (the preheader) to an exit block of the loop is definitely profitable.
|
|
|
|
/// It is also almost always profitable to thread backedges from within the loop
|
|
|
|
/// to exit blocks, and is often profitable to thread backedges to other blocks
|
|
|
|
/// within the loop (forming a nested loop). This simple analysis is not rich
|
|
|
|
/// enough to track all of these properties and keep it up-to-date as the CFG
|
|
|
|
/// mutates, so we don't allow any of these transformations.
|
|
|
|
///
|
|
|
|
void JumpThreading::FindLoopHeaders(Function &F) {
|
|
|
|
SmallVector<std::pair<const BasicBlock*,const BasicBlock*>, 32> Edges;
|
|
|
|
FindFunctionBackedges(F, Edges);
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = Edges.size(); i != e; ++i)
|
|
|
|
LoopHeaders.insert(const_cast<BasicBlock*>(Edges[i].second));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Teach jump threading to thread through blocks like:
br (and X, phi(Y, Z, false)), label L1, label L2
This triggers once on 252.eon and 6 times on 176.gcc. Blocks
in question often look like this:
bb262: ; preds = %bb261, %bb248
%iftmp.251.0 = phi i1 [ true, %bb261 ], [ false, %bb248 ] ; <i1> [#uses=4]
%tmp270 = icmp eq %struct.rtx_def* %tmp.0.i, null ; <i1> [#uses=1]
%bothcond = or i1 %iftmp.251.0, %tmp270 ; <i1> [#uses=1]
br i1 %bothcond, label %bb288, label %bb273
In this case, it is clear that it doesn't matter if tmp.0.i is null when coming from bb261. When coming from bb248, it is all that matters.
Another random example:
check_asm_operands.exit: ; preds = %check_asm_operands.exit.thr_comm, %bb30.i, %bb12.i, %bb6.i413
%tmp.0.i420 = phi i1 [ true, %bb6.i413 ], [ true, %bb12.i ], [ true, %bb30.i ], [ false, %check_asm_operands.exit.thr_comm ; <i1> [#uses=1]
call void @llvm.stackrestore( i8* %savedstack ) nounwind
%tmp4389 = icmp eq i32 %added_sets_1.0, 0 ; <i1> [#uses=1]
%tmp4394 = icmp eq i32 %added_sets_2.0, 0 ; <i1> [#uses=1]
%bothcond80 = and i1 %tmp4389, %tmp4394 ; <i1> [#uses=1]
%bothcond81 = and i1 %bothcond80, %tmp.0.i420 ; <i1> [#uses=1]
br i1 %bothcond81, label %bb4398, label %bb4397
Here is the case from 252.eon:
bb290.i.i: ; preds = %bb23.i57.i.i, %bb8.i39.i.i, %bb100.i.i, %bb100.i.i, %bb85.i.i110
%myEOF.1.i.i = phi i1 [ true, %bb100.i.i ], [ true, %bb100.i.i ], [ true, %bb85.i.i110 ], [ true, %bb8.i39.i.i ], [ false, %bb23.i57.i.i ] ; <i1> [#uses=2]
%i.4.i.i = phi i32 [ %i.1.i.i, %bb85.i.i110 ], [ %i.0.i.i, %bb100.i.i ], [ %i.0.i.i, %bb100.i.i ], [ %i.3.i.i, %bb8.i39.i.i ], [ %i.3.i.i, %bb23.i57.i.i ] ; <i32> [#uses=3]
%tmp292.i.i = load i8* %tmp16.i.i100, align 1 ; <i8> [#uses=1]
%tmp293.not.i.i = icmp ne i8 %tmp292.i.i, 0 ; <i1> [#uses=1]
%bothcond.i.i = and i1 %tmp293.not.i.i, %myEOF.1.i.i ; <i1> [#uses=1]
br i1 %bothcond.i.i, label %bb202.i.i, label %bb301.i.i
Factoring out 3 common predecessors.
On the path from any blocks other than bb23.i57.i.i, the load and compare
are dead.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50096 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 07:05:46 +00:00
|
|
|
/// FactorCommonPHIPreds - If there are multiple preds with the same incoming
|
|
|
|
/// value for the PHI, factor them together so we get one block to thread for
|
|
|
|
/// the whole group.
|
|
|
|
/// This is important for things like "phi i1 [true, true, false, true, x]"
|
|
|
|
/// where we only need to clone the block for the true blocks once.
|
|
|
|
///
|
2009-06-19 04:56:29 +00:00
|
|
|
BasicBlock *JumpThreading::FactorCommonPHIPreds(PHINode *PN, Value *Val) {
|
Teach jump threading to thread through blocks like:
br (and X, phi(Y, Z, false)), label L1, label L2
This triggers once on 252.eon and 6 times on 176.gcc. Blocks
in question often look like this:
bb262: ; preds = %bb261, %bb248
%iftmp.251.0 = phi i1 [ true, %bb261 ], [ false, %bb248 ] ; <i1> [#uses=4]
%tmp270 = icmp eq %struct.rtx_def* %tmp.0.i, null ; <i1> [#uses=1]
%bothcond = or i1 %iftmp.251.0, %tmp270 ; <i1> [#uses=1]
br i1 %bothcond, label %bb288, label %bb273
In this case, it is clear that it doesn't matter if tmp.0.i is null when coming from bb261. When coming from bb248, it is all that matters.
Another random example:
check_asm_operands.exit: ; preds = %check_asm_operands.exit.thr_comm, %bb30.i, %bb12.i, %bb6.i413
%tmp.0.i420 = phi i1 [ true, %bb6.i413 ], [ true, %bb12.i ], [ true, %bb30.i ], [ false, %check_asm_operands.exit.thr_comm ; <i1> [#uses=1]
call void @llvm.stackrestore( i8* %savedstack ) nounwind
%tmp4389 = icmp eq i32 %added_sets_1.0, 0 ; <i1> [#uses=1]
%tmp4394 = icmp eq i32 %added_sets_2.0, 0 ; <i1> [#uses=1]
%bothcond80 = and i1 %tmp4389, %tmp4394 ; <i1> [#uses=1]
%bothcond81 = and i1 %bothcond80, %tmp.0.i420 ; <i1> [#uses=1]
br i1 %bothcond81, label %bb4398, label %bb4397
Here is the case from 252.eon:
bb290.i.i: ; preds = %bb23.i57.i.i, %bb8.i39.i.i, %bb100.i.i, %bb100.i.i, %bb85.i.i110
%myEOF.1.i.i = phi i1 [ true, %bb100.i.i ], [ true, %bb100.i.i ], [ true, %bb85.i.i110 ], [ true, %bb8.i39.i.i ], [ false, %bb23.i57.i.i ] ; <i1> [#uses=2]
%i.4.i.i = phi i32 [ %i.1.i.i, %bb85.i.i110 ], [ %i.0.i.i, %bb100.i.i ], [ %i.0.i.i, %bb100.i.i ], [ %i.3.i.i, %bb8.i39.i.i ], [ %i.3.i.i, %bb23.i57.i.i ] ; <i32> [#uses=3]
%tmp292.i.i = load i8* %tmp16.i.i100, align 1 ; <i8> [#uses=1]
%tmp293.not.i.i = icmp ne i8 %tmp292.i.i, 0 ; <i1> [#uses=1]
%bothcond.i.i = and i1 %tmp293.not.i.i, %myEOF.1.i.i ; <i1> [#uses=1]
br i1 %bothcond.i.i, label %bb202.i.i, label %bb301.i.i
Factoring out 3 common predecessors.
On the path from any blocks other than bb23.i57.i.i, the load and compare
are dead.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50096 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 07:05:46 +00:00
|
|
|
SmallVector<BasicBlock*, 16> CommonPreds;
|
|
|
|
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
|
2009-06-19 04:56:29 +00:00
|
|
|
if (PN->getIncomingValue(i) == Val)
|
Teach jump threading to thread through blocks like:
br (and X, phi(Y, Z, false)), label L1, label L2
This triggers once on 252.eon and 6 times on 176.gcc. Blocks
in question often look like this:
bb262: ; preds = %bb261, %bb248
%iftmp.251.0 = phi i1 [ true, %bb261 ], [ false, %bb248 ] ; <i1> [#uses=4]
%tmp270 = icmp eq %struct.rtx_def* %tmp.0.i, null ; <i1> [#uses=1]
%bothcond = or i1 %iftmp.251.0, %tmp270 ; <i1> [#uses=1]
br i1 %bothcond, label %bb288, label %bb273
In this case, it is clear that it doesn't matter if tmp.0.i is null when coming from bb261. When coming from bb248, it is all that matters.
Another random example:
check_asm_operands.exit: ; preds = %check_asm_operands.exit.thr_comm, %bb30.i, %bb12.i, %bb6.i413
%tmp.0.i420 = phi i1 [ true, %bb6.i413 ], [ true, %bb12.i ], [ true, %bb30.i ], [ false, %check_asm_operands.exit.thr_comm ; <i1> [#uses=1]
call void @llvm.stackrestore( i8* %savedstack ) nounwind
%tmp4389 = icmp eq i32 %added_sets_1.0, 0 ; <i1> [#uses=1]
%tmp4394 = icmp eq i32 %added_sets_2.0, 0 ; <i1> [#uses=1]
%bothcond80 = and i1 %tmp4389, %tmp4394 ; <i1> [#uses=1]
%bothcond81 = and i1 %bothcond80, %tmp.0.i420 ; <i1> [#uses=1]
br i1 %bothcond81, label %bb4398, label %bb4397
Here is the case from 252.eon:
bb290.i.i: ; preds = %bb23.i57.i.i, %bb8.i39.i.i, %bb100.i.i, %bb100.i.i, %bb85.i.i110
%myEOF.1.i.i = phi i1 [ true, %bb100.i.i ], [ true, %bb100.i.i ], [ true, %bb85.i.i110 ], [ true, %bb8.i39.i.i ], [ false, %bb23.i57.i.i ] ; <i1> [#uses=2]
%i.4.i.i = phi i32 [ %i.1.i.i, %bb85.i.i110 ], [ %i.0.i.i, %bb100.i.i ], [ %i.0.i.i, %bb100.i.i ], [ %i.3.i.i, %bb8.i39.i.i ], [ %i.3.i.i, %bb23.i57.i.i ] ; <i32> [#uses=3]
%tmp292.i.i = load i8* %tmp16.i.i100, align 1 ; <i8> [#uses=1]
%tmp293.not.i.i = icmp ne i8 %tmp292.i.i, 0 ; <i1> [#uses=1]
%bothcond.i.i = and i1 %tmp293.not.i.i, %myEOF.1.i.i ; <i1> [#uses=1]
br i1 %bothcond.i.i, label %bb202.i.i, label %bb301.i.i
Factoring out 3 common predecessors.
On the path from any blocks other than bb23.i57.i.i, the load and compare
are dead.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50096 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 07:05:46 +00:00
|
|
|
CommonPreds.push_back(PN->getIncomingBlock(i));
|
|
|
|
|
|
|
|
if (CommonPreds.size() == 1)
|
|
|
|
return CommonPreds[0];
|
|
|
|
|
|
|
|
DOUT << " Factoring out " << CommonPreds.size()
|
|
|
|
<< " common predecessors.\n";
|
|
|
|
return SplitBlockPredecessors(PN->getParent(),
|
|
|
|
&CommonPreds[0], CommonPreds.size(),
|
|
|
|
".thr_comm", this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-04-20 21:13:06 +00:00
|
|
|
/// getJumpThreadDuplicationCost - Return the cost of duplicating this block to
|
|
|
|
/// thread across it.
|
2008-04-20 22:39:42 +00:00
|
|
|
static unsigned getJumpThreadDuplicationCost(const BasicBlock *BB) {
|
2008-04-20 21:13:06 +00:00
|
|
|
/// Ignore PHI nodes, these will be flattened when duplication happens.
|
2008-05-23 21:05:58 +00:00
|
|
|
BasicBlock::const_iterator I = BB->getFirstNonPHI();
|
2008-04-20 21:13:06 +00:00
|
|
|
|
|
|
|
// Sum up the cost of each instruction until we get to the terminator. Don't
|
|
|
|
// include the terminator because the copy won't include it.
|
|
|
|
unsigned Size = 0;
|
|
|
|
for (; !isa<TerminatorInst>(I); ++I) {
|
|
|
|
// Debugger intrinsics don't incur code size.
|
|
|
|
if (isa<DbgInfoIntrinsic>(I)) continue;
|
|
|
|
|
|
|
|
// If this is a pointer->pointer bitcast, it is free.
|
|
|
|
if (isa<BitCastInst>(I) && isa<PointerType>(I->getType()))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// All other instructions count for at least one unit.
|
|
|
|
++Size;
|
|
|
|
|
|
|
|
// Calls are more expensive. If they are non-intrinsic calls, we model them
|
|
|
|
// as having cost of 4. If they are a non-vector intrinsic, we model them
|
|
|
|
// as having cost of 2 total, and if they are a vector intrinsic, we model
|
|
|
|
// them as having cost 1.
|
|
|
|
if (const CallInst *CI = dyn_cast<CallInst>(I)) {
|
|
|
|
if (!isa<IntrinsicInst>(CI))
|
|
|
|
Size += 3;
|
2009-07-02 15:39:39 +00:00
|
|
|
else if (!isa<VectorType>(CI->getType()))
|
2008-04-20 21:13:06 +00:00
|
|
|
Size += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Threading through a switch statement is particularly profitable. If this
|
|
|
|
// block ends in a switch, decrease its cost to make it more likely to happen.
|
|
|
|
if (isa<SwitchInst>(I))
|
|
|
|
Size = Size > 6 ? Size-6 : 0;
|
|
|
|
|
|
|
|
return Size;
|
|
|
|
}
|
|
|
|
|
2008-11-27 07:20:04 +00:00
|
|
|
/// ProcessBlock - If there are any predecessors whose control can be threaded
|
2008-04-20 21:13:06 +00:00
|
|
|
/// through to a successor, transform them now.
|
2008-11-27 07:20:04 +00:00
|
|
|
bool JumpThreading::ProcessBlock(BasicBlock *BB) {
|
2008-11-27 05:07:53 +00:00
|
|
|
// If this block has a single predecessor, and if that pred has a single
|
|
|
|
// successor, merge the blocks. This encourages recursive jump threading
|
|
|
|
// because now the condition in this block can be threaded through
|
|
|
|
// predecessors of our predecessor block.
|
|
|
|
if (BasicBlock *SinglePred = BB->getSinglePredecessor())
|
2008-11-28 19:54:49 +00:00
|
|
|
if (SinglePred->getTerminator()->getNumSuccessors() == 1 &&
|
|
|
|
SinglePred != BB) {
|
2009-05-04 18:40:41 +00:00
|
|
|
// If SinglePred was a loop header, BB becomes one.
|
|
|
|
if (LoopHeaders.erase(SinglePred))
|
|
|
|
LoopHeaders.insert(BB);
|
|
|
|
|
2008-11-27 19:25:19 +00:00
|
|
|
// Remember if SinglePred was the entry block of the function. If so, we
|
|
|
|
// will need to move BB back to the entry position.
|
|
|
|
bool isEntry = SinglePred == &SinglePred->getParent()->getEntryBlock();
|
2008-11-27 05:07:53 +00:00
|
|
|
MergeBasicBlockIntoOnlyPred(BB);
|
2008-11-27 19:25:19 +00:00
|
|
|
|
|
|
|
if (isEntry && BB != &BB->getParent()->getEntryBlock())
|
|
|
|
BB->moveBefore(&BB->getParent()->getEntryBlock());
|
2008-11-27 05:07:53 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-05-20 07:26:45 +00:00
|
|
|
// See if this block ends with a branch or switch. If so, see if the
|
2008-04-20 21:13:06 +00:00
|
|
|
// condition is a phi node. If so, and if an entry of the phi node is a
|
|
|
|
// constant, we can thread the block.
|
|
|
|
Value *Condition;
|
2008-04-20 22:39:42 +00:00
|
|
|
if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator())) {
|
|
|
|
// Can't thread an unconditional jump.
|
|
|
|
if (BI->isUnconditional()) return false;
|
2008-04-20 21:13:06 +00:00
|
|
|
Condition = BI->getCondition();
|
2008-04-20 22:39:42 +00:00
|
|
|
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(BB->getTerminator()))
|
2008-04-20 21:13:06 +00:00
|
|
|
Condition = SI->getCondition();
|
|
|
|
else
|
|
|
|
return false; // Must be an invoke.
|
2008-04-20 22:39:42 +00:00
|
|
|
|
|
|
|
// If the terminator of this block is branching on a constant, simplify the
|
2008-04-21 18:25:01 +00:00
|
|
|
// terminator to an unconditional branch. This can occur due to threading in
|
2008-04-20 22:39:42 +00:00
|
|
|
// other blocks.
|
|
|
|
if (isa<ConstantInt>(Condition)) {
|
|
|
|
DOUT << " In block '" << BB->getNameStart()
|
|
|
|
<< "' folding terminator: " << *BB->getTerminator();
|
|
|
|
++NumFolds;
|
|
|
|
ConstantFoldTerminator(BB);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-12-03 07:48:08 +00:00
|
|
|
// If the terminator is branching on an undef, we can pick any of the
|
|
|
|
// successors to branch to. Since this is arbitrary, we pick the successor
|
|
|
|
// with the fewest predecessors. This should reduce the in-degree of the
|
|
|
|
// others.
|
|
|
|
if (isa<UndefValue>(Condition)) {
|
|
|
|
TerminatorInst *BBTerm = BB->getTerminator();
|
|
|
|
unsigned MinSucc = 0;
|
|
|
|
BasicBlock *TestBB = BBTerm->getSuccessor(MinSucc);
|
|
|
|
// Compute the successor with the minimum number of predecessors.
|
|
|
|
unsigned MinNumPreds = std::distance(pred_begin(TestBB), pred_end(TestBB));
|
|
|
|
for (unsigned i = 1, e = BBTerm->getNumSuccessors(); i != e; ++i) {
|
|
|
|
TestBB = BBTerm->getSuccessor(i);
|
|
|
|
unsigned NumPreds = std::distance(pred_begin(TestBB), pred_end(TestBB));
|
|
|
|
if (NumPreds < MinNumPreds)
|
|
|
|
MinSucc = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fold the branch/switch.
|
|
|
|
for (unsigned i = 0, e = BBTerm->getNumSuccessors(); i != e; ++i) {
|
|
|
|
if (i == MinSucc) continue;
|
|
|
|
BBTerm->getSuccessor(i)->removePredecessor(BB);
|
|
|
|
}
|
|
|
|
|
|
|
|
DOUT << " In block '" << BB->getNameStart()
|
|
|
|
<< "' folding undef terminator: " << *BBTerm;
|
|
|
|
BranchInst::Create(BBTerm->getSuccessor(MinSucc), BBTerm);
|
|
|
|
BBTerm->eraseFromParent();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Instruction *CondInst = dyn_cast<Instruction>(Condition);
|
|
|
|
|
|
|
|
// If the condition is an instruction defined in another block, see if a
|
|
|
|
// predecessor has the same condition:
|
|
|
|
// br COND, BBX, BBY
|
|
|
|
// BBX:
|
|
|
|
// br COND, BBZ, BBW
|
|
|
|
if (!Condition->hasOneUse() && // Multiple uses.
|
|
|
|
(CondInst == 0 || CondInst->getParent() != BB)) { // Non-local definition.
|
|
|
|
pred_iterator PI = pred_begin(BB), E = pred_end(BB);
|
|
|
|
if (isa<BranchInst>(BB->getTerminator())) {
|
|
|
|
for (; PI != E; ++PI)
|
|
|
|
if (BranchInst *PBI = dyn_cast<BranchInst>((*PI)->getTerminator()))
|
|
|
|
if (PBI->isConditional() && PBI->getCondition() == Condition &&
|
|
|
|
ProcessBranchOnDuplicateCond(*PI, BB))
|
|
|
|
return true;
|
2008-12-04 06:31:07 +00:00
|
|
|
} else {
|
|
|
|
assert(isa<SwitchInst>(BB->getTerminator()) && "Unknown jump terminator");
|
|
|
|
for (; PI != E; ++PI)
|
|
|
|
if (SwitchInst *PSI = dyn_cast<SwitchInst>((*PI)->getTerminator()))
|
|
|
|
if (PSI->getCondition() == Condition &&
|
|
|
|
ProcessSwitchOnDuplicateCond(*PI, BB))
|
|
|
|
return true;
|
2008-12-03 07:48:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// All the rest of our checks depend on the condition being an instruction.
|
|
|
|
if (CondInst == 0)
|
|
|
|
return false;
|
|
|
|
|
2008-04-20 21:13:06 +00:00
|
|
|
// See if this is a phi node in the current block.
|
2008-12-03 07:48:08 +00:00
|
|
|
if (PHINode *PN = dyn_cast<PHINode>(CondInst))
|
|
|
|
if (PN->getParent() == BB)
|
|
|
|
return ProcessJumpOnPHI(PN);
|
2008-04-20 21:13:06 +00:00
|
|
|
|
Teach jump threading to thread through blocks like:
br (and X, phi(Y, Z, false)), label L1, label L2
This triggers once on 252.eon and 6 times on 176.gcc. Blocks
in question often look like this:
bb262: ; preds = %bb261, %bb248
%iftmp.251.0 = phi i1 [ true, %bb261 ], [ false, %bb248 ] ; <i1> [#uses=4]
%tmp270 = icmp eq %struct.rtx_def* %tmp.0.i, null ; <i1> [#uses=1]
%bothcond = or i1 %iftmp.251.0, %tmp270 ; <i1> [#uses=1]
br i1 %bothcond, label %bb288, label %bb273
In this case, it is clear that it doesn't matter if tmp.0.i is null when coming from bb261. When coming from bb248, it is all that matters.
Another random example:
check_asm_operands.exit: ; preds = %check_asm_operands.exit.thr_comm, %bb30.i, %bb12.i, %bb6.i413
%tmp.0.i420 = phi i1 [ true, %bb6.i413 ], [ true, %bb12.i ], [ true, %bb30.i ], [ false, %check_asm_operands.exit.thr_comm ; <i1> [#uses=1]
call void @llvm.stackrestore( i8* %savedstack ) nounwind
%tmp4389 = icmp eq i32 %added_sets_1.0, 0 ; <i1> [#uses=1]
%tmp4394 = icmp eq i32 %added_sets_2.0, 0 ; <i1> [#uses=1]
%bothcond80 = and i1 %tmp4389, %tmp4394 ; <i1> [#uses=1]
%bothcond81 = and i1 %bothcond80, %tmp.0.i420 ; <i1> [#uses=1]
br i1 %bothcond81, label %bb4398, label %bb4397
Here is the case from 252.eon:
bb290.i.i: ; preds = %bb23.i57.i.i, %bb8.i39.i.i, %bb100.i.i, %bb100.i.i, %bb85.i.i110
%myEOF.1.i.i = phi i1 [ true, %bb100.i.i ], [ true, %bb100.i.i ], [ true, %bb85.i.i110 ], [ true, %bb8.i39.i.i ], [ false, %bb23.i57.i.i ] ; <i1> [#uses=2]
%i.4.i.i = phi i32 [ %i.1.i.i, %bb85.i.i110 ], [ %i.0.i.i, %bb100.i.i ], [ %i.0.i.i, %bb100.i.i ], [ %i.3.i.i, %bb8.i39.i.i ], [ %i.3.i.i, %bb23.i57.i.i ] ; <i32> [#uses=3]
%tmp292.i.i = load i8* %tmp16.i.i100, align 1 ; <i8> [#uses=1]
%tmp293.not.i.i = icmp ne i8 %tmp292.i.i, 0 ; <i1> [#uses=1]
%bothcond.i.i = and i1 %tmp293.not.i.i, %myEOF.1.i.i ; <i1> [#uses=1]
br i1 %bothcond.i.i, label %bb202.i.i, label %bb301.i.i
Factoring out 3 common predecessors.
On the path from any blocks other than bb23.i57.i.i, the load and compare
are dead.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50096 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 07:05:46 +00:00
|
|
|
// If this is a conditional branch whose condition is and/or of a phi, try to
|
|
|
|
// simplify it.
|
2008-12-03 07:48:08 +00:00
|
|
|
if ((CondInst->getOpcode() == Instruction::And ||
|
|
|
|
CondInst->getOpcode() == Instruction::Or) &&
|
|
|
|
isa<BranchInst>(BB->getTerminator()) &&
|
|
|
|
ProcessBranchOnLogical(CondInst, BB,
|
|
|
|
CondInst->getOpcode() == Instruction::And))
|
|
|
|
return true;
|
Teach jump threading to thread through blocks like:
br (and X, phi(Y, Z, false)), label L1, label L2
This triggers once on 252.eon and 6 times on 176.gcc. Blocks
in question often look like this:
bb262: ; preds = %bb261, %bb248
%iftmp.251.0 = phi i1 [ true, %bb261 ], [ false, %bb248 ] ; <i1> [#uses=4]
%tmp270 = icmp eq %struct.rtx_def* %tmp.0.i, null ; <i1> [#uses=1]
%bothcond = or i1 %iftmp.251.0, %tmp270 ; <i1> [#uses=1]
br i1 %bothcond, label %bb288, label %bb273
In this case, it is clear that it doesn't matter if tmp.0.i is null when coming from bb261. When coming from bb248, it is all that matters.
Another random example:
check_asm_operands.exit: ; preds = %check_asm_operands.exit.thr_comm, %bb30.i, %bb12.i, %bb6.i413
%tmp.0.i420 = phi i1 [ true, %bb6.i413 ], [ true, %bb12.i ], [ true, %bb30.i ], [ false, %check_asm_operands.exit.thr_comm ; <i1> [#uses=1]
call void @llvm.stackrestore( i8* %savedstack ) nounwind
%tmp4389 = icmp eq i32 %added_sets_1.0, 0 ; <i1> [#uses=1]
%tmp4394 = icmp eq i32 %added_sets_2.0, 0 ; <i1> [#uses=1]
%bothcond80 = and i1 %tmp4389, %tmp4394 ; <i1> [#uses=1]
%bothcond81 = and i1 %bothcond80, %tmp.0.i420 ; <i1> [#uses=1]
br i1 %bothcond81, label %bb4398, label %bb4397
Here is the case from 252.eon:
bb290.i.i: ; preds = %bb23.i57.i.i, %bb8.i39.i.i, %bb100.i.i, %bb100.i.i, %bb85.i.i110
%myEOF.1.i.i = phi i1 [ true, %bb100.i.i ], [ true, %bb100.i.i ], [ true, %bb85.i.i110 ], [ true, %bb8.i39.i.i ], [ false, %bb23.i57.i.i ] ; <i1> [#uses=2]
%i.4.i.i = phi i32 [ %i.1.i.i, %bb85.i.i110 ], [ %i.0.i.i, %bb100.i.i ], [ %i.0.i.i, %bb100.i.i ], [ %i.3.i.i, %bb8.i39.i.i ], [ %i.3.i.i, %bb23.i57.i.i ] ; <i32> [#uses=3]
%tmp292.i.i = load i8* %tmp16.i.i100, align 1 ; <i8> [#uses=1]
%tmp293.not.i.i = icmp ne i8 %tmp292.i.i, 0 ; <i1> [#uses=1]
%bothcond.i.i = and i1 %tmp293.not.i.i, %myEOF.1.i.i ; <i1> [#uses=1]
br i1 %bothcond.i.i, label %bb202.i.i, label %bb301.i.i
Factoring out 3 common predecessors.
On the path from any blocks other than bb23.i57.i.i, the load and compare
are dead.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50096 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 07:05:46 +00:00
|
|
|
|
2009-06-19 04:56:29 +00:00
|
|
|
if (CmpInst *CondCmp = dyn_cast<CmpInst>(CondInst)) {
|
|
|
|
if (isa<PHINode>(CondCmp->getOperand(0))) {
|
|
|
|
// If we have "br (phi != 42)" and the phi node has any constant values
|
|
|
|
// as operands, we can thread through this block.
|
|
|
|
//
|
|
|
|
// If we have "br (cmp phi, x)" and the phi node contains x such that the
|
|
|
|
// comparison uniquely identifies the branch target, we can thread
|
|
|
|
// through this block.
|
|
|
|
|
|
|
|
if (ProcessBranchOnCompare(CondCmp, BB))
|
|
|
|
return true;
|
|
|
|
}
|
2009-06-19 16:27:56 +00:00
|
|
|
|
|
|
|
// If we have a comparison, loop over the predecessors to see if there is
|
|
|
|
// a condition with the same value.
|
|
|
|
pred_iterator PI = pred_begin(BB), E = pred_end(BB);
|
|
|
|
for (; PI != E; ++PI)
|
|
|
|
if (BranchInst *PBI = dyn_cast<BranchInst>((*PI)->getTerminator()))
|
|
|
|
if (PBI->isConditional() && *PI != BB) {
|
|
|
|
if (CmpInst *CI = dyn_cast<CmpInst>(PBI->getCondition())) {
|
|
|
|
if (CI->getOperand(0) == CondCmp->getOperand(0) &&
|
|
|
|
CI->getOperand(1) == CondCmp->getOperand(1) &&
|
|
|
|
CI->getPredicate() == CondCmp->getPredicate()) {
|
|
|
|
// TODO: Could handle things like (x != 4) --> (x == 17)
|
|
|
|
if (ProcessBranchOnDuplicateCond(*PI, BB))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-06-19 04:56:29 +00:00
|
|
|
}
|
2008-11-27 05:07:53 +00:00
|
|
|
|
|
|
|
// Check for some cases that are worth simplifying. Right now we want to look
|
|
|
|
// for loads that are used by a switch or by the condition for the branch. If
|
|
|
|
// we see one, check to see if it's partially redundant. If so, insert a PHI
|
|
|
|
// which can then be used to thread the values.
|
|
|
|
//
|
|
|
|
// This is particularly important because reg2mem inserts loads and stores all
|
|
|
|
// over the place, and this blocks jump threading if we don't zap them.
|
2008-12-03 07:48:08 +00:00
|
|
|
Value *SimplifyValue = CondInst;
|
2008-11-27 05:07:53 +00:00
|
|
|
if (CmpInst *CondCmp = dyn_cast<CmpInst>(SimplifyValue))
|
|
|
|
if (isa<Constant>(CondCmp->getOperand(1)))
|
|
|
|
SimplifyValue = CondCmp->getOperand(0);
|
|
|
|
|
|
|
|
if (LoadInst *LI = dyn_cast<LoadInst>(SimplifyValue))
|
|
|
|
if (SimplifyPartiallyRedundantLoad(LI))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// TODO: If we have: "br (X > 0)" and we have a predecessor where we know
|
|
|
|
// "(X == 4)" thread through this block.
|
Start doing the significantly useful part of jump threading: handle cases
where a comparison has a phi input and that phi is a constant. For example,
stuff like:
Threading edge through bool from 'bb2149' to 'bb2231' with cost: 1, across block:
bb2237: ; preds = %bb2231, %bb2149
%tmp2328.rle = phi i32 [ %tmp2232, %bb2231 ], [ %tmp2232439, %bb2149 ] ; <i32> [#uses=2]
%done.0 = phi i32 [ %done.2, %bb2231 ], [ 0, %bb2149 ] ; <i32> [#uses=1]
%tmp2239 = icmp eq i32 %done.0, 0 ; <i1> [#uses=1]
br i1 %tmp2239, label %bb2231, label %bb2327
or
bb38.i298: ; preds = %bb33.i295, %bb1693
%tmp39.i296.rle = phi %struct.ibox* [ null, %bb1693 ], [ %tmp39.i296.rle1109, %bb33.i295 ] ; <%struct.ibox*> [#uses=2]
%minspan.1.i291.reg2mem.1 = phi i32 [ 32000, %bb1693 ], [ %minspan.0.i288, %bb33.i295 ] ; <i32> [#uses=1]
%tmp40.i297 = icmp eq %struct.ibox* %tmp39.i296.rle, null ; <i1> [#uses=1]
br i1 %tmp40.i297, label %implfeeds.exit311, label %bb43.i301
This triggers thousands of times in spec.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50110 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 21:40:39 +00:00
|
|
|
|
2008-04-22 06:36:15 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-12-03 07:48:08 +00:00
|
|
|
/// ProcessBranchOnDuplicateCond - We found a block and a predecessor of that
|
|
|
|
/// block that jump on exactly the same condition. This means that we almost
|
|
|
|
/// always know the direction of the edge in the DESTBB:
|
|
|
|
/// PREDBB:
|
|
|
|
/// br COND, DESTBB, BBY
|
|
|
|
/// DESTBB:
|
|
|
|
/// br COND, BBZ, BBW
|
|
|
|
///
|
|
|
|
/// If DESTBB has multiple predecessors, we can't just constant fold the branch
|
|
|
|
/// in DESTBB, we have to thread over it.
|
|
|
|
bool JumpThreading::ProcessBranchOnDuplicateCond(BasicBlock *PredBB,
|
|
|
|
BasicBlock *BB) {
|
|
|
|
BranchInst *PredBI = cast<BranchInst>(PredBB->getTerminator());
|
|
|
|
|
|
|
|
// If both successors of PredBB go to DESTBB, we don't know anything. We can
|
|
|
|
// fold the branch to an unconditional one, which allows other recursive
|
|
|
|
// simplifications.
|
|
|
|
bool BranchDir;
|
|
|
|
if (PredBI->getSuccessor(1) != BB)
|
|
|
|
BranchDir = true;
|
|
|
|
else if (PredBI->getSuccessor(0) != BB)
|
|
|
|
BranchDir = false;
|
|
|
|
else {
|
|
|
|
DOUT << " In block '" << PredBB->getNameStart()
|
|
|
|
<< "' folding terminator: " << *PredBB->getTerminator();
|
|
|
|
++NumFolds;
|
|
|
|
ConstantFoldTerminator(PredBB);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
BranchInst *DestBI = cast<BranchInst>(BB->getTerminator());
|
|
|
|
|
|
|
|
// If the dest block has one predecessor, just fix the branch condition to a
|
|
|
|
// constant and fold it.
|
|
|
|
if (BB->getSinglePredecessor()) {
|
|
|
|
DOUT << " In block '" << BB->getNameStart()
|
|
|
|
<< "' folding condition to '" << BranchDir << "': "
|
|
|
|
<< *BB->getTerminator();
|
|
|
|
++NumFolds;
|
2009-07-03 00:54:20 +00:00
|
|
|
DestBI->setCondition(Context->getConstantInt(Type::Int1Ty, BranchDir));
|
2008-12-03 07:48:08 +00:00
|
|
|
ConstantFoldTerminator(BB);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise we need to thread from PredBB to DestBB's successor which
|
|
|
|
// involves code duplication. Check to see if it is worth it.
|
|
|
|
unsigned JumpThreadCost = getJumpThreadDuplicationCost(BB);
|
|
|
|
if (JumpThreadCost > Threshold) {
|
|
|
|
DOUT << " Not threading BB '" << BB->getNameStart()
|
|
|
|
<< "' - Cost is too high: " << JumpThreadCost << "\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next, figure out which successor we are threading to.
|
|
|
|
BasicBlock *SuccBB = DestBI->getSuccessor(!BranchDir);
|
|
|
|
|
2009-05-04 18:40:41 +00:00
|
|
|
// Ok, try to thread it!
|
|
|
|
return ThreadEdge(BB, PredBB, SuccBB, JumpThreadCost);
|
2008-12-03 07:48:08 +00:00
|
|
|
}
|
|
|
|
|
2008-12-04 06:31:07 +00:00
|
|
|
/// ProcessSwitchOnDuplicateCond - We found a block and a predecessor of that
|
|
|
|
/// block that switch on exactly the same condition. This means that we almost
|
|
|
|
/// always know the direction of the edge in the DESTBB:
|
|
|
|
/// PREDBB:
|
|
|
|
/// switch COND [... DESTBB, BBY ... ]
|
|
|
|
/// DESTBB:
|
|
|
|
/// switch COND [... BBZ, BBW ]
|
|
|
|
///
|
|
|
|
/// Optimizing switches like this is very important, because simplifycfg builds
|
|
|
|
/// switches out of repeated 'if' conditions.
|
|
|
|
bool JumpThreading::ProcessSwitchOnDuplicateCond(BasicBlock *PredBB,
|
|
|
|
BasicBlock *DestBB) {
|
2009-01-19 21:20:34 +00:00
|
|
|
// Can't thread edge to self.
|
|
|
|
if (PredBB == DestBB)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
2008-12-04 06:31:07 +00:00
|
|
|
SwitchInst *PredSI = cast<SwitchInst>(PredBB->getTerminator());
|
|
|
|
SwitchInst *DestSI = cast<SwitchInst>(DestBB->getTerminator());
|
|
|
|
|
|
|
|
// There are a variety of optimizations that we can potentially do on these
|
|
|
|
// blocks: we order them from most to least preferable.
|
|
|
|
|
|
|
|
// If DESTBB *just* contains the switch, then we can forward edges from PREDBB
|
|
|
|
// directly to their destination. This does not introduce *any* code size
|
2009-03-17 00:38:24 +00:00
|
|
|
// growth. Skip debug info first.
|
|
|
|
BasicBlock::iterator BBI = DestBB->begin();
|
|
|
|
while (isa<DbgInfoIntrinsic>(BBI))
|
|
|
|
BBI++;
|
2008-12-04 06:31:07 +00:00
|
|
|
|
|
|
|
// FIXME: Thread if it just contains a PHI.
|
2009-03-17 00:38:24 +00:00
|
|
|
if (isa<SwitchInst>(BBI)) {
|
2008-12-04 06:31:07 +00:00
|
|
|
bool MadeChange = false;
|
|
|
|
// Ignore the default edge for now.
|
|
|
|
for (unsigned i = 1, e = DestSI->getNumSuccessors(); i != e; ++i) {
|
|
|
|
ConstantInt *DestVal = DestSI->getCaseValue(i);
|
|
|
|
BasicBlock *DestSucc = DestSI->getSuccessor(i);
|
|
|
|
|
|
|
|
// Okay, DestSI has a case for 'DestVal' that goes to 'DestSucc'. See if
|
|
|
|
// PredSI has an explicit case for it. If so, forward. If it is covered
|
|
|
|
// by the default case, we can't update PredSI.
|
|
|
|
unsigned PredCase = PredSI->findCaseValue(DestVal);
|
|
|
|
if (PredCase == 0) continue;
|
|
|
|
|
|
|
|
// If PredSI doesn't go to DestBB on this value, then it won't reach the
|
|
|
|
// case on this condition.
|
|
|
|
if (PredSI->getSuccessor(PredCase) != DestBB &&
|
|
|
|
DestSI->getSuccessor(i) != DestBB)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Otherwise, we're safe to make the change. Make sure that the edge from
|
|
|
|
// DestSI to DestSucc is not critical and has no PHI nodes.
|
|
|
|
DOUT << "FORWARDING EDGE " << *DestVal << " FROM: " << *PredSI;
|
|
|
|
DOUT << "THROUGH: " << *DestSI;
|
|
|
|
|
|
|
|
// If the destination has PHI nodes, just split the edge for updating
|
|
|
|
// simplicity.
|
|
|
|
if (isa<PHINode>(DestSucc->begin()) && !DestSucc->getSinglePredecessor()){
|
|
|
|
SplitCriticalEdge(DestSI, i, this);
|
|
|
|
DestSucc = DestSI->getSuccessor(i);
|
|
|
|
}
|
|
|
|
FoldSingleEntryPHINodes(DestSucc);
|
|
|
|
PredSI->setSuccessor(PredCase, DestSucc);
|
|
|
|
MadeChange = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MadeChange)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-27 05:07:53 +00:00
|
|
|
/// SimplifyPartiallyRedundantLoad - If LI is an obviously partially redundant
|
|
|
|
/// load instruction, eliminate it by replacing it with a PHI node. This is an
|
|
|
|
/// important optimization that encourages jump threading, and needs to be run
|
|
|
|
/// interlaced with other jump threading tasks.
|
|
|
|
bool JumpThreading::SimplifyPartiallyRedundantLoad(LoadInst *LI) {
|
|
|
|
// Don't hack volatile loads.
|
|
|
|
if (LI->isVolatile()) return false;
|
|
|
|
|
|
|
|
// If the load is defined in a block with exactly one predecessor, it can't be
|
|
|
|
// partially redundant.
|
|
|
|
BasicBlock *LoadBB = LI->getParent();
|
|
|
|
if (LoadBB->getSinglePredecessor())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Value *LoadedPtr = LI->getOperand(0);
|
|
|
|
|
|
|
|
// If the loaded operand is defined in the LoadBB, it can't be available.
|
|
|
|
// FIXME: Could do PHI translation, that would be fun :)
|
|
|
|
if (Instruction *PtrOp = dyn_cast<Instruction>(LoadedPtr))
|
|
|
|
if (PtrOp->getParent() == LoadBB)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Scan a few instructions up from the load, to see if it is obviously live at
|
|
|
|
// the entry to its block.
|
|
|
|
BasicBlock::iterator BBIt = LI;
|
|
|
|
|
2008-11-27 08:10:05 +00:00
|
|
|
if (Value *AvailableVal = FindAvailableLoadedValue(LoadedPtr, LoadBB,
|
|
|
|
BBIt, 6)) {
|
2008-11-27 05:07:53 +00:00
|
|
|
// If the value if the load is locally available within the block, just use
|
|
|
|
// it. This frequently occurs for reg2mem'd allocas.
|
|
|
|
//cerr << "LOAD ELIMINATED:\n" << *BBIt << *LI << "\n";
|
2009-01-09 06:08:12 +00:00
|
|
|
|
|
|
|
// If the returned value is the load itself, replace with an undef. This can
|
|
|
|
// only happen in dead loops.
|
2009-07-03 00:54:20 +00:00
|
|
|
if (AvailableVal == LI) AvailableVal = Context->getUndef(LI->getType());
|
2008-11-27 05:07:53 +00:00
|
|
|
LI->replaceAllUsesWith(AvailableVal);
|
|
|
|
LI->eraseFromParent();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, if we scanned the whole block and got to the top of the block,
|
|
|
|
// we know the block is locally transparent to the load. If not, something
|
|
|
|
// might clobber its value.
|
|
|
|
if (BBIt != LoadBB->begin())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
SmallPtrSet<BasicBlock*, 8> PredsScanned;
|
|
|
|
typedef SmallVector<std::pair<BasicBlock*, Value*>, 8> AvailablePredsTy;
|
|
|
|
AvailablePredsTy AvailablePreds;
|
|
|
|
BasicBlock *OneUnavailablePred = 0;
|
|
|
|
|
|
|
|
// If we got here, the loaded value is transparent through to the start of the
|
|
|
|
// block. Check to see if it is available in any of the predecessor blocks.
|
|
|
|
for (pred_iterator PI = pred_begin(LoadBB), PE = pred_end(LoadBB);
|
|
|
|
PI != PE; ++PI) {
|
|
|
|
BasicBlock *PredBB = *PI;
|
|
|
|
|
|
|
|
// If we already scanned this predecessor, skip it.
|
|
|
|
if (!PredsScanned.insert(PredBB))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Scan the predecessor to see if the value is available in the pred.
|
|
|
|
BBIt = PredBB->end();
|
2008-11-27 08:10:05 +00:00
|
|
|
Value *PredAvailable = FindAvailableLoadedValue(LoadedPtr, PredBB, BBIt, 6);
|
2008-11-27 05:07:53 +00:00
|
|
|
if (!PredAvailable) {
|
|
|
|
OneUnavailablePred = PredBB;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If so, this load is partially redundant. Remember this info so that we
|
|
|
|
// can create a PHI node.
|
|
|
|
AvailablePreds.push_back(std::make_pair(PredBB, PredAvailable));
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the loaded value isn't available in any predecessor, it isn't partially
|
|
|
|
// redundant.
|
|
|
|
if (AvailablePreds.empty()) return false;
|
|
|
|
|
|
|
|
// Okay, the loaded value is available in at least one (and maybe all!)
|
|
|
|
// predecessors. If the value is unavailable in more than one unique
|
|
|
|
// predecessor, we want to insert a merge block for those common predecessors.
|
|
|
|
// This ensures that we only have to insert one reload, thus not increasing
|
|
|
|
// code size.
|
|
|
|
BasicBlock *UnavailablePred = 0;
|
|
|
|
|
|
|
|
// If there is exactly one predecessor where the value is unavailable, the
|
|
|
|
// already computed 'OneUnavailablePred' block is it. If it ends in an
|
|
|
|
// unconditional branch, we know that it isn't a critical edge.
|
|
|
|
if (PredsScanned.size() == AvailablePreds.size()+1 &&
|
|
|
|
OneUnavailablePred->getTerminator()->getNumSuccessors() == 1) {
|
|
|
|
UnavailablePred = OneUnavailablePred;
|
|
|
|
} else if (PredsScanned.size() != AvailablePreds.size()) {
|
|
|
|
// Otherwise, we had multiple unavailable predecessors or we had a critical
|
|
|
|
// edge from the one.
|
|
|
|
SmallVector<BasicBlock*, 8> PredsToSplit;
|
|
|
|
SmallPtrSet<BasicBlock*, 8> AvailablePredSet;
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = AvailablePreds.size(); i != e; ++i)
|
|
|
|
AvailablePredSet.insert(AvailablePreds[i].first);
|
|
|
|
|
|
|
|
// Add all the unavailable predecessors to the PredsToSplit list.
|
|
|
|
for (pred_iterator PI = pred_begin(LoadBB), PE = pred_end(LoadBB);
|
|
|
|
PI != PE; ++PI)
|
|
|
|
if (!AvailablePredSet.count(*PI))
|
|
|
|
PredsToSplit.push_back(*PI);
|
|
|
|
|
|
|
|
// Split them out to their own block.
|
|
|
|
UnavailablePred =
|
|
|
|
SplitBlockPredecessors(LoadBB, &PredsToSplit[0], PredsToSplit.size(),
|
|
|
|
"thread-split", this);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the value isn't available in all predecessors, then there will be
|
|
|
|
// exactly one where it isn't available. Insert a load on that edge and add
|
|
|
|
// it to the AvailablePreds list.
|
|
|
|
if (UnavailablePred) {
|
|
|
|
assert(UnavailablePred->getTerminator()->getNumSuccessors() == 1 &&
|
|
|
|
"Can't handle critical edge here!");
|
|
|
|
Value *NewVal = new LoadInst(LoadedPtr, LI->getName()+".pr",
|
|
|
|
UnavailablePred->getTerminator());
|
|
|
|
AvailablePreds.push_back(std::make_pair(UnavailablePred, NewVal));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now we know that each predecessor of this block has a value in
|
|
|
|
// AvailablePreds, sort them for efficient access as we're walking the preds.
|
2008-12-01 06:52:57 +00:00
|
|
|
array_pod_sort(AvailablePreds.begin(), AvailablePreds.end());
|
2008-11-27 05:07:53 +00:00
|
|
|
|
|
|
|
// Create a PHI node at the start of the block for the PRE'd load value.
|
|
|
|
PHINode *PN = PHINode::Create(LI->getType(), "", LoadBB->begin());
|
|
|
|
PN->takeName(LI);
|
|
|
|
|
|
|
|
// Insert new entries into the PHI for each predecessor. A single block may
|
|
|
|
// have multiple entries here.
|
|
|
|
for (pred_iterator PI = pred_begin(LoadBB), E = pred_end(LoadBB); PI != E;
|
|
|
|
++PI) {
|
|
|
|
AvailablePredsTy::iterator I =
|
|
|
|
std::lower_bound(AvailablePreds.begin(), AvailablePreds.end(),
|
|
|
|
std::make_pair(*PI, (Value*)0));
|
|
|
|
|
|
|
|
assert(I != AvailablePreds.end() && I->first == *PI &&
|
|
|
|
"Didn't find entry for predecessor!");
|
|
|
|
|
|
|
|
PN->addIncoming(I->second, I->first);
|
|
|
|
}
|
|
|
|
|
|
|
|
//cerr << "PRE: " << *LI << *PN << "\n";
|
|
|
|
|
|
|
|
LI->replaceAllUsesWith(PN);
|
|
|
|
LI->eraseFromParent();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-04-22 06:36:15 +00:00
|
|
|
/// ProcessJumpOnPHI - We have a conditional branch of switch on a PHI node in
|
|
|
|
/// the current block. See if there are any simplifications we can do based on
|
|
|
|
/// inputs to the phi node.
|
|
|
|
///
|
|
|
|
bool JumpThreading::ProcessJumpOnPHI(PHINode *PN) {
|
2008-04-20 21:18:09 +00:00
|
|
|
// See if the phi node has any constant values. If so, we can determine where
|
|
|
|
// the corresponding predecessor will branch.
|
2008-04-20 22:39:42 +00:00
|
|
|
ConstantInt *PredCst = 0;
|
Start doing the significantly useful part of jump threading: handle cases
where a comparison has a phi input and that phi is a constant. For example,
stuff like:
Threading edge through bool from 'bb2149' to 'bb2231' with cost: 1, across block:
bb2237: ; preds = %bb2231, %bb2149
%tmp2328.rle = phi i32 [ %tmp2232, %bb2231 ], [ %tmp2232439, %bb2149 ] ; <i32> [#uses=2]
%done.0 = phi i32 [ %done.2, %bb2231 ], [ 0, %bb2149 ] ; <i32> [#uses=1]
%tmp2239 = icmp eq i32 %done.0, 0 ; <i1> [#uses=1]
br i1 %tmp2239, label %bb2231, label %bb2327
or
bb38.i298: ; preds = %bb33.i295, %bb1693
%tmp39.i296.rle = phi %struct.ibox* [ null, %bb1693 ], [ %tmp39.i296.rle1109, %bb33.i295 ] ; <%struct.ibox*> [#uses=2]
%minspan.1.i291.reg2mem.1 = phi i32 [ 32000, %bb1693 ], [ %minspan.0.i288, %bb33.i295 ] ; <i32> [#uses=1]
%tmp40.i297 = icmp eq %struct.ibox* %tmp39.i296.rle, null ; <i1> [#uses=1]
br i1 %tmp40.i297, label %implfeeds.exit311, label %bb43.i301
This triggers thousands of times in spec.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50110 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 21:40:39 +00:00
|
|
|
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
|
|
|
|
if ((PredCst = dyn_cast<ConstantInt>(PN->getIncomingValue(i))))
|
2008-04-20 21:18:09 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
// If no incoming value has a constant, we don't know the destination of any
|
|
|
|
// predecessors.
|
Start doing the significantly useful part of jump threading: handle cases
where a comparison has a phi input and that phi is a constant. For example,
stuff like:
Threading edge through bool from 'bb2149' to 'bb2231' with cost: 1, across block:
bb2237: ; preds = %bb2231, %bb2149
%tmp2328.rle = phi i32 [ %tmp2232, %bb2231 ], [ %tmp2232439, %bb2149 ] ; <i32> [#uses=2]
%done.0 = phi i32 [ %done.2, %bb2231 ], [ 0, %bb2149 ] ; <i32> [#uses=1]
%tmp2239 = icmp eq i32 %done.0, 0 ; <i1> [#uses=1]
br i1 %tmp2239, label %bb2231, label %bb2327
or
bb38.i298: ; preds = %bb33.i295, %bb1693
%tmp39.i296.rle = phi %struct.ibox* [ null, %bb1693 ], [ %tmp39.i296.rle1109, %bb33.i295 ] ; <%struct.ibox*> [#uses=2]
%minspan.1.i291.reg2mem.1 = phi i32 [ 32000, %bb1693 ], [ %minspan.0.i288, %bb33.i295 ] ; <i32> [#uses=1]
%tmp40.i297 = icmp eq %struct.ibox* %tmp39.i296.rle, null ; <i1> [#uses=1]
br i1 %tmp40.i297, label %implfeeds.exit311, label %bb43.i301
This triggers thousands of times in spec.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50110 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 21:40:39 +00:00
|
|
|
if (PredCst == 0)
|
2008-04-20 21:18:09 +00:00
|
|
|
return false;
|
|
|
|
|
2008-04-20 21:13:06 +00:00
|
|
|
// See if the cost of duplicating this block is low enough.
|
2008-04-22 06:36:15 +00:00
|
|
|
BasicBlock *BB = PN->getParent();
|
2008-04-20 21:13:06 +00:00
|
|
|
unsigned JumpThreadCost = getJumpThreadDuplicationCost(BB);
|
|
|
|
if (JumpThreadCost > Threshold) {
|
2008-04-20 22:39:42 +00:00
|
|
|
DOUT << " Not threading BB '" << BB->getNameStart()
|
2008-04-20 21:18:09 +00:00
|
|
|
<< "' - Cost is too high: " << JumpThreadCost << "\n";
|
2008-04-20 21:13:06 +00:00
|
|
|
return false;
|
|
|
|
}
|
2008-04-20 22:39:42 +00:00
|
|
|
|
Teach jump threading to thread through blocks like:
br (and X, phi(Y, Z, false)), label L1, label L2
This triggers once on 252.eon and 6 times on 176.gcc. Blocks
in question often look like this:
bb262: ; preds = %bb261, %bb248
%iftmp.251.0 = phi i1 [ true, %bb261 ], [ false, %bb248 ] ; <i1> [#uses=4]
%tmp270 = icmp eq %struct.rtx_def* %tmp.0.i, null ; <i1> [#uses=1]
%bothcond = or i1 %iftmp.251.0, %tmp270 ; <i1> [#uses=1]
br i1 %bothcond, label %bb288, label %bb273
In this case, it is clear that it doesn't matter if tmp.0.i is null when coming from bb261. When coming from bb248, it is all that matters.
Another random example:
check_asm_operands.exit: ; preds = %check_asm_operands.exit.thr_comm, %bb30.i, %bb12.i, %bb6.i413
%tmp.0.i420 = phi i1 [ true, %bb6.i413 ], [ true, %bb12.i ], [ true, %bb30.i ], [ false, %check_asm_operands.exit.thr_comm ; <i1> [#uses=1]
call void @llvm.stackrestore( i8* %savedstack ) nounwind
%tmp4389 = icmp eq i32 %added_sets_1.0, 0 ; <i1> [#uses=1]
%tmp4394 = icmp eq i32 %added_sets_2.0, 0 ; <i1> [#uses=1]
%bothcond80 = and i1 %tmp4389, %tmp4394 ; <i1> [#uses=1]
%bothcond81 = and i1 %bothcond80, %tmp.0.i420 ; <i1> [#uses=1]
br i1 %bothcond81, label %bb4398, label %bb4397
Here is the case from 252.eon:
bb290.i.i: ; preds = %bb23.i57.i.i, %bb8.i39.i.i, %bb100.i.i, %bb100.i.i, %bb85.i.i110
%myEOF.1.i.i = phi i1 [ true, %bb100.i.i ], [ true, %bb100.i.i ], [ true, %bb85.i.i110 ], [ true, %bb8.i39.i.i ], [ false, %bb23.i57.i.i ] ; <i1> [#uses=2]
%i.4.i.i = phi i32 [ %i.1.i.i, %bb85.i.i110 ], [ %i.0.i.i, %bb100.i.i ], [ %i.0.i.i, %bb100.i.i ], [ %i.3.i.i, %bb8.i39.i.i ], [ %i.3.i.i, %bb23.i57.i.i ] ; <i32> [#uses=3]
%tmp292.i.i = load i8* %tmp16.i.i100, align 1 ; <i8> [#uses=1]
%tmp293.not.i.i = icmp ne i8 %tmp292.i.i, 0 ; <i1> [#uses=1]
%bothcond.i.i = and i1 %tmp293.not.i.i, %myEOF.1.i.i ; <i1> [#uses=1]
br i1 %bothcond.i.i, label %bb202.i.i, label %bb301.i.i
Factoring out 3 common predecessors.
On the path from any blocks other than bb23.i57.i.i, the load and compare
are dead.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50096 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 07:05:46 +00:00
|
|
|
// If so, we can actually do this threading. Merge any common predecessors
|
|
|
|
// that will act the same.
|
|
|
|
BasicBlock *PredBB = FactorCommonPHIPreds(PN, PredCst);
|
|
|
|
|
|
|
|
// Next, figure out which successor we are threading to.
|
2008-04-20 22:39:42 +00:00
|
|
|
BasicBlock *SuccBB;
|
|
|
|
if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator()))
|
2009-07-03 00:54:20 +00:00
|
|
|
SuccBB = BI->getSuccessor(PredCst == Context->getConstantIntFalse());
|
2008-04-20 22:39:42 +00:00
|
|
|
else {
|
|
|
|
SwitchInst *SI = cast<SwitchInst>(BB->getTerminator());
|
|
|
|
SuccBB = SI->getSuccessor(SI->findCaseValue(PredCst));
|
|
|
|
}
|
|
|
|
|
2009-05-04 18:40:41 +00:00
|
|
|
// Ok, try to thread it!
|
|
|
|
return ThreadEdge(BB, PredBB, SuccBB, JumpThreadCost);
|
2008-04-20 22:39:42 +00:00
|
|
|
}
|
|
|
|
|
Teach jump threading to thread through blocks like:
br (and X, phi(Y, Z, false)), label L1, label L2
This triggers once on 252.eon and 6 times on 176.gcc. Blocks
in question often look like this:
bb262: ; preds = %bb261, %bb248
%iftmp.251.0 = phi i1 [ true, %bb261 ], [ false, %bb248 ] ; <i1> [#uses=4]
%tmp270 = icmp eq %struct.rtx_def* %tmp.0.i, null ; <i1> [#uses=1]
%bothcond = or i1 %iftmp.251.0, %tmp270 ; <i1> [#uses=1]
br i1 %bothcond, label %bb288, label %bb273
In this case, it is clear that it doesn't matter if tmp.0.i is null when coming from bb261. When coming from bb248, it is all that matters.
Another random example:
check_asm_operands.exit: ; preds = %check_asm_operands.exit.thr_comm, %bb30.i, %bb12.i, %bb6.i413
%tmp.0.i420 = phi i1 [ true, %bb6.i413 ], [ true, %bb12.i ], [ true, %bb30.i ], [ false, %check_asm_operands.exit.thr_comm ; <i1> [#uses=1]
call void @llvm.stackrestore( i8* %savedstack ) nounwind
%tmp4389 = icmp eq i32 %added_sets_1.0, 0 ; <i1> [#uses=1]
%tmp4394 = icmp eq i32 %added_sets_2.0, 0 ; <i1> [#uses=1]
%bothcond80 = and i1 %tmp4389, %tmp4394 ; <i1> [#uses=1]
%bothcond81 = and i1 %bothcond80, %tmp.0.i420 ; <i1> [#uses=1]
br i1 %bothcond81, label %bb4398, label %bb4397
Here is the case from 252.eon:
bb290.i.i: ; preds = %bb23.i57.i.i, %bb8.i39.i.i, %bb100.i.i, %bb100.i.i, %bb85.i.i110
%myEOF.1.i.i = phi i1 [ true, %bb100.i.i ], [ true, %bb100.i.i ], [ true, %bb85.i.i110 ], [ true, %bb8.i39.i.i ], [ false, %bb23.i57.i.i ] ; <i1> [#uses=2]
%i.4.i.i = phi i32 [ %i.1.i.i, %bb85.i.i110 ], [ %i.0.i.i, %bb100.i.i ], [ %i.0.i.i, %bb100.i.i ], [ %i.3.i.i, %bb8.i39.i.i ], [ %i.3.i.i, %bb23.i57.i.i ] ; <i32> [#uses=3]
%tmp292.i.i = load i8* %tmp16.i.i100, align 1 ; <i8> [#uses=1]
%tmp293.not.i.i = icmp ne i8 %tmp292.i.i, 0 ; <i1> [#uses=1]
%bothcond.i.i = and i1 %tmp293.not.i.i, %myEOF.1.i.i ; <i1> [#uses=1]
br i1 %bothcond.i.i, label %bb202.i.i, label %bb301.i.i
Factoring out 3 common predecessors.
On the path from any blocks other than bb23.i57.i.i, the load and compare
are dead.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50096 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 07:05:46 +00:00
|
|
|
/// ProcessJumpOnLogicalPHI - PN's basic block contains a conditional branch
|
|
|
|
/// whose condition is an AND/OR where one side is PN. If PN has constant
|
|
|
|
/// operands that permit us to evaluate the condition for some operand, thread
|
|
|
|
/// through the block. For example with:
|
|
|
|
/// br (and X, phi(Y, Z, false))
|
|
|
|
/// the predecessor corresponding to the 'false' will always jump to the false
|
|
|
|
/// destination of the branch.
|
|
|
|
///
|
2008-04-22 20:46:09 +00:00
|
|
|
bool JumpThreading::ProcessBranchOnLogical(Value *V, BasicBlock *BB,
|
|
|
|
bool isAnd) {
|
|
|
|
// If this is a binary operator tree of the same AND/OR opcode, check the
|
|
|
|
// LHS/RHS.
|
|
|
|
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(V))
|
2008-05-27 11:50:51 +00:00
|
|
|
if ((isAnd && BO->getOpcode() == Instruction::And) ||
|
|
|
|
(!isAnd && BO->getOpcode() == Instruction::Or)) {
|
2008-04-22 20:46:09 +00:00
|
|
|
if (ProcessBranchOnLogical(BO->getOperand(0), BB, isAnd))
|
|
|
|
return true;
|
|
|
|
if (ProcessBranchOnLogical(BO->getOperand(1), BB, isAnd))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this isn't a PHI node, we can't handle it.
|
|
|
|
PHINode *PN = dyn_cast<PHINode>(V);
|
|
|
|
if (!PN || PN->getParent() != BB) return false;
|
|
|
|
|
Teach jump threading to thread through blocks like:
br (and X, phi(Y, Z, false)), label L1, label L2
This triggers once on 252.eon and 6 times on 176.gcc. Blocks
in question often look like this:
bb262: ; preds = %bb261, %bb248
%iftmp.251.0 = phi i1 [ true, %bb261 ], [ false, %bb248 ] ; <i1> [#uses=4]
%tmp270 = icmp eq %struct.rtx_def* %tmp.0.i, null ; <i1> [#uses=1]
%bothcond = or i1 %iftmp.251.0, %tmp270 ; <i1> [#uses=1]
br i1 %bothcond, label %bb288, label %bb273
In this case, it is clear that it doesn't matter if tmp.0.i is null when coming from bb261. When coming from bb248, it is all that matters.
Another random example:
check_asm_operands.exit: ; preds = %check_asm_operands.exit.thr_comm, %bb30.i, %bb12.i, %bb6.i413
%tmp.0.i420 = phi i1 [ true, %bb6.i413 ], [ true, %bb12.i ], [ true, %bb30.i ], [ false, %check_asm_operands.exit.thr_comm ; <i1> [#uses=1]
call void @llvm.stackrestore( i8* %savedstack ) nounwind
%tmp4389 = icmp eq i32 %added_sets_1.0, 0 ; <i1> [#uses=1]
%tmp4394 = icmp eq i32 %added_sets_2.0, 0 ; <i1> [#uses=1]
%bothcond80 = and i1 %tmp4389, %tmp4394 ; <i1> [#uses=1]
%bothcond81 = and i1 %bothcond80, %tmp.0.i420 ; <i1> [#uses=1]
br i1 %bothcond81, label %bb4398, label %bb4397
Here is the case from 252.eon:
bb290.i.i: ; preds = %bb23.i57.i.i, %bb8.i39.i.i, %bb100.i.i, %bb100.i.i, %bb85.i.i110
%myEOF.1.i.i = phi i1 [ true, %bb100.i.i ], [ true, %bb100.i.i ], [ true, %bb85.i.i110 ], [ true, %bb8.i39.i.i ], [ false, %bb23.i57.i.i ] ; <i1> [#uses=2]
%i.4.i.i = phi i32 [ %i.1.i.i, %bb85.i.i110 ], [ %i.0.i.i, %bb100.i.i ], [ %i.0.i.i, %bb100.i.i ], [ %i.3.i.i, %bb8.i39.i.i ], [ %i.3.i.i, %bb23.i57.i.i ] ; <i32> [#uses=3]
%tmp292.i.i = load i8* %tmp16.i.i100, align 1 ; <i8> [#uses=1]
%tmp293.not.i.i = icmp ne i8 %tmp292.i.i, 0 ; <i1> [#uses=1]
%bothcond.i.i = and i1 %tmp293.not.i.i, %myEOF.1.i.i ; <i1> [#uses=1]
br i1 %bothcond.i.i, label %bb202.i.i, label %bb301.i.i
Factoring out 3 common predecessors.
On the path from any blocks other than bb23.i57.i.i, the load and compare
are dead.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50096 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 07:05:46 +00:00
|
|
|
// We can only do the simplification for phi nodes of 'false' with AND or
|
|
|
|
// 'true' with OR. See if we have any entries in the phi for this.
|
|
|
|
unsigned PredNo = ~0U;
|
2009-07-03 00:54:20 +00:00
|
|
|
ConstantInt *PredCst = Context->getConstantInt(Type::Int1Ty, !isAnd);
|
Teach jump threading to thread through blocks like:
br (and X, phi(Y, Z, false)), label L1, label L2
This triggers once on 252.eon and 6 times on 176.gcc. Blocks
in question often look like this:
bb262: ; preds = %bb261, %bb248
%iftmp.251.0 = phi i1 [ true, %bb261 ], [ false, %bb248 ] ; <i1> [#uses=4]
%tmp270 = icmp eq %struct.rtx_def* %tmp.0.i, null ; <i1> [#uses=1]
%bothcond = or i1 %iftmp.251.0, %tmp270 ; <i1> [#uses=1]
br i1 %bothcond, label %bb288, label %bb273
In this case, it is clear that it doesn't matter if tmp.0.i is null when coming from bb261. When coming from bb248, it is all that matters.
Another random example:
check_asm_operands.exit: ; preds = %check_asm_operands.exit.thr_comm, %bb30.i, %bb12.i, %bb6.i413
%tmp.0.i420 = phi i1 [ true, %bb6.i413 ], [ true, %bb12.i ], [ true, %bb30.i ], [ false, %check_asm_operands.exit.thr_comm ; <i1> [#uses=1]
call void @llvm.stackrestore( i8* %savedstack ) nounwind
%tmp4389 = icmp eq i32 %added_sets_1.0, 0 ; <i1> [#uses=1]
%tmp4394 = icmp eq i32 %added_sets_2.0, 0 ; <i1> [#uses=1]
%bothcond80 = and i1 %tmp4389, %tmp4394 ; <i1> [#uses=1]
%bothcond81 = and i1 %bothcond80, %tmp.0.i420 ; <i1> [#uses=1]
br i1 %bothcond81, label %bb4398, label %bb4397
Here is the case from 252.eon:
bb290.i.i: ; preds = %bb23.i57.i.i, %bb8.i39.i.i, %bb100.i.i, %bb100.i.i, %bb85.i.i110
%myEOF.1.i.i = phi i1 [ true, %bb100.i.i ], [ true, %bb100.i.i ], [ true, %bb85.i.i110 ], [ true, %bb8.i39.i.i ], [ false, %bb23.i57.i.i ] ; <i1> [#uses=2]
%i.4.i.i = phi i32 [ %i.1.i.i, %bb85.i.i110 ], [ %i.0.i.i, %bb100.i.i ], [ %i.0.i.i, %bb100.i.i ], [ %i.3.i.i, %bb8.i39.i.i ], [ %i.3.i.i, %bb23.i57.i.i ] ; <i32> [#uses=3]
%tmp292.i.i = load i8* %tmp16.i.i100, align 1 ; <i8> [#uses=1]
%tmp293.not.i.i = icmp ne i8 %tmp292.i.i, 0 ; <i1> [#uses=1]
%bothcond.i.i = and i1 %tmp293.not.i.i, %myEOF.1.i.i ; <i1> [#uses=1]
br i1 %bothcond.i.i, label %bb202.i.i, label %bb301.i.i
Factoring out 3 common predecessors.
On the path from any blocks other than bb23.i57.i.i, the load and compare
are dead.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50096 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 07:05:46 +00:00
|
|
|
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
|
|
|
|
if (PN->getIncomingValue(i) == PredCst) {
|
|
|
|
PredNo = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If no match, bail out.
|
|
|
|
if (PredNo == ~0U)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// See if the cost of duplicating this block is low enough.
|
|
|
|
unsigned JumpThreadCost = getJumpThreadDuplicationCost(BB);
|
|
|
|
if (JumpThreadCost > Threshold) {
|
|
|
|
DOUT << " Not threading BB '" << BB->getNameStart()
|
|
|
|
<< "' - Cost is too high: " << JumpThreadCost << "\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If so, we can actually do this threading. Merge any common predecessors
|
|
|
|
// that will act the same.
|
|
|
|
BasicBlock *PredBB = FactorCommonPHIPreds(PN, PredCst);
|
|
|
|
|
|
|
|
// Next, figure out which successor we are threading to. If this was an AND,
|
|
|
|
// the constant must be FALSE, and we must be targeting the 'false' block.
|
|
|
|
// If this is an OR, the constant must be TRUE, and we must be targeting the
|
|
|
|
// 'true' block.
|
|
|
|
BasicBlock *SuccBB = BB->getTerminator()->getSuccessor(isAnd);
|
|
|
|
|
2009-05-04 18:40:41 +00:00
|
|
|
// Ok, try to thread it!
|
|
|
|
return ThreadEdge(BB, PredBB, SuccBB, JumpThreadCost);
|
Teach jump threading to thread through blocks like:
br (and X, phi(Y, Z, false)), label L1, label L2
This triggers once on 252.eon and 6 times on 176.gcc. Blocks
in question often look like this:
bb262: ; preds = %bb261, %bb248
%iftmp.251.0 = phi i1 [ true, %bb261 ], [ false, %bb248 ] ; <i1> [#uses=4]
%tmp270 = icmp eq %struct.rtx_def* %tmp.0.i, null ; <i1> [#uses=1]
%bothcond = or i1 %iftmp.251.0, %tmp270 ; <i1> [#uses=1]
br i1 %bothcond, label %bb288, label %bb273
In this case, it is clear that it doesn't matter if tmp.0.i is null when coming from bb261. When coming from bb248, it is all that matters.
Another random example:
check_asm_operands.exit: ; preds = %check_asm_operands.exit.thr_comm, %bb30.i, %bb12.i, %bb6.i413
%tmp.0.i420 = phi i1 [ true, %bb6.i413 ], [ true, %bb12.i ], [ true, %bb30.i ], [ false, %check_asm_operands.exit.thr_comm ; <i1> [#uses=1]
call void @llvm.stackrestore( i8* %savedstack ) nounwind
%tmp4389 = icmp eq i32 %added_sets_1.0, 0 ; <i1> [#uses=1]
%tmp4394 = icmp eq i32 %added_sets_2.0, 0 ; <i1> [#uses=1]
%bothcond80 = and i1 %tmp4389, %tmp4394 ; <i1> [#uses=1]
%bothcond81 = and i1 %bothcond80, %tmp.0.i420 ; <i1> [#uses=1]
br i1 %bothcond81, label %bb4398, label %bb4397
Here is the case from 252.eon:
bb290.i.i: ; preds = %bb23.i57.i.i, %bb8.i39.i.i, %bb100.i.i, %bb100.i.i, %bb85.i.i110
%myEOF.1.i.i = phi i1 [ true, %bb100.i.i ], [ true, %bb100.i.i ], [ true, %bb85.i.i110 ], [ true, %bb8.i39.i.i ], [ false, %bb23.i57.i.i ] ; <i1> [#uses=2]
%i.4.i.i = phi i32 [ %i.1.i.i, %bb85.i.i110 ], [ %i.0.i.i, %bb100.i.i ], [ %i.0.i.i, %bb100.i.i ], [ %i.3.i.i, %bb8.i39.i.i ], [ %i.3.i.i, %bb23.i57.i.i ] ; <i32> [#uses=3]
%tmp292.i.i = load i8* %tmp16.i.i100, align 1 ; <i8> [#uses=1]
%tmp293.not.i.i = icmp ne i8 %tmp292.i.i, 0 ; <i1> [#uses=1]
%bothcond.i.i = and i1 %tmp293.not.i.i, %myEOF.1.i.i ; <i1> [#uses=1]
br i1 %bothcond.i.i, label %bb202.i.i, label %bb301.i.i
Factoring out 3 common predecessors.
On the path from any blocks other than bb23.i57.i.i, the load and compare
are dead.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50096 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 07:05:46 +00:00
|
|
|
}
|
|
|
|
|
2009-06-19 04:56:29 +00:00
|
|
|
/// GetResultOfComparison - Given an icmp/fcmp predicate and the left and right
|
|
|
|
/// hand sides of the compare instruction, try to determine the result. If the
|
|
|
|
/// result can not be determined, a null pointer is returned.
|
|
|
|
static Constant *GetResultOfComparison(CmpInst::Predicate pred,
|
2009-07-03 00:54:20 +00:00
|
|
|
Value *LHS, Value *RHS,
|
2009-07-06 23:00:19 +00:00
|
|
|
LLVMContext *Context) {
|
2009-06-19 04:56:29 +00:00
|
|
|
if (Constant *CLHS = dyn_cast<Constant>(LHS))
|
|
|
|
if (Constant *CRHS = dyn_cast<Constant>(RHS))
|
2009-07-03 00:54:20 +00:00
|
|
|
return Context->getConstantExprCompare(pred, CLHS, CRHS);
|
2009-06-19 04:56:29 +00:00
|
|
|
|
|
|
|
if (LHS == RHS)
|
|
|
|
if (isa<IntegerType>(LHS->getType()) || isa<PointerType>(LHS->getType()))
|
|
|
|
return ICmpInst::isTrueWhenEqual(pred) ?
|
2009-07-03 00:54:20 +00:00
|
|
|
Context->getConstantIntTrue() : Context->getConstantIntFalse();
|
2009-06-19 04:56:29 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Start doing the significantly useful part of jump threading: handle cases
where a comparison has a phi input and that phi is a constant. For example,
stuff like:
Threading edge through bool from 'bb2149' to 'bb2231' with cost: 1, across block:
bb2237: ; preds = %bb2231, %bb2149
%tmp2328.rle = phi i32 [ %tmp2232, %bb2231 ], [ %tmp2232439, %bb2149 ] ; <i32> [#uses=2]
%done.0 = phi i32 [ %done.2, %bb2231 ], [ 0, %bb2149 ] ; <i32> [#uses=1]
%tmp2239 = icmp eq i32 %done.0, 0 ; <i1> [#uses=1]
br i1 %tmp2239, label %bb2231, label %bb2327
or
bb38.i298: ; preds = %bb33.i295, %bb1693
%tmp39.i296.rle = phi %struct.ibox* [ null, %bb1693 ], [ %tmp39.i296.rle1109, %bb33.i295 ] ; <%struct.ibox*> [#uses=2]
%minspan.1.i291.reg2mem.1 = phi i32 [ 32000, %bb1693 ], [ %minspan.0.i288, %bb33.i295 ] ; <i32> [#uses=1]
%tmp40.i297 = icmp eq %struct.ibox* %tmp39.i296.rle, null ; <i1> [#uses=1]
br i1 %tmp40.i297, label %implfeeds.exit311, label %bb43.i301
This triggers thousands of times in spec.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50110 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 21:40:39 +00:00
|
|
|
/// ProcessBranchOnCompare - We found a branch on a comparison between a phi
|
2009-06-19 04:56:29 +00:00
|
|
|
/// node and a value. If we can identify when the comparison is true between
|
|
|
|
/// the phi inputs and the value, we can fold the compare for that edge and
|
|
|
|
/// thread through it.
|
Start doing the significantly useful part of jump threading: handle cases
where a comparison has a phi input and that phi is a constant. For example,
stuff like:
Threading edge through bool from 'bb2149' to 'bb2231' with cost: 1, across block:
bb2237: ; preds = %bb2231, %bb2149
%tmp2328.rle = phi i32 [ %tmp2232, %bb2231 ], [ %tmp2232439, %bb2149 ] ; <i32> [#uses=2]
%done.0 = phi i32 [ %done.2, %bb2231 ], [ 0, %bb2149 ] ; <i32> [#uses=1]
%tmp2239 = icmp eq i32 %done.0, 0 ; <i1> [#uses=1]
br i1 %tmp2239, label %bb2231, label %bb2327
or
bb38.i298: ; preds = %bb33.i295, %bb1693
%tmp39.i296.rle = phi %struct.ibox* [ null, %bb1693 ], [ %tmp39.i296.rle1109, %bb33.i295 ] ; <%struct.ibox*> [#uses=2]
%minspan.1.i291.reg2mem.1 = phi i32 [ 32000, %bb1693 ], [ %minspan.0.i288, %bb33.i295 ] ; <i32> [#uses=1]
%tmp40.i297 = icmp eq %struct.ibox* %tmp39.i296.rle, null ; <i1> [#uses=1]
br i1 %tmp40.i297, label %implfeeds.exit311, label %bb43.i301
This triggers thousands of times in spec.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50110 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 21:40:39 +00:00
|
|
|
bool JumpThreading::ProcessBranchOnCompare(CmpInst *Cmp, BasicBlock *BB) {
|
|
|
|
PHINode *PN = cast<PHINode>(Cmp->getOperand(0));
|
2009-06-19 04:56:29 +00:00
|
|
|
Value *RHS = Cmp->getOperand(1);
|
Start doing the significantly useful part of jump threading: handle cases
where a comparison has a phi input and that phi is a constant. For example,
stuff like:
Threading edge through bool from 'bb2149' to 'bb2231' with cost: 1, across block:
bb2237: ; preds = %bb2231, %bb2149
%tmp2328.rle = phi i32 [ %tmp2232, %bb2231 ], [ %tmp2232439, %bb2149 ] ; <i32> [#uses=2]
%done.0 = phi i32 [ %done.2, %bb2231 ], [ 0, %bb2149 ] ; <i32> [#uses=1]
%tmp2239 = icmp eq i32 %done.0, 0 ; <i1> [#uses=1]
br i1 %tmp2239, label %bb2231, label %bb2327
or
bb38.i298: ; preds = %bb33.i295, %bb1693
%tmp39.i296.rle = phi %struct.ibox* [ null, %bb1693 ], [ %tmp39.i296.rle1109, %bb33.i295 ] ; <%struct.ibox*> [#uses=2]
%minspan.1.i291.reg2mem.1 = phi i32 [ 32000, %bb1693 ], [ %minspan.0.i288, %bb33.i295 ] ; <i32> [#uses=1]
%tmp40.i297 = icmp eq %struct.ibox* %tmp39.i296.rle, null ; <i1> [#uses=1]
br i1 %tmp40.i297, label %implfeeds.exit311, label %bb43.i301
This triggers thousands of times in spec.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50110 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 21:40:39 +00:00
|
|
|
|
|
|
|
// If the phi isn't in the current block, an incoming edge to this block
|
|
|
|
// doesn't control the destination.
|
|
|
|
if (PN->getParent() != BB)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// We can do this simplification if any comparisons fold to true or false.
|
|
|
|
// See if any do.
|
2009-06-19 04:56:29 +00:00
|
|
|
Value *PredVal = 0;
|
Start doing the significantly useful part of jump threading: handle cases
where a comparison has a phi input and that phi is a constant. For example,
stuff like:
Threading edge through bool from 'bb2149' to 'bb2231' with cost: 1, across block:
bb2237: ; preds = %bb2231, %bb2149
%tmp2328.rle = phi i32 [ %tmp2232, %bb2231 ], [ %tmp2232439, %bb2149 ] ; <i32> [#uses=2]
%done.0 = phi i32 [ %done.2, %bb2231 ], [ 0, %bb2149 ] ; <i32> [#uses=1]
%tmp2239 = icmp eq i32 %done.0, 0 ; <i1> [#uses=1]
br i1 %tmp2239, label %bb2231, label %bb2327
or
bb38.i298: ; preds = %bb33.i295, %bb1693
%tmp39.i296.rle = phi %struct.ibox* [ null, %bb1693 ], [ %tmp39.i296.rle1109, %bb33.i295 ] ; <%struct.ibox*> [#uses=2]
%minspan.1.i291.reg2mem.1 = phi i32 [ 32000, %bb1693 ], [ %minspan.0.i288, %bb33.i295 ] ; <i32> [#uses=1]
%tmp40.i297 = icmp eq %struct.ibox* %tmp39.i296.rle, null ; <i1> [#uses=1]
br i1 %tmp40.i297, label %implfeeds.exit311, label %bb43.i301
This triggers thousands of times in spec.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50110 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 21:40:39 +00:00
|
|
|
bool TrueDirection = false;
|
|
|
|
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
|
2009-06-19 04:56:29 +00:00
|
|
|
PredVal = PN->getIncomingValue(i);
|
|
|
|
|
2009-07-03 00:54:20 +00:00
|
|
|
Constant *Res = GetResultOfComparison(Cmp->getPredicate(), PredVal,
|
|
|
|
RHS, Context);
|
2009-06-19 04:56:29 +00:00
|
|
|
if (!Res) {
|
|
|
|
PredVal = 0;
|
|
|
|
continue;
|
|
|
|
}
|
Start doing the significantly useful part of jump threading: handle cases
where a comparison has a phi input and that phi is a constant. For example,
stuff like:
Threading edge through bool from 'bb2149' to 'bb2231' with cost: 1, across block:
bb2237: ; preds = %bb2231, %bb2149
%tmp2328.rle = phi i32 [ %tmp2232, %bb2231 ], [ %tmp2232439, %bb2149 ] ; <i32> [#uses=2]
%done.0 = phi i32 [ %done.2, %bb2231 ], [ 0, %bb2149 ] ; <i32> [#uses=1]
%tmp2239 = icmp eq i32 %done.0, 0 ; <i1> [#uses=1]
br i1 %tmp2239, label %bb2231, label %bb2327
or
bb38.i298: ; preds = %bb33.i295, %bb1693
%tmp39.i296.rle = phi %struct.ibox* [ null, %bb1693 ], [ %tmp39.i296.rle1109, %bb33.i295 ] ; <%struct.ibox*> [#uses=2]
%minspan.1.i291.reg2mem.1 = phi i32 [ 32000, %bb1693 ], [ %minspan.0.i288, %bb33.i295 ] ; <i32> [#uses=1]
%tmp40.i297 = icmp eq %struct.ibox* %tmp39.i296.rle, null ; <i1> [#uses=1]
br i1 %tmp40.i297, label %implfeeds.exit311, label %bb43.i301
This triggers thousands of times in spec.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50110 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 21:40:39 +00:00
|
|
|
|
|
|
|
// If this folded to a constant expr, we can't do anything.
|
|
|
|
if (ConstantInt *ResC = dyn_cast<ConstantInt>(Res)) {
|
|
|
|
TrueDirection = ResC->getZExtValue();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// If this folded to undef, just go the false way.
|
|
|
|
if (isa<UndefValue>(Res)) {
|
|
|
|
TrueDirection = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, we can't fold this input.
|
2009-06-19 04:56:29 +00:00
|
|
|
PredVal = 0;
|
Start doing the significantly useful part of jump threading: handle cases
where a comparison has a phi input and that phi is a constant. For example,
stuff like:
Threading edge through bool from 'bb2149' to 'bb2231' with cost: 1, across block:
bb2237: ; preds = %bb2231, %bb2149
%tmp2328.rle = phi i32 [ %tmp2232, %bb2231 ], [ %tmp2232439, %bb2149 ] ; <i32> [#uses=2]
%done.0 = phi i32 [ %done.2, %bb2231 ], [ 0, %bb2149 ] ; <i32> [#uses=1]
%tmp2239 = icmp eq i32 %done.0, 0 ; <i1> [#uses=1]
br i1 %tmp2239, label %bb2231, label %bb2327
or
bb38.i298: ; preds = %bb33.i295, %bb1693
%tmp39.i296.rle = phi %struct.ibox* [ null, %bb1693 ], [ %tmp39.i296.rle1109, %bb33.i295 ] ; <%struct.ibox*> [#uses=2]
%minspan.1.i291.reg2mem.1 = phi i32 [ 32000, %bb1693 ], [ %minspan.0.i288, %bb33.i295 ] ; <i32> [#uses=1]
%tmp40.i297 = icmp eq %struct.ibox* %tmp39.i296.rle, null ; <i1> [#uses=1]
br i1 %tmp40.i297, label %implfeeds.exit311, label %bb43.i301
This triggers thousands of times in spec.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50110 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 21:40:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If no match, bail out.
|
2009-06-19 04:56:29 +00:00
|
|
|
if (PredVal == 0)
|
Start doing the significantly useful part of jump threading: handle cases
where a comparison has a phi input and that phi is a constant. For example,
stuff like:
Threading edge through bool from 'bb2149' to 'bb2231' with cost: 1, across block:
bb2237: ; preds = %bb2231, %bb2149
%tmp2328.rle = phi i32 [ %tmp2232, %bb2231 ], [ %tmp2232439, %bb2149 ] ; <i32> [#uses=2]
%done.0 = phi i32 [ %done.2, %bb2231 ], [ 0, %bb2149 ] ; <i32> [#uses=1]
%tmp2239 = icmp eq i32 %done.0, 0 ; <i1> [#uses=1]
br i1 %tmp2239, label %bb2231, label %bb2327
or
bb38.i298: ; preds = %bb33.i295, %bb1693
%tmp39.i296.rle = phi %struct.ibox* [ null, %bb1693 ], [ %tmp39.i296.rle1109, %bb33.i295 ] ; <%struct.ibox*> [#uses=2]
%minspan.1.i291.reg2mem.1 = phi i32 [ 32000, %bb1693 ], [ %minspan.0.i288, %bb33.i295 ] ; <i32> [#uses=1]
%tmp40.i297 = icmp eq %struct.ibox* %tmp39.i296.rle, null ; <i1> [#uses=1]
br i1 %tmp40.i297, label %implfeeds.exit311, label %bb43.i301
This triggers thousands of times in spec.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50110 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 21:40:39 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// See if the cost of duplicating this block is low enough.
|
|
|
|
unsigned JumpThreadCost = getJumpThreadDuplicationCost(BB);
|
|
|
|
if (JumpThreadCost > Threshold) {
|
|
|
|
DOUT << " Not threading BB '" << BB->getNameStart()
|
|
|
|
<< "' - Cost is too high: " << JumpThreadCost << "\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If so, we can actually do this threading. Merge any common predecessors
|
|
|
|
// that will act the same.
|
2009-06-19 04:56:29 +00:00
|
|
|
BasicBlock *PredBB = FactorCommonPHIPreds(PN, PredVal);
|
Start doing the significantly useful part of jump threading: handle cases
where a comparison has a phi input and that phi is a constant. For example,
stuff like:
Threading edge through bool from 'bb2149' to 'bb2231' with cost: 1, across block:
bb2237: ; preds = %bb2231, %bb2149
%tmp2328.rle = phi i32 [ %tmp2232, %bb2231 ], [ %tmp2232439, %bb2149 ] ; <i32> [#uses=2]
%done.0 = phi i32 [ %done.2, %bb2231 ], [ 0, %bb2149 ] ; <i32> [#uses=1]
%tmp2239 = icmp eq i32 %done.0, 0 ; <i1> [#uses=1]
br i1 %tmp2239, label %bb2231, label %bb2327
or
bb38.i298: ; preds = %bb33.i295, %bb1693
%tmp39.i296.rle = phi %struct.ibox* [ null, %bb1693 ], [ %tmp39.i296.rle1109, %bb33.i295 ] ; <%struct.ibox*> [#uses=2]
%minspan.1.i291.reg2mem.1 = phi i32 [ 32000, %bb1693 ], [ %minspan.0.i288, %bb33.i295 ] ; <i32> [#uses=1]
%tmp40.i297 = icmp eq %struct.ibox* %tmp39.i296.rle, null ; <i1> [#uses=1]
br i1 %tmp40.i297, label %implfeeds.exit311, label %bb43.i301
This triggers thousands of times in spec.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50110 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 21:40:39 +00:00
|
|
|
|
|
|
|
// Next, get our successor.
|
|
|
|
BasicBlock *SuccBB = BB->getTerminator()->getSuccessor(!TrueDirection);
|
|
|
|
|
2009-05-04 18:40:41 +00:00
|
|
|
// Ok, try to thread it!
|
|
|
|
return ThreadEdge(BB, PredBB, SuccBB, JumpThreadCost);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// ThreadEdge - We have decided that it is safe and profitable to thread an
|
|
|
|
/// edge from PredBB to SuccBB across BB. Transform the IR to reflect this
|
|
|
|
/// change.
|
|
|
|
bool JumpThreading::ThreadEdge(BasicBlock *BB, BasicBlock *PredBB,
|
|
|
|
BasicBlock *SuccBB, unsigned JumpThreadCost) {
|
|
|
|
|
Don't infininitely thread branches when a threaded edge
goes back to the block, e.g.:
Threading edge through bool from 'bb37.us.thread3829' to 'bb37.us' with cost: 1, across block:
bb37.us: ; preds = %bb37.us.thread3829, %bb37.us, %bb33
%D1361.1.us = phi i32 [ %tmp36, %bb33 ], [ %D1361.1.us, %bb37.us ], [ 0, %bb37.us.thread3829 ] ; <i32> [#uses=2]
%tmp39.us = icmp eq i32 %D1361.1.us, 0 ; <i1> [#uses=1]
br i1 %tmp39.us, label %bb37.us, label %bb42.us
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50251 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-25 04:12:29 +00:00
|
|
|
// If threading to the same block as we come from, we would infinite loop.
|
|
|
|
if (SuccBB == BB) {
|
2009-05-04 18:40:41 +00:00
|
|
|
DOUT << " Not threading across BB '" << BB->getNameStart()
|
|
|
|
<< "' - would thread to self!\n";
|
Don't infininitely thread branches when a threaded edge
goes back to the block, e.g.:
Threading edge through bool from 'bb37.us.thread3829' to 'bb37.us' with cost: 1, across block:
bb37.us: ; preds = %bb37.us.thread3829, %bb37.us, %bb33
%D1361.1.us = phi i32 [ %tmp36, %bb33 ], [ %D1361.1.us, %bb37.us ], [ 0, %bb37.us.thread3829 ] ; <i32> [#uses=2]
%tmp39.us = icmp eq i32 %D1361.1.us, 0 ; <i1> [#uses=1]
br i1 %tmp39.us, label %bb37.us, label %bb42.us
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50251 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-25 04:12:29 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-05-04 18:40:41 +00:00
|
|
|
// If threading this would thread across a loop header, don't thread the edge.
|
|
|
|
// See the comments above FindLoopHeaders for justifications and caveats.
|
|
|
|
if (LoopHeaders.count(BB)) {
|
|
|
|
DOUT << " Not threading from '" << PredBB->getNameStart()
|
|
|
|
<< "' across loop header BB '" << BB->getNameStart()
|
|
|
|
<< "' to dest BB '" << SuccBB->getNameStart()
|
|
|
|
<< "' - it might create an irreducible loop!\n";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Start doing the significantly useful part of jump threading: handle cases
where a comparison has a phi input and that phi is a constant. For example,
stuff like:
Threading edge through bool from 'bb2149' to 'bb2231' with cost: 1, across block:
bb2237: ; preds = %bb2231, %bb2149
%tmp2328.rle = phi i32 [ %tmp2232, %bb2231 ], [ %tmp2232439, %bb2149 ] ; <i32> [#uses=2]
%done.0 = phi i32 [ %done.2, %bb2231 ], [ 0, %bb2149 ] ; <i32> [#uses=1]
%tmp2239 = icmp eq i32 %done.0, 0 ; <i1> [#uses=1]
br i1 %tmp2239, label %bb2231, label %bb2327
or
bb38.i298: ; preds = %bb33.i295, %bb1693
%tmp39.i296.rle = phi %struct.ibox* [ null, %bb1693 ], [ %tmp39.i296.rle1109, %bb33.i295 ] ; <%struct.ibox*> [#uses=2]
%minspan.1.i291.reg2mem.1 = phi i32 [ 32000, %bb1693 ], [ %minspan.0.i288, %bb33.i295 ] ; <i32> [#uses=1]
%tmp40.i297 = icmp eq %struct.ibox* %tmp39.i296.rle, null ; <i1> [#uses=1]
br i1 %tmp40.i297, label %implfeeds.exit311, label %bb43.i301
This triggers thousands of times in spec.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50110 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 21:40:39 +00:00
|
|
|
// And finally, do it!
|
2009-05-04 18:40:41 +00:00
|
|
|
DOUT << " Threading edge from '" << PredBB->getNameStart() << "' to '"
|
|
|
|
<< SuccBB->getNameStart() << "' with cost: " << JumpThreadCost
|
|
|
|
<< ", across block:\n "
|
Start doing the significantly useful part of jump threading: handle cases
where a comparison has a phi input and that phi is a constant. For example,
stuff like:
Threading edge through bool from 'bb2149' to 'bb2231' with cost: 1, across block:
bb2237: ; preds = %bb2231, %bb2149
%tmp2328.rle = phi i32 [ %tmp2232, %bb2231 ], [ %tmp2232439, %bb2149 ] ; <i32> [#uses=2]
%done.0 = phi i32 [ %done.2, %bb2231 ], [ 0, %bb2149 ] ; <i32> [#uses=1]
%tmp2239 = icmp eq i32 %done.0, 0 ; <i1> [#uses=1]
br i1 %tmp2239, label %bb2231, label %bb2327
or
bb38.i298: ; preds = %bb33.i295, %bb1693
%tmp39.i296.rle = phi %struct.ibox* [ null, %bb1693 ], [ %tmp39.i296.rle1109, %bb33.i295 ] ; <%struct.ibox*> [#uses=2]
%minspan.1.i291.reg2mem.1 = phi i32 [ 32000, %bb1693 ], [ %minspan.0.i288, %bb33.i295 ] ; <i32> [#uses=1]
%tmp40.i297 = icmp eq %struct.ibox* %tmp39.i296.rle, null ; <i1> [#uses=1]
br i1 %tmp40.i297, label %implfeeds.exit311, label %bb43.i301
This triggers thousands of times in spec.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50110 91177308-0d34-0410-b5e6-96231b3b80d8
2008-04-22 21:40:39 +00:00
|
|
|
<< *BB << "\n";
|
|
|
|
|
2008-04-20 22:39:42 +00:00
|
|
|
// Jump Threading can not update SSA properties correctly if the values
|
|
|
|
// defined in the duplicated block are used outside of the block itself. For
|
|
|
|
// this reason, we spill all values that are used outside of BB to the stack.
|
2008-05-05 20:21:22 +00:00
|
|
|
for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) {
|
|
|
|
if (!I->isUsedOutsideOfBlock(BB))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// We found a use of I outside of BB. Create a new stack slot to
|
|
|
|
// break this inter-block usage pattern.
|
2008-07-23 00:34:11 +00:00
|
|
|
DemoteRegToStack(*I);
|
2008-05-05 20:21:22 +00:00
|
|
|
}
|
2008-04-20 22:39:42 +00:00
|
|
|
|
|
|
|
// We are going to have to map operands from the original BB block to the new
|
|
|
|
// copy of the block 'NewBB'. If there are PHI nodes in BB, evaluate them to
|
|
|
|
// account for entry from PredBB.
|
|
|
|
DenseMap<Instruction*, Value*> ValueMapping;
|
|
|
|
|
|
|
|
BasicBlock *NewBB =
|
|
|
|
BasicBlock::Create(BB->getName()+".thread", BB->getParent(), BB);
|
|
|
|
NewBB->moveAfter(PredBB);
|
|
|
|
|
|
|
|
BasicBlock::iterator BI = BB->begin();
|
|
|
|
for (; PHINode *PN = dyn_cast<PHINode>(BI); ++BI)
|
|
|
|
ValueMapping[PN] = PN->getIncomingValueForBlock(PredBB);
|
|
|
|
|
|
|
|
// Clone the non-phi instructions of BB into NewBB, keeping track of the
|
|
|
|
// mapping and using it to remap operands in the cloned instructions.
|
|
|
|
for (; !isa<TerminatorInst>(BI); ++BI) {
|
2009-07-09 23:48:35 +00:00
|
|
|
Instruction *New = BI->clone(*Context);
|
2008-04-20 22:39:42 +00:00
|
|
|
New->setName(BI->getNameStart());
|
|
|
|
NewBB->getInstList().push_back(New);
|
|
|
|
ValueMapping[BI] = New;
|
|
|
|
|
|
|
|
// Remap operands to patch up intra-block references.
|
|
|
|
for (unsigned i = 0, e = New->getNumOperands(); i != e; ++i)
|
2009-07-02 00:17:47 +00:00
|
|
|
if (Instruction *Inst = dyn_cast<Instruction>(New->getOperand(i))) {
|
|
|
|
DenseMap<Instruction*, Value*>::iterator I = ValueMapping.find(Inst);
|
|
|
|
if (I != ValueMapping.end())
|
|
|
|
New->setOperand(i, I->second);
|
|
|
|
}
|
2008-04-20 22:39:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// We didn't copy the terminator from BB over to NewBB, because there is now
|
|
|
|
// an unconditional jump to SuccBB. Insert the unconditional jump.
|
|
|
|
BranchInst::Create(SuccBB, NewBB);
|
|
|
|
|
|
|
|
// Check to see if SuccBB has PHI nodes. If so, we need to add entries to the
|
|
|
|
// PHI nodes for NewBB now.
|
|
|
|
for (BasicBlock::iterator PNI = SuccBB->begin(); isa<PHINode>(PNI); ++PNI) {
|
|
|
|
PHINode *PN = cast<PHINode>(PNI);
|
|
|
|
// Ok, we have a PHI node. Figure out what the incoming value was for the
|
|
|
|
// DestBlock.
|
|
|
|
Value *IV = PN->getIncomingValueForBlock(BB);
|
|
|
|
|
|
|
|
// Remap the value if necessary.
|
2009-07-02 00:17:47 +00:00
|
|
|
if (Instruction *Inst = dyn_cast<Instruction>(IV)) {
|
|
|
|
DenseMap<Instruction*, Value*>::iterator I = ValueMapping.find(Inst);
|
|
|
|
if (I != ValueMapping.end())
|
|
|
|
IV = I->second;
|
|
|
|
}
|
2008-04-20 22:39:42 +00:00
|
|
|
PN->addIncoming(IV, NewBB);
|
|
|
|
}
|
2008-04-20 21:13:06 +00:00
|
|
|
|
2008-12-01 04:48:07 +00:00
|
|
|
// Ok, NewBB is good to go. Update the terminator of PredBB to jump to
|
2008-04-20 22:39:42 +00:00
|
|
|
// NewBB instead of BB. This eliminates predecessors from BB, which requires
|
|
|
|
// us to simplify any PHI nodes in BB.
|
|
|
|
TerminatorInst *PredTerm = PredBB->getTerminator();
|
|
|
|
for (unsigned i = 0, e = PredTerm->getNumSuccessors(); i != e; ++i)
|
|
|
|
if (PredTerm->getSuccessor(i) == BB) {
|
|
|
|
BB->removePredecessor(PredBB);
|
|
|
|
PredTerm->setSuccessor(i, NewBB);
|
|
|
|
}
|
2008-12-01 04:48:07 +00:00
|
|
|
|
|
|
|
// At this point, the IR is fully up to date and consistent. Do a quick scan
|
|
|
|
// over the new instructions and zap any that are constants or dead. This
|
|
|
|
// frequently happens because of phi translation.
|
|
|
|
BI = NewBB->begin();
|
|
|
|
for (BasicBlock::iterator E = NewBB->end(); BI != E; ) {
|
|
|
|
Instruction *Inst = BI++;
|
2009-07-06 18:42:36 +00:00
|
|
|
if (Constant *C = ConstantFoldInstruction(Inst, BB->getContext(), TD)) {
|
2008-12-01 04:48:07 +00:00
|
|
|
Inst->replaceAllUsesWith(C);
|
|
|
|
Inst->eraseFromParent();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
RecursivelyDeleteTriviallyDeadInstructions(Inst);
|
|
|
|
}
|
2009-05-04 18:40:41 +00:00
|
|
|
|
|
|
|
// Threaded an edge!
|
|
|
|
++NumThreads;
|
|
|
|
return true;
|
2008-04-20 21:13:06 +00:00
|
|
|
}
|