From: Frits van Bommel Date: Mon, 6 Dec 2010 23:36:56 +0000 (+0000) Subject: Implement jump threading of 'indirectbr' by keeping track of whether we're looking... X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=6033b346e20d6932cc62c754cf23ae51786724d6;p=oota-llvm.git Implement jump threading of 'indirectbr' by keeping track of whether we're looking for ConstantInt*s or BlockAddress*s. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121066 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Scalar/JumpThreading.cpp b/lib/Transforms/Scalar/JumpThreading.cpp index 1bcbd0a7dc2..27bd6687bf3 100644 --- a/lib/Transforms/Scalar/JumpThreading.cpp +++ b/lib/Transforms/Scalar/JumpThreading.cpp @@ -49,6 +49,13 @@ namespace { typedef SmallVectorImpl > PredValueInfo; typedef SmallVector, 8> PredValueInfoTy; + // This is used to keep track of what kind of constant we're currently hoping + // to find. + enum ConstantPreference { + WantInteger, + WantBlockAddress + }; + /// 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 @@ -109,8 +116,10 @@ namespace { const SmallVectorImpl &PredBBs); bool ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB, - PredValueInfo &Result); - bool ProcessThreadableEdges(Value *Cond, BasicBlock *BB); + PredValueInfo &Result, + ConstantPreference Preference); + bool ProcessThreadableEdges(Value *Cond, BasicBlock *BB, + ConstantPreference Preference); bool ProcessBranchOnDuplicateCond(BasicBlock *PredBB, BasicBlock *DestBB); @@ -247,6 +256,10 @@ static unsigned getJumpThreadDuplicationCost(const BasicBlock *BB) { if (isa(I)) Size = Size > 6 ? Size-6 : 0; + // The same holds for indirect branches, but slightly more so. + if (isa(I)) + Size = Size > 8 ? Size-8 : 0; + return Size; } @@ -275,9 +288,10 @@ void JumpThreading::FindLoopHeaders(Function &F) { /// getKnownConstant - Helper method to determine if we can thread over a /// terminator with the given value as its condition, and if so what value to -/// use for that. +/// use for that. What kind of value this is depends on whether we want an +/// integer or a block address, but an undef is always accepted. /// Returns null if Val is null or not an appropriate constant. -static Constant *getKnownConstant(Value *Val) { +static Constant *getKnownConstant(Value *Val, ConstantPreference Preference) { if (!Val) return 0; @@ -285,26 +299,22 @@ static Constant *getKnownConstant(Value *Val) { if (UndefValue *U = dyn_cast(Val)) return U; - return dyn_cast(Val); -} + if (Preference == WantBlockAddress) + return dyn_cast(Val->stripPointerCasts()); -// Helper method for ComputeValueKnownInPredecessors. If Value is a -// ConstantInt or undef, push it. Otherwise, do nothing. -static void PushKnownConstantOrUndef(PredValueInfo &Result, Constant *Value, - BasicBlock *BB) { - if (Constant *KC = getKnownConstant(Value)) - Result.push_back(std::make_pair(KC, BB)); + return dyn_cast(Val); } /// ComputeValueKnownInPredecessors - Given a basic block BB and a value V, see -/// if we can infer that the value is a known ConstantInt in any of our -/// predecessors. If so, return the known list of value and pred BB in the -/// result vector. If a value is known to be undef, it is returned as null. +/// if we can infer that the value is a known ConstantInt/BlockAddress or undef +/// in any of our predecessors. If so, return the known list of value and pred +/// BB in the result vector. /// /// This returns true if there were any known values. /// bool JumpThreading:: -ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB,PredValueInfo &Result){ +ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB, PredValueInfo &Result, + ConstantPreference Preference) { // This method walks up use-def chains recursively. Because of this, we could // get into an infinite loop going around loops in the use-def chain. To // prevent this, keep track of what (value, block) pairs we've already visited @@ -317,7 +327,7 @@ ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB,PredValueInfo &Result){ RecursionSetRemover remover(RecursionSet, std::make_pair(V, BB)); // If V is a constant, then it is known in all predecessors. - if (Constant *KC = getKnownConstant(V)) { + if (Constant *KC = getKnownConstant(V, Preference)) { for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) Result.push_back(std::make_pair(KC, *PI)); @@ -347,7 +357,7 @@ ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB,PredValueInfo &Result){ // If the value is known by LazyValueInfo to be a constant in a // predecessor, use that information to try to thread this block. Constant *PredCst = LVI->getConstantOnEdge(V, P, BB); - if (Constant *KC = getKnownConstant(PredCst)) + if (Constant *KC = getKnownConstant(PredCst, Preference)) Result.push_back(std::make_pair(KC, P)); } @@ -358,14 +368,13 @@ ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB,PredValueInfo &Result){ if (PHINode *PN = dyn_cast(I)) { for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { Value *InVal = PN->getIncomingValue(i); - if (Constant *KC = getKnownConstant(InVal)) { + if (Constant *KC = getKnownConstant(InVal, Preference)) { Result.push_back(std::make_pair(KC, PN->getIncomingBlock(i))); } else { Constant *CI = LVI->getConstantOnEdge(InVal, PN->getIncomingBlock(i), BB); - // LVI returns null is no value could be determined. - if (!CI) continue; - PushKnownConstantOrUndef(Result, CI, PN->getIncomingBlock(i)); + if (Constant *KC = getKnownConstant(CI, Preference)) + Result.push_back(std::make_pair(KC, PN->getIncomingBlock(i))); } } @@ -376,12 +385,15 @@ ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB,PredValueInfo &Result){ // Handle some boolean conditions. if (I->getType()->getPrimitiveSizeInBits() == 1) { + assert(Preference == WantInteger && "One-bit non-integer type?"); // X | true -> true // X & false -> false if (I->getOpcode() == Instruction::Or || I->getOpcode() == Instruction::And) { - ComputeValueKnownInPredecessors(I->getOperand(0), BB, LHSVals); - ComputeValueKnownInPredecessors(I->getOperand(1), BB, RHSVals); + ComputeValueKnownInPredecessors(I->getOperand(0), BB, LHSVals, + WantInteger); + ComputeValueKnownInPredecessors(I->getOperand(1), BB, RHSVals, + WantInteger); if (LHSVals.empty() && RHSVals.empty()) return false; @@ -421,7 +433,8 @@ ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB,PredValueInfo &Result){ if (I->getOpcode() == Instruction::Xor && isa(I->getOperand(1)) && cast(I->getOperand(1))->isOne()) { - ComputeValueKnownInPredecessors(I->getOperand(0), BB, Result); + ComputeValueKnownInPredecessors(I->getOperand(0), BB, Result, + WantInteger); if (Result.empty()) return false; @@ -434,16 +447,20 @@ ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB,PredValueInfo &Result){ // Try to simplify some other binary operator values. } else if (BinaryOperator *BO = dyn_cast(I)) { + assert(Preference != WantBlockAddress + && "A binary operator creating a block address?"); if (ConstantInt *CI = dyn_cast(BO->getOperand(1))) { PredValueInfoTy LHSVals; - ComputeValueKnownInPredecessors(BO->getOperand(0), BB, LHSVals); + ComputeValueKnownInPredecessors(BO->getOperand(0), BB, LHSVals, + WantInteger); // Try to use constant folding to simplify the binary operator. for (unsigned i = 0, e = LHSVals.size(); i != e; ++i) { Constant *V = LHSVals[i].first; Constant *Folded = ConstantExpr::get(BO->getOpcode(), V, CI); - PushKnownConstantOrUndef(Result, Folded, LHSVals[i].second); + if (Constant *KC = getKnownConstant(Folded, WantInteger)) + Result.push_back(std::make_pair(KC, LHSVals[i].second)); } } @@ -452,6 +469,7 @@ ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB,PredValueInfo &Result){ // Handle compare with phi operand, where the PHI is defined in this block. if (CmpInst *Cmp = dyn_cast(I)) { + assert(Preference == WantInteger && "Compares only produce integers"); PHINode *PN = dyn_cast(Cmp->getOperand(0)); if (PN && PN->getParent() == BB) { // We can do this simplification if any comparisons fold to true or false. @@ -474,8 +492,8 @@ ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB,PredValueInfo &Result){ Res = ConstantInt::get(Type::getInt1Ty(LHS->getContext()), ResT); } - if (Constant *ConstRes = dyn_cast(Res)) - PushKnownConstantOrUndef(Result, ConstRes, PredBB); + if (Constant *KC = getKnownConstant(Res, WantInteger)) + Result.push_back(std::make_pair(KC, PredBB)); } return !Result.empty(); @@ -510,13 +528,15 @@ ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB,PredValueInfo &Result){ // and evaluate it statically if we can. if (Constant *CmpConst = dyn_cast(Cmp->getOperand(1))) { PredValueInfoTy LHSVals; - ComputeValueKnownInPredecessors(I->getOperand(0), BB, LHSVals); + ComputeValueKnownInPredecessors(I->getOperand(0), BB, LHSVals, + WantInteger); for (unsigned i = 0, e = LHSVals.size(); i != e; ++i) { Constant *V = LHSVals[i].first; Constant *Folded = ConstantExpr::getCompare(Cmp->getPredicate(), V, CmpConst); - PushKnownConstantOrUndef(Result, Folded, LHSVals[i].second); + if (Constant *KC = getKnownConstant(Folded, WantInteger)) + Result.push_back(std::make_pair(KC, LHSVals[i].second)); } return !Result.empty(); @@ -526,7 +546,7 @@ ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB,PredValueInfo &Result){ // If all else fails, see if LVI can figure out a constant value for us. Constant *CI = LVI->getConstant(V, BB); - if (Constant *KC = getKnownConstant(CI)) { + if (Constant *KC = getKnownConstant(CI, Preference)) { for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) Result.push_back(std::make_pair(KC, *PI)); } @@ -590,17 +610,25 @@ bool JumpThreading::ProcessBlock(BasicBlock *BB) { } } - // Look to see if the terminator is a branch of switch, if not we can't thread - // it. + // What kind of constant we're looking for. + ConstantPreference Preference = WantInteger; + + // Look to see if the terminator is a conditional branch, switch or indirect + // branch, if not we can't thread it. Value *Condition; - if (BranchInst *BI = dyn_cast(BB->getTerminator())) { + Instruction *Terminator = BB->getTerminator(); + if (BranchInst *BI = dyn_cast(Terminator)) { // Can't thread an unconditional jump. if (BI->isUnconditional()) return false; Condition = BI->getCondition(); - } else if (SwitchInst *SI = dyn_cast(BB->getTerminator())) + } else if (SwitchInst *SI = dyn_cast(Terminator)) { Condition = SI->getCondition(); - else + } else if (IndirectBrInst *IB = dyn_cast(Terminator)) { + Condition = IB->getAddress()->stripPointerCasts(); + Preference = WantBlockAddress; + } else { return false; // Must be an invoke. + } // If the terminator is branching on an undef, we can pick any of the // successors to branch to. Let GetBestDestForJumpOnUndef decide. @@ -624,7 +652,7 @@ bool JumpThreading::ProcessBlock(BasicBlock *BB) { // If the terminator of this block is branching on a constant, simplify the // terminator to an unconditional branch. This can occur due to threading in // other blocks. - if (getKnownConstant(Condition)) { + if (getKnownConstant(Condition, Preference)) { DEBUG(dbgs() << " In block '" << BB->getName() << "' folding terminator: " << *BB->getTerminator() << '\n'); ++NumFolds; @@ -637,7 +665,7 @@ bool JumpThreading::ProcessBlock(BasicBlock *BB) { // All the rest of our checks depend on the condition being an instruction. if (CondInst == 0) { // FIXME: Unify this with code below. - if (ProcessThreadableEdges(Condition, BB)) + if (ProcessThreadableEdges(Condition, BB, Preference)) return true; return false; } @@ -703,7 +731,7 @@ bool JumpThreading::ProcessBlock(BasicBlock *BB) { // a PHI node in the current block. If we can prove that any predecessors // compute a predictable value based on a PHI node, thread those predecessors. // - if (ProcessThreadableEdges(CondInst, BB)) + if (ProcessThreadableEdges(CondInst, BB, Preference)) return true; // If this is an otherwise-unfoldable branch on a phi node in the current @@ -1088,14 +1116,15 @@ FindMostPopularDest(BasicBlock *BB, return MostPopularDest; } -bool JumpThreading::ProcessThreadableEdges(Value *Cond, BasicBlock *BB) { +bool JumpThreading::ProcessThreadableEdges(Value *Cond, BasicBlock *BB, + ConstantPreference Preference) { // If threading this would thread across a loop header, don't even try to // thread the edge. if (LoopHeaders.count(BB)) return false; PredValueInfoTy PredValues; - if (!ComputeValueKnownInPredecessors(Cond, BB, PredValues)) + if (!ComputeValueKnownInPredecessors(Cond, BB, PredValues, Preference)) return false; assert(!PredValues.empty() && @@ -1135,9 +1164,12 @@ bool JumpThreading::ProcessThreadableEdges(Value *Cond, BasicBlock *BB) { DestBB = 0; else if (BranchInst *BI = dyn_cast(BB->getTerminator())) DestBB = BI->getSuccessor(cast(Val)->isZero()); - else { - SwitchInst *SI = cast(BB->getTerminator()); + else if (SwitchInst *SI = dyn_cast(BB->getTerminator())) DestBB = SI->getSuccessor(SI->findCaseValue(cast(Val))); + else { + assert(isa(BB->getTerminator()) + && "Unexpected terminator"); + DestBB = cast(Val)->getBasicBlock(); } // If we have exactly one destination, remember it for efficiency below. @@ -1256,9 +1288,11 @@ bool JumpThreading::ProcessBranchOnXOR(BinaryOperator *BO) { PredValueInfoTy XorOpValues; bool isLHS = true; - if (!ComputeValueKnownInPredecessors(BO->getOperand(0), BB, XorOpValues)) { + if (!ComputeValueKnownInPredecessors(BO->getOperand(0), BB, XorOpValues, + WantInteger)) { assert(XorOpValues.empty()); - if (!ComputeValueKnownInPredecessors(BO->getOperand(1), BB, XorOpValues)) + if (!ComputeValueKnownInPredecessors(BO->getOperand(1), BB, XorOpValues, + WantInteger)) return false; isLHS = false; } diff --git a/test/Transforms/JumpThreading/indirectbr.ll b/test/Transforms/JumpThreading/indirectbr.ll new file mode 100644 index 00000000000..6c5321d3194 --- /dev/null +++ b/test/Transforms/JumpThreading/indirectbr.ll @@ -0,0 +1,61 @@ +; RUN: opt -S < %s -jump-threading | FileCheck %s + +; Keep block addresses alive. +@addresses = constant [4 x i8*] [ + i8* blockaddress(@test1, %L1), i8* blockaddress(@test1, %L2), + i8* blockaddress(@test2, %L1), i8* blockaddress(@test2, %L2) +] + +declare void @bar() +declare void @baz() + + + +; Check basic jump threading for indirectbr instructions. + +; CHECK: void @test1 +; CHECK: br i1 %tobool, label %L1, label %indirectgoto +; CHECK-NOT: if.else: +; CHECK: L1: +; CHECK: indirectbr i8* %address, [label %L1, label %L2] +define void @test1(i32 %i, i8* %address) nounwind { +entry: + %rem = srem i32 %i, 2 + %tobool = icmp ne i32 %rem, 0 + br i1 %tobool, label %indirectgoto, label %if.else + +if.else: ; preds = %entry + br label %indirectgoto + +L1: ; preds = %indirectgoto + call void @bar() + ret void + +L2: ; preds = %indirectgoto + call void @baz() + ret void + +indirectgoto: ; preds = %if.else, %entry + %indirect.goto.dest = phi i8* [ %address, %if.else ], [ blockaddress(@test1, %L1), %entry ] + indirectbr i8* %indirect.goto.dest, [label %L1, label %L2] +} + + +; Check constant folding of indirectbr + +; CHECK: void @test2 +; CHECK-NEXT: : +; CHECK-NEXT: call void @bar +; CHECK-NEXT: ret void +define void @test2() nounwind { +entry: + indirectbr i8* blockaddress(@test2, %L1), [label %L1, label %L2] + +L1: ; preds = %indirectgoto + call void @bar() + ret void + +L2: ; preds = %indirectgoto + call void @baz() + ret void +}