[llvm-commits] [llvm] r50096 - in /llvm/trunk: lib/Transforms/Scalar/JumpThreading.cpp test/Transforms/JumpThreading/and-cond.ll

Evan Cheng evan.cheng at apple.com
Tue Apr 22 00:31:23 PDT 2008


On Apr 22, 2008, at 12:05 AM, Chris Lattner wrote:

> Author: lattner
> Date: Tue Apr 22 02:05:46 2008
> New Revision: 50096
>
> URL: http://llvm.org/viewvc/llvm-project?rev=50096&view=rev
> Log:
> 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.

Do you mean iftmp.251.0, not tmp.0.i?

Evan

>
>
>
> 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.
>
>
> Added:
>    llvm/trunk/test/Transforms/JumpThreading/and-cond.ll
> Modified:
>    llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp
>
> Modified: llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp?rev=50096&r1=50095&r2=50096&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp Tue Apr 22  
> 02:05:46 2008
> @@ -57,8 +57,10 @@
>     bool runOnFunction(Function &F);
>     bool ThreadBlock(BasicBlock *BB);
>     void ThreadEdge(BasicBlock *BB, BasicBlock *PredBB, BasicBlock  
> *SuccBB);
> -
> +    BasicBlock *FactorCommonPHIPreds(PHINode *PN, Constant *CstVal);
> +
>     bool ProcessJumpOnPHI(PHINode *PN);
> +    bool ProcessJumpOnLogicalPHI(PHINode *PN, bool isAnd);
>   };
>   char JumpThreading::ID = 0;
>   RegisterPass<JumpThreading> X("jump-threading", "Jump Threading");
> @@ -85,6 +87,29 @@
>   return EverChanged;
> }
>
> +/// 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.
> +///
> +BasicBlock *JumpThreading::FactorCommonPHIPreds(PHINode *PN,  
> Constant *CstVal) {
> +  SmallVector<BasicBlock*, 16> CommonPreds;
> +  for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
> +    if (PN->getIncomingValue(i) == CstVal)
> +      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);
> +}
> +
> +
> /// getJumpThreadDuplicationCost - Return the cost of duplicating  
> this block to
> /// thread across it.
> static unsigned getJumpThreadDuplicationCost(const BasicBlock *BB) {
> @@ -163,6 +188,23 @@
>   if (PN && PN->getParent() == BB)
>     return ProcessJumpOnPHI(PN);
>
> +  // If this is a conditional branch whose condition is and/or of a  
> phi, try to
> +  // simplify it.
> +  if (BinaryOperator *CondI = dyn_cast<BinaryOperator>(Condition)) {
> +    if ((CondI->getOpcode() == Instruction::And ||
> +         CondI->getOpcode() == Instruction::Or) &&
> +        isa<BranchInst>(BB->getTerminator())) {
> +      if (PHINode *PN = dyn_cast<PHINode>(CondI->getOperand(0)))
> +        if (PN->getParent() == BB &&
> +            ProcessJumpOnLogicalPHI(PN, CondI->getOpcode() ==  
> Instruction::And))
> +          return true;
> +      if (PHINode *PN = dyn_cast<PHINode>(CondI->getOperand(1)))
> +        if (PN->getParent() == BB &&
> +            ProcessJumpOnLogicalPHI(PN, CondI->getOpcode() ==  
> Instruction::And))
> +          return true;
> +    }
> +  }
> +
>   return false;
> }
>
> @@ -196,9 +238,11 @@
>     return false;
>   }
>
> -  // If so, we can actually do this threading.  Figure out which  
> predecessor and
> -  // which successor we are threading for.
> -  BasicBlock *PredBB = PN->getIncomingBlock(PredNo);
> +  // 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.
>   BasicBlock *SuccBB;
>   if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator()))
>     SuccBB = BI->getSuccessor(PredCst == ConstantInt::getFalse());
> @@ -207,31 +251,73 @@
>     SuccBB = SI->getSuccessor(SI->findCaseValue(PredCst));
>   }
>
> -  // 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.
> -  SmallVector<BasicBlock*, 16> CommonPreds;
> -  for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
> -    if (PN->getIncomingValue(i) == PredCst)
> -      CommonPreds.push_back(PN->getIncomingBlock(i));
> -  if (CommonPreds.size() != 1) {
> -    DOUT << "  Factoring out " << CommonPreds.size()
> -         << " common predecessors.\n";
> -    PredBB = SplitBlockPredecessors(BB, &CommonPreds[0],  
> CommonPreds.size(),
> -                                    ".thr_comm", this);
> -  }
> -
> +  // And finally, do it!
>   DOUT << "  Threading edge from '" << PredBB->getNameStart() << "'  
> to '"
>        << SuccBB->getNameStart() << "' with cost: " << JumpThreadCost
>        << ", across block:\n    "
> -       << *BB;
> +       << *BB << "\n";
>
>   ThreadEdge(BB, PredBB, SuccBB);
>   ++NumThreads;
>   return true;
> }
>
> +/// 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.
> +///
> +bool JumpThreading::ProcessJumpOnLogicalPHI(PHINode *PN, bool  
> isAnd) {
> +
> +  // 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;
> +  ConstantInt *PredCst = ConstantInt::get(Type::Int1Ty, !isAnd);
> +  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.
> +  BasicBlock *BB = PN->getParent();
> +  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);
> +
> +  // And finally, do it!
> +  DOUT << "  Threading edge through bool from '" << PredBB- 
> >getNameStart()
> +       << "' to '" << SuccBB->getNameStart() << "' with cost: "
> +       << JumpThreadCost << ", across block:\n    "
> +       << *BB << "\n";
> +
> +  ThreadEdge(BB, PredBB, SuccBB);
> +  ++NumThreads;
> +  return true;
> +}
> +
> +
> /// 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.
>
> Added: llvm/trunk/test/Transforms/JumpThreading/and-cond.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/and-cond.ll?rev=50096&view=auto
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- llvm/trunk/test/Transforms/JumpThreading/and-cond.ll (added)
> +++ llvm/trunk/test/Transforms/JumpThreading/and-cond.ll Tue Apr 22  
> 02:05:46 2008
> @@ -0,0 +1,32 @@
> +; RUN: llvm-as < %s | opt -jump-threading -mem2reg -instcombine - 
> simplifycfg  | llvm-dis | grep {ret i32 %v1}
> +; There should be no uncond branches left.
> +; RUN: llvm-as < %s | opt -jump-threading -mem2reg -instcombine - 
> simplifycfg  | llvm-dis | not grep {br label}
> +
> +declare i32 @f1()
> +declare i32 @f2()
> +declare void @f3()
> +
> +define i32 @test(i1 %cond, i1 %cond2) {
> +	br i1 %cond, label %T1, label %F1
> +
> +T1:
> +	%v1 = call i32 @f1()
> +	br label %Merge
> +
> +F1:
> +	%v2 = call i32 @f2()
> +	br label %Merge
> +
> +Merge:
> +	%A = phi i1 [true, %T1], [false, %F1]
> +	%B = phi i32 [%v1, %T1], [%v2, %F1]
> +	%C = and i1 %A, %cond2
> +	br i1 %C, label %T2, label %F2
> +
> +T2:
> +	call void @f3()
> +	ret i32 %B
> +
> +F2:
> +	ret i32 %B
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list