r201528 - Change PGO instrumentation to compute counts in a separate AST traversal.

Justin Bogner mail at justinbogner.com
Mon Feb 17 18:35:44 PST 2014


Bob Wilson <bob.wilson at apple.com> writes:
> Change PGO instrumentation to compute counts in a separate AST traversal.
>
> Previously, we made one traversal of the AST prior to codegen to assign
> counters to the ASTs and then propagated the count values during codegen. This
> patch now adds a separate AST traversal prior to codegen for the
> -fprofile-instr-use option to propagate the count values. The counts are then
> saved in a map from which they can be retrieved during codegen.

Thanks for doing this.

It would be really nice if the RegionCounter type was restrained to
CodeGenPGO, now that almost everything it does is in ComputeRegionCounts.
There are a few ways this is still used in the rest of CodeGen:

1. Calls to beginRegion. I think these should really just be
   emitCounterIncrements - more on that later.

2. EmitBlockWithFallThrough. This only needs RegionCounter for a call to
   beginRegion, so it's basically a special case of (1).

3. PGO.createLoopWeights(S.getCond(), Cnt). The counter is associated
   with S here, and all invocations use S.getCond() as the first
   argument. We can easily have this simply take a statement and hide
   the implementation from the caller.

4. The TrueCount of EmitBranchOnBoolExpr. This one's a bit tricky, as
   we need the count associated with the parent statement of the
   expression we're evaluating.

5. A number of places in EmitCaseStmt/EmitSwitchStmt/etc. Can't more of
   this move into ComputeRegionCounts?

I have a few more specific thoughts below.

> This new approach has several advantages:
>
> 1. It gets rid of a lot of extra PGO-related code that had previously been
> added to codegen.
>
> 2. It fixes a serious bug. My original implementation (which was mailed to the
> list but never committed) used 3 counters for every loop. Justin improved it to
> move 2 of those counters into the less-frequently executed breaks and continues,
> but that turned out to produce wrong count values in some cases. The solution
> requires visiting a loop body before the condition so that the count for the
> condition properly includes the break and continue counts. Changing codegen to
> visit a loop body first would be a fairly invasive change, but with a separate
> AST traversal, it is easy to control the order of traversal. I've added a
> testcase (provided by Justin) to make sure this works correctly.
>
> 3. It improves the instrumentation overhead, reducing the number of counters for
> a loop from 3 to 1. We no longer need dedicated counters for breaks and
> continues, since we can just use the propagated count values when visiting
> breaks and continues.
>
> To make this work, I needed to make a change to the way we count case
> statements, going back to my original approach of not including the fall-through
> in the counter values. This was necessary because there isn't always an AST node
> that can be used to record the fall-through count. Now case statements are
> handled the same as default statements, with the fall-through paths branching
> over the counter increments.  While I was at it, I also went back to using this
> approach for do-loops -- omitting the fall-through count into the loop body
> simplifies some of the calculations and make them behave the same as other
> loops. Whenever we start using this instrumentation for coverage, we'll need
> to add the fall-through counts into the counter values.
>
> Modified:
>     cfe/trunk/lib/CodeGen/CGExpr.cpp
>     cfe/trunk/lib/CodeGen/CGExprAgg.cpp
>     cfe/trunk/lib/CodeGen/CGExprComplex.cpp
>     cfe/trunk/lib/CodeGen/CGExprScalar.cpp
>     cfe/trunk/lib/CodeGen/CGObjC.cpp
>     cfe/trunk/lib/CodeGen/CGStmt.cpp
>     cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
>     cfe/trunk/lib/CodeGen/CodeGenFunction.h
>     cfe/trunk/lib/CodeGen/CodeGenPGO.cpp
>     cfe/trunk/lib/CodeGen/CodeGenPGO.h
>     cfe/trunk/test/CodeGen/Inputs/instr-profile.pgodata
>     cfe/trunk/test/CodeGen/instr-profile.c
>     cfe/trunk/test/CodeGenCXX/Inputs/instr-profile-throws.pgodata
>     cfe/trunk/test/CodeGenCXX/instr-profile-throws.cpp
>
> Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=201528&r1=201527&r2=201528&view=diff==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Mon Feb 17 13:21:09 2014
> @@ -85,6 +85,7 @@ llvm::AllocaInst *CodeGenFunction::Creat
>  /// EvaluateExprAsBool - Perform the usual unary conversions on the specified
>  /// expression and compare the result against zero, returning an Int1Ty value.
>  llvm::Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) {
> +  PGO.setCurrentStmt(E);
>    if (const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>()) {
>      llvm::Value *MemPtr = EmitScalarExpr(E);
>      return CGM.getCXXABI().EmitMemberPointerIsNotNull(*this, MemPtr, MPT);
> @@ -2680,7 +2681,6 @@ EmitConditionalOperatorLValue(const Abst
>    eval.begin(*this);
>    LValue lhs = EmitLValue(expr->getTrueExpr());
>    eval.end(*this);
> -  Cnt.adjustForControlFlow();
>  
>    if (!lhs.isSimple())
>      return EmitUnsupportedLValue(expr, "conditional operator");
> @@ -2690,17 +2690,14 @@ EmitConditionalOperatorLValue(const Abst
>  
>    // Any temporaries created here are conditional.
>    EmitBlock(rhsBlock);
> -  Cnt.beginElseRegion();
>    eval.begin(*this);
>    LValue rhs = EmitLValue(expr->getFalseExpr());
>    eval.end(*this);
> -  Cnt.adjustForControlFlow();
>    if (!rhs.isSimple())
>      return EmitUnsupportedLValue(expr, "conditional operator");
>    rhsBlock = Builder.GetInsertBlock();
>  
>    EmitBlock(contBlock);
> -  Cnt.applyAdjustmentsToRegion();
>  
>    llvm::PHINode *phi = Builder.CreatePHI(lhs.getAddress()->getType(), 2,
>                                           "cond-lvalue");
>
> Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=201528&r1=201527&r2=201528&view=diff==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Mon Feb 17 13:21:09 2014
> @@ -903,7 +903,6 @@ VisitAbstractConditionalOperator(const A
>    CGF.EmitBlock(LHSBlock);
>    Cnt.beginRegion(Builder);
>    Visit(E->getTrueExpr());
> -  Cnt.adjustForControlFlow();
>    eval.end(CGF);
>  
>    assert(CGF.HaveInsertPoint() && "expression evaluation ended with no IP!");
> @@ -917,13 +916,10 @@ VisitAbstractConditionalOperator(const A
>  
>    eval.begin(CGF);
>    CGF.EmitBlock(RHSBlock);
> -  Cnt.beginElseRegion();
>    Visit(E->getFalseExpr());
> -  Cnt.adjustForControlFlow();
>    eval.end(CGF);
>  
>    CGF.EmitBlock(ContBlock);
> -  Cnt.applyAdjustmentsToRegion();
>  }
>  
>  void AggExprEmitter::VisitChooseExpr(const ChooseExpr *CE) {
>
> Modified: cfe/trunk/lib/CodeGen/CGExprComplex.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprComplex.cpp?rev=201528&r1=201527&r2=201528&view=diff==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprComplex.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprComplex.cpp Mon Feb 17 13:21:09 2014
> @@ -760,20 +760,16 @@ VisitAbstractConditionalOperator(const A
>    CGF.EmitBlock(LHSBlock);
>    Cnt.beginRegion(Builder);
>    ComplexPairTy LHS = Visit(E->getTrueExpr());
> -  Cnt.adjustForControlFlow();
>    LHSBlock = Builder.GetInsertBlock();
>    CGF.EmitBranch(ContBlock);
>    eval.end(CGF);
>  
>    eval.begin(CGF);
>    CGF.EmitBlock(RHSBlock);
> -  Cnt.beginElseRegion();
>    ComplexPairTy RHS = Visit(E->getFalseExpr());
> -  Cnt.adjustForControlFlow();
>    RHSBlock = Builder.GetInsertBlock();
>    CGF.EmitBlock(ContBlock);
>    eval.end(CGF);
> -  Cnt.applyAdjustmentsToRegion();
>  
>    // Create a PHI node for the real part.
>    llvm::PHINode *RealPN = Builder.CreatePHI(LHS.first->getType(), 2, "cond.r");
>
> Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=201528&r1=201527&r2=201528&view=diff==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Mon Feb 17 13:21:09 2014
> @@ -2934,7 +2934,6 @@ Value *ScalarExprEmitter::VisitBinLAnd(c
>    CGF.EmitBlock(RHSBlock);
>    Cnt.beginRegion(Builder);
>    Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
> -  Cnt.adjustForControlFlow();
>    eval.end(CGF);
>  
>    // Reaquire the RHS block, as there may be subblocks inserted.
> @@ -2947,7 +2946,6 @@ Value *ScalarExprEmitter::VisitBinLAnd(c
>      Builder.SetCurrentDebugLocation(llvm::DebugLoc());
>    CGF.EmitBlock(ContBlock);
>    PN->addIncoming(RHSCond, RHSBlock);
> -  Cnt.applyAdjustmentsToRegion();
>  
>    // ZExt result to int.
>    return Builder.CreateZExtOrBitCast(PN, ResTy, "land.ext");
> @@ -3017,7 +3015,6 @@ Value *ScalarExprEmitter::VisitBinLOr(co
>    CGF.EmitBlock(RHSBlock);
>    Cnt.beginRegion(Builder);
>    Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS());
> -  Cnt.adjustForControlFlow();
>  
>    eval.end(CGF);
>  
> @@ -3028,7 +3025,6 @@ Value *ScalarExprEmitter::VisitBinLOr(co
>    // into the phi node for the edge with the value of RHSCond.
>    CGF.EmitBlock(ContBlock);
>    PN->addIncoming(RHSCond, RHSBlock);
> -  Cnt.applyAdjustmentsToRegion();
>  
>    // ZExt result to int.
>    return Builder.CreateZExtOrBitCast(PN, ResTy, "lor.ext");
> @@ -3171,21 +3167,17 @@ VisitAbstractConditionalOperator(const A
>    eval.begin(CGF);
>    Value *LHS = Visit(lhsExpr);
>    eval.end(CGF);
> -  Cnt.adjustForControlFlow();
>  
>    LHSBlock = Builder.GetInsertBlock();
>    Builder.CreateBr(ContBlock);
>  
>    CGF.EmitBlock(RHSBlock);
> -  Cnt.beginElseRegion();
>    eval.begin(CGF);
>    Value *RHS = Visit(rhsExpr);
>    eval.end(CGF);
> -  Cnt.adjustForControlFlow();
>  
>    RHSBlock = Builder.GetInsertBlock();
>    CGF.EmitBlock(ContBlock);
> -  Cnt.applyAdjustmentsToRegion();
>  
>    // If the LHS or RHS is a throw expression, it will be legitimately null.
>    if (!LHS)
>
> Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=201528&r1=201527&r2=201528&view=diff==============================================================================
> --- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGObjC.cpp Mon Feb 17 13:21:09 2014
> @@ -1628,7 +1628,7 @@ void CodeGenFunction::EmitObjCForCollect
>      EmitAutoVarCleanups(variable);
>  
>    // Perform the loop body, setting up break and continue labels.
> -  BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody, &Cnt));
> +  BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody));
>    {
>      RunCleanupsScope Scope(*this);
>      EmitStmt(S.getBody());
>
> Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=201528&r1=201527&r2=201528&view=diff==============================================================================
> --- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGStmt.cpp Mon Feb 17 13:21:09 2014
> @@ -43,6 +43,7 @@ void CodeGenFunction::EmitStopPoint(cons
>  
>  void CodeGenFunction::EmitStmt(const Stmt *S) {
>    assert(S && "Null statement?");
> +  PGO.setCurrentStmt(S);
>  
>    // These statements have their own debug info handling.
>    if (EmitSimpleStmt(S))
> @@ -404,14 +405,12 @@ void CodeGenFunction::EmitGotoStmt(const
>      EmitStopPoint(&S);
>  
>    EmitBranchThroughCleanup(getJumpDestForLabel(S.getLabel()));
> -  PGO.setCurrentRegionUnreachable();
>  }
>  
>  
>  void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
>    if (const LabelDecl *Target = S.getConstantTarget()) {
>      EmitBranchThroughCleanup(getJumpDestForLabel(Target));
> -    PGO.setCurrentRegionUnreachable();
>      return;
>    }
>  
> @@ -428,7 +427,6 @@ void CodeGenFunction::EmitIndirectGotoSt
>    cast<llvm::PHINode>(IndGotoBB->begin())->addIncoming(V, CurBB);
>  
>    EmitBranch(IndGotoBB);
> -  PGO.setCurrentRegionUnreachable();
>  }
>  
>  void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
> @@ -480,7 +478,6 @@ void CodeGenFunction::EmitIfStmt(const I
>      RunCleanupsScope ThenScope(*this);
>      EmitStmt(S.getThen());
>    }
> -  Cnt.adjustForControlFlow();
>    EmitBranch(ContBlock);
>  
>    // Emit the 'else' code if present.
> @@ -489,12 +486,10 @@ void CodeGenFunction::EmitIfStmt(const I
>      if (getDebugInfo())
>        Builder.SetCurrentDebugLocation(llvm::DebugLoc());
>      EmitBlock(ElseBlock);
> -    Cnt.beginElseRegion();
>      {
>        RunCleanupsScope ElseScope(*this);
>        EmitStmt(Else);
>      }
> -    Cnt.adjustForControlFlow();
>      // There is no need to emit line number for unconditional branch.
>      if (getDebugInfo())
>        Builder.SetCurrentDebugLocation(llvm::DebugLoc());
> @@ -503,7 +498,6 @@ void CodeGenFunction::EmitIfStmt(const I
>  
>    // Emit the continuation block for code after the if.
>    EmitBlock(ContBlock, true);
> -  Cnt.applyAdjustmentsToRegion();
>  }
>  
>  void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) {
> @@ -519,7 +513,7 @@ void CodeGenFunction::EmitWhileStmt(cons
>    JumpDest LoopExit = getJumpDestInCurrentScope("while.end");
>  
>    // Store the blocks to use for break and continue.
> -  BreakContinueStack.push_back(BreakContinue(LoopExit, LoopHeader, &Cnt));
> +  BreakContinueStack.push_back(BreakContinue(LoopExit, LoopHeader));
>  
>    // C++ [stmt.while]p2:
>    //   When the condition of a while statement is a declaration, the
> @@ -541,7 +535,6 @@ void CodeGenFunction::EmitWhileStmt(cons
>    // while(1) is common, avoid extra exit blocks.  Be sure
>    // to correctly handle break/continue though.
>    bool EmitBoolCondBranch = true;
> -  llvm::BranchInst *CondBr = NULL;
>    if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal))
>      if (C->isOne())
>        EmitBoolCondBranch = false;
> @@ -552,8 +545,8 @@ void CodeGenFunction::EmitWhileStmt(cons
>      llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
>      if (ConditionScope.requiresCleanups())
>        ExitBlock = createBasicBlock("while.exit");
> -
> -    CondBr = Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
> +    Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock,
> +                         PGO.createLoopWeights(S.getCond(), Cnt));
>  
>      if (ExitBlock != LoopExit.getBlock()) {
>        EmitBlock(ExitBlock);
> @@ -569,16 +562,9 @@ void CodeGenFunction::EmitWhileStmt(cons
>      Cnt.beginRegion(Builder);
>      EmitStmt(S.getBody());
>    }
> -  Cnt.adjustForControlFlow();
>  
>    BreakContinueStack.pop_back();
>  
> -  uint64_t LoopCount = Cnt.getCount();
> -  uint64_t ExitCount = Cnt.getLoopExitCount();
> -  if (EmitBoolCondBranch)
> -    CondBr->setMetadata(llvm::LLVMContext::MD_prof,
> -                        PGO.createBranchWeights(LoopCount, ExitCount));
> -
>    // Immediately force cleanup.
>    ConditionScope.ForceCleanup();
>  
> @@ -587,7 +573,6 @@ void CodeGenFunction::EmitWhileStmt(cons
>  
>    // Emit the exit block.
>    EmitBlock(LoopExit.getBlock(), true);
> -  PGO.setCurrentRegionCount(ExitCount + Cnt.getBreakCounter().getCount());
>  
>    // The LoopHeader typically is just a branch if we skipped emitting
>    // a branch, try to erase it.
> @@ -602,17 +587,15 @@ void CodeGenFunction::EmitDoStmt(const D
>    RegionCounter Cnt = getPGORegionCounter(&S);
>  
>    // Store the blocks to use for break and continue.
> -  BreakContinueStack.push_back(BreakContinue(LoopExit, LoopCond, &Cnt));
> +  BreakContinueStack.push_back(BreakContinue(LoopExit, LoopCond));
>  
>    // Emit the body of the loop.
>    llvm::BasicBlock *LoopBody = createBasicBlock("do.body");
> -  EmitBlock(LoopBody);
> -  Cnt.beginRegion(Builder);
> +  EmitBlockWithFallThrough(LoopBody, Cnt);
>    {
>      RunCleanupsScope BodyScope(*this);
>      EmitStmt(S.getBody());
>    }
> -  Cnt.adjustForControlFlow();
>  
>    EmitBlock(LoopCond.getBlock());
>  
> @@ -633,17 +616,13 @@ void CodeGenFunction::EmitDoStmt(const D
>      if (C->isZero())
>        EmitBoolCondBranch = false;
>  
> -  uint64_t LoopCount = Cnt.getCount() - Cnt.getParentCount();
> -  uint64_t ExitCount = Cnt.getLoopExitCount();
> -
>    // As long as the condition is true, iterate the loop.
>    if (EmitBoolCondBranch)
>      Builder.CreateCondBr(BoolCondVal, LoopBody, LoopExit.getBlock(),
> -                         PGO.createBranchWeights(LoopCount, ExitCount));
> +                         PGO.createLoopWeights(S.getCond(), Cnt));
>  
>    // Emit the exit block.
>    EmitBlock(LoopExit.getBlock());
> -  PGO.setCurrentRegionCount(ExitCount + Cnt.getBreakCounter().getCount());
>  
>    // The DoCond block typically is just a branch if we skipped
>    // emitting a branch, try to erase it.
> @@ -652,8 +631,6 @@ void CodeGenFunction::EmitDoStmt(const D
>  }
>  
>  void CodeGenFunction::EmitForStmt(const ForStmt &S) {
> -  RegionCounter Cnt = getPGORegionCounter(&S);
> -
>    JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
>  
>    RunCleanupsScope ForScope(*this);
> @@ -666,6 +643,8 @@ void CodeGenFunction::EmitForStmt(const
>    if (S.getInit())
>      EmitStmt(S.getInit());
>  
> +  RegionCounter Cnt = getPGORegionCounter(&S);
> +
>    // Start the loop with a block that tests the condition.
>    // If there's an increment, the continue scope will be overwritten
>    // later.
> @@ -681,12 +660,11 @@ void CodeGenFunction::EmitForStmt(const
>      Continue = getJumpDestInCurrentScope("for.inc");
>  
>    // Store the blocks to use for break and continue.
> -  BreakContinueStack.push_back(BreakContinue(LoopExit, Continue, &Cnt));
> +  BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
>  
>    // Create a cleanup scope for the condition variable cleanups.
>    RunCleanupsScope ConditionScope(*this);
>  
> -  llvm::BranchInst *CondBr = NULL;
>    if (S.getCond()) {
>      // If the for statement has a condition scope, emit the local variable
>      // declaration.
> @@ -706,7 +684,8 @@ void CodeGenFunction::EmitForStmt(const
>      // C99 6.8.5p2/p4: The first substatement is executed if the expression
>      // compares unequal to 0.  The condition must be a scalar type.
>      llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
> -    CondBr = Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock);
> +    Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock,
> +                         PGO.createLoopWeights(S.getCond(), Cnt));
>  
>      if (ExitBlock != LoopExit.getBlock()) {
>        EmitBlock(ExitBlock);
> @@ -732,16 +711,9 @@ void CodeGenFunction::EmitForStmt(const
>      EmitBlock(Continue.getBlock());
>      EmitStmt(S.getInc());
>    }
> -  Cnt.adjustForControlFlow();
>  
>    BreakContinueStack.pop_back();
>  
> -  uint64_t LoopCount = Cnt.getCount();
> -  uint64_t ExitCount = Cnt.getLoopExitCount();
> -  if (S.getCond())
> -    CondBr->setMetadata(llvm::LLVMContext::MD_prof,
> -                        PGO.createBranchWeights(LoopCount, ExitCount));
> -
>    ConditionScope.ForceCleanup();
>    EmitBranch(CondBlock);
>  
> @@ -752,12 +724,9 @@ void CodeGenFunction::EmitForStmt(const
>  
>    // Emit the fall-through block.
>    EmitBlock(LoopExit.getBlock(), true);
> -  PGO.setCurrentRegionCount(ExitCount + Cnt.getBreakCounter().getCount());
>  }
>  
>  void CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S) {
> -  RegionCounter Cnt = getPGORegionCounter(&S);
> -
>    JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
>  
>    RunCleanupsScope ForScope(*this);
> @@ -770,6 +739,8 @@ void CodeGenFunction::EmitCXXForRangeStm
>    EmitStmt(S.getRangeStmt());
>    EmitStmt(S.getBeginEndStmt());
>  
> +  RegionCounter Cnt = getPGORegionCounter(&S);
> +
>    // Start the loop with a block that tests the condition.
>    // If there's an increment, the continue scope will be overwritten
>    // later.
> @@ -788,8 +759,8 @@ void CodeGenFunction::EmitCXXForRangeStm
>    // The body is executed if the expression, contextually converted
>    // to bool, is true.
>    llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
> -  llvm::BranchInst *CondBr = Builder.CreateCondBr(BoolCondVal,
> -                                                  ForBody, ExitBlock);
> +  Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock,
> +                       PGO.createLoopWeights(S.getCond(), Cnt));
>  
>    if (ExitBlock != LoopExit.getBlock()) {
>      EmitBlock(ExitBlock);
> @@ -803,7 +774,7 @@ void CodeGenFunction::EmitCXXForRangeStm
>    JumpDest Continue = getJumpDestInCurrentScope("for.inc");
>  
>    // Store the blocks to use for break and continue.
> -  BreakContinueStack.push_back(BreakContinue(LoopExit, Continue, &Cnt));
> +  BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
>  
>    {
>      // Create a separate cleanup scope for the loop variable and body.
> @@ -815,15 +786,9 @@ void CodeGenFunction::EmitCXXForRangeStm
>    // If there is an increment, emit it next.
>    EmitBlock(Continue.getBlock());
>    EmitStmt(S.getInc());
> -  Cnt.adjustForControlFlow();
>  
>    BreakContinueStack.pop_back();
>  
> -  uint64_t LoopCount = Cnt.getCount();
> -  uint64_t ExitCount = Cnt.getLoopExitCount();
> -  CondBr->setMetadata(llvm::LLVMContext::MD_prof,
> -                      PGO.createBranchWeights(LoopCount, ExitCount));
> -
>    EmitBranch(CondBlock);
>  
>    ForScope.ForceCleanup();
> @@ -833,7 +798,6 @@ void CodeGenFunction::EmitCXXForRangeStm
>  
>    // Emit the fall-through block.
>    EmitBlock(LoopExit.getBlock(), true);
> -  PGO.setCurrentRegionCount(ExitCount + Cnt.getBreakCounter().getCount());
>  }
>  
>  void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
> @@ -847,7 +811,6 @@ void CodeGenFunction::EmitReturnOfRValue
>                         /*init*/ true);
>    }
>    EmitBranchThroughCleanup(ReturnBlock);
> -  PGO.setCurrentRegionUnreachable();
>  }
>  
>  /// EmitReturnStmt - Note that due to GCC extensions, this can have an operand
> @@ -920,7 +883,6 @@ void CodeGenFunction::EmitReturnStmt(con
>  
>    cleanupScope.ForceCleanup();
>    EmitBranchThroughCleanup(ReturnBlock);
> -  PGO.setCurrentRegionUnreachable();
>  }
>  
>  void CodeGenFunction::EmitDeclStmt(const DeclStmt &S) {
> @@ -943,14 +905,7 @@ void CodeGenFunction::EmitBreakStmt(cons
>    if (HaveInsertPoint())
>      EmitStopPoint(&S);
>  
> -  BreakContinue &BC = BreakContinueStack.back();
> -  // We keep track of breaks from the loop so we can differentiate them from
> -  // non-local exits in PGO instrumentation. This only applies to loops, not
> -  // breaks from switch statements.
> -  if (BC.CountBreak)
> -    BC.LoopCnt->getBreakCounter().beginRegion(Builder);
> -  EmitBranchThroughCleanup(BC.BreakBlock);
> -  PGO.setCurrentRegionUnreachable();
> +  EmitBranchThroughCleanup(BreakContinueStack.back().BreakBlock);
>  }
>  
>  void CodeGenFunction::EmitContinueStmt(const ContinueStmt &S) {
> @@ -962,12 +917,7 @@ void CodeGenFunction::EmitContinueStmt(c
>    if (HaveInsertPoint())
>      EmitStopPoint(&S);
>  
> -  BreakContinue &BC = BreakContinueStack.back();
> -  // We keep track of continues in the loop so we can differentiate them from
> -  // non-local exits in PGO instrumentation.
> -  BC.LoopCnt->getContinueCounter().beginRegion(Builder);
> -  EmitBranchThroughCleanup(BC.ContinueBlock);
> -  PGO.setCurrentRegionUnreachable();
> +  EmitBranchThroughCleanup(BreakContinueStack.back().ContinueBlock);
>  }
>  
>  /// EmitCaseStmtRange - If case statement range is not too big then
> @@ -984,9 +934,8 @@ void CodeGenFunction::EmitCaseStmtRange(
>    // Emit the code for this case. We do this first to make sure it is
>    // properly chained from our predecessor before generating the
>    // switch machinery to enter this block.
> -  EmitBlock(createBasicBlock("sw.bb"));
> -  llvm::BasicBlock *CaseDest = Builder.GetInsertBlock();
> -  CaseCnt.beginRegion(Builder);
> +  llvm::BasicBlock *CaseDest = createBasicBlock("sw.bb");
> +  EmitBlockWithFallThrough(CaseDest, CaseCnt);
>    EmitStmt(S.getSubStmt());
>  
>    // If range is empty, do nothing.
> @@ -997,7 +946,7 @@ void CodeGenFunction::EmitCaseStmtRange(
>    // FIXME: parameters such as this should not be hardcoded.
>    if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) {
>      // Range is small enough to add multiple switch instruction cases.
> -    uint64_t Total = CaseCnt.getCount() - CaseCnt.getParentCount();
> +    uint64_t Total = CaseCnt.getCount();
>      unsigned NCases = Range.getZExtValue() + 1;
>      // We only have one region counter for the entire set of cases here, so we
>      // need to divide the weights evenly between the generated cases, ensuring
> @@ -1036,7 +985,7 @@ void CodeGenFunction::EmitCaseStmtRange(
>  
>    llvm::MDNode *Weights = 0;
>    if (SwitchWeights) {
> -    uint64_t ThisCount = CaseCnt.getCount() - CaseCnt.getParentCount();
> +    uint64_t ThisCount = CaseCnt.getCount();
>      uint64_t DefaultCount = (*SwitchWeights)[0];
>      Weights = PGO.createBranchWeights(ThisCount, DefaultCount);
>  
> @@ -1086,7 +1035,7 @@ void CodeGenFunction::EmitCaseStmt(const
>      // Only do this optimization if there are no cleanups that need emitting.
>      if (isObviouslyBranchWithoutCleanups(Block)) {
>        if (SwitchWeights)
> -        SwitchWeights->push_back(CaseCnt.getCount() - CaseCnt.getParentCount());
> +        SwitchWeights->push_back(CaseCnt.getCount());
>        SwitchInsn->addCase(CaseVal, Block.getBlock());
>  
>        // If there was a fallthrough into this case, make sure to redirect it to
> @@ -1099,11 +1048,10 @@ void CodeGenFunction::EmitCaseStmt(const
>      }
>    }
>  
> -  EmitBlock(createBasicBlock("sw.bb"));
> -  llvm::BasicBlock *CaseDest = Builder.GetInsertBlock();
> +  llvm::BasicBlock *CaseDest = createBasicBlock("sw.bb");
> +  EmitBlockWithFallThrough(CaseDest, CaseCnt);
>    if (SwitchWeights)
> -    SwitchWeights->push_back(CaseCnt.getCount() - CaseCnt.getParentCount());
> -  CaseCnt.beginRegion(Builder);
> +    SwitchWeights->push_back(CaseCnt.getCount());
>    SwitchInsn->addCase(CaseVal, CaseDest);
>  
>    // Recursively emitting the statement is acceptable, but is not wonderful for
> @@ -1126,8 +1074,11 @@ void CodeGenFunction::EmitCaseStmt(const
>  
>      CaseCnt = getPGORegionCounter(NextCase);
>      if (SwitchWeights)
> -      SwitchWeights->push_back(CaseCnt.getCount() - CaseCnt.getParentCount());
> -    CaseCnt.beginRegion(Builder);
> +      SwitchWeights->push_back(CaseCnt.getCount());
> +    if (CGM.getCodeGenOpts().ProfileInstrGenerate) {
> +      CaseDest = createBasicBlock("sw.bb");
> +      EmitBlockWithFallThrough(CaseDest, CaseCnt);
> +    }
>  
>      SwitchInsn->addCase(CaseVal, CaseDest);
>      NextCase = dyn_cast<CaseStmt>(CurCase->getSubStmt());
> @@ -1142,21 +1093,9 @@ void CodeGenFunction::EmitDefaultStmt(co
>    assert(DefaultBlock->empty() &&
>           "EmitDefaultStmt: Default block already defined?");
>  
> -  llvm::BasicBlock *SkipCountBB = 0;
> -  if (CGM.getCodeGenOpts().ProfileInstrGenerate) {
> -    // The PGO region here needs to count the number of times the edge occurs,
> -    // so fallthrough into this case will jump past the region counter to the
> -    // skipcount basic block.
> -    SkipCountBB = createBasicBlock("skipcount");
> -    EmitBranch(SkipCountBB);
> -  }
> -  EmitBlock(DefaultBlock);
> -
>    RegionCounter Cnt = getPGORegionCounter(&S);
> -  Cnt.beginRegion(Builder, /*AddIncomingFallThrough=*/true);
> +  EmitBlockWithFallThrough(DefaultBlock, Cnt);
>  
> -  if (SkipCountBB)
> -    EmitBlock(SkipCountBB);
>    EmitStmt(S.getSubStmt());
>  }
>  
> @@ -1439,20 +1378,14 @@ void CodeGenFunction::EmitSwitchStmt(con
>  
>    // Clear the insertion point to indicate we are in unreachable code.
>    Builder.ClearInsertionPoint();
> -  PGO.setCurrentRegionUnreachable();
>  
>    // All break statements jump to NextBlock. If BreakContinueStack is non-empty
> -  // then reuse last ContinueBlock and that block's counter.
> +  // then reuse last ContinueBlock.
>    JumpDest OuterContinue;
> -  RegionCounter *OuterCount = 0;
> -  if (!BreakContinueStack.empty()) {
> -    BreakContinue &BC = BreakContinueStack.back();
> -    OuterContinue = BC.ContinueBlock;
> -    OuterCount = BC.LoopCnt;
> -  }
> +  if (!BreakContinueStack.empty())
> +    OuterContinue = BreakContinueStack.back().ContinueBlock;
>  
> -  BreakContinueStack.push_back(BreakContinue(SwitchExit, OuterContinue,
> -                                             OuterCount, /*CountBreak=*/false));
> +  BreakContinueStack.push_back(BreakContinue(SwitchExit, OuterContinue));
>  
>    // Emit switch body.
>    EmitStmt(S.getBody());
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=201528&r1=201527&r2=201528&view=diff==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Mon Feb 17 13:21:09 2014

I think EmitFunctionBody needs to do PGO.setCurrentStmt(Body) as well.

> @@ -688,6 +688,26 @@ void CodeGenFunction::EmitFunctionBody(F
>      EmitStmt(Body);
>  }
>  
> +/// When instrumenting to collect profile data, the counts for some blocks
> +/// such as switch cases need to not include the fall-through counts, so
> +/// emit a branch around the instrumentation code. When not instrumenting,
> +/// this just calls EmitBlock().
> +void CodeGenFunction::EmitBlockWithFallThrough(llvm::BasicBlock *BB,
> +                                               RegionCounter &Cnt) {
> +  llvm::BasicBlock *SkipCountBB = 0;
> +  if (HaveInsertPoint() && CGM.getCodeGenOpts().ProfileInstrGenerate) {
> +    // When instrumenting for profiling, the fallthrough to certain
> +    // statements needs to skip over the instrumentation code so that we
> +    // get an accurate count.
> +    SkipCountBB = createBasicBlock("skipcount");
> +    EmitBranch(SkipCountBB);
> +  }
> +  EmitBlock(BB);
> +  Cnt.beginRegion(Builder, /*AddIncomingFallThrough=*/true);
> +  if (SkipCountBB)
> +    EmitBlock(SkipCountBB);
> +}

My first thought when seeing this here was that this belongs in
CodeGenPGO, rather than CodeGenFunction, based on the similarity to
emitCounterIncrement. Thinking about it though, I think it actually
makes more sense to move CodeGenPGO::emitCounterIncrement to
CodeGenFunction::incrementPGOCounter.

It would also make sense to change the signature to take a Stmt* instead
of a counter, and then just expose a method to get the address of the
region counter for that statement. Of course, this only makes sense if
we change beginRegion as I suggest below, so that PGO doesn't need to
increment counters itself.

>  /// Tries to mark the given function nounwind based on the
>  /// non-existence of any throwing calls within it.  We believe this is
>  /// lightweight enough to do at -O0.
> @@ -917,10 +937,11 @@ void CodeGenFunction::EmitBranchOnBoolEx
>    Cond = Cond->IgnoreParens();
>  
>    if (const BinaryOperator *CondBOp = dyn_cast<BinaryOperator>(Cond)) {
> -    RegionCounter Cnt = getPGORegionCounter(CondBOp);
>  
>      // Handle X && Y in a condition.
>      if (CondBOp->getOpcode() == BO_LAnd) {
> +      RegionCounter Cnt = getPGORegionCounter(CondBOp);
> +
>        // If we have "1 && X", simplify the code.  "0 && X" would have constant
>        // folded if the case was simple enough.
>        bool ConstantBool = false;
> @@ -957,13 +978,13 @@ void CodeGenFunction::EmitBranchOnBoolEx
>        eval.begin(*this);
>        EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, TrueCount);
>        eval.end(*this);
> -      Cnt.adjustForControlFlow();
> -      Cnt.applyAdjustmentsToRegion();
>  
>        return;
>      }
>  
>      if (CondBOp->getOpcode() == BO_LOr) {
> +      RegionCounter Cnt = getPGORegionCounter(CondBOp);
> +
>        // If we have "0 || X", simplify the code.  "1 || X" would have constant
>        // folded if the case was simple enough.
>        bool ConstantBool = false;
> @@ -1003,8 +1024,6 @@ void CodeGenFunction::EmitBranchOnBoolEx
>        EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, RHSCount);
>  
>        eval.end(*this);
> -      Cnt.adjustForControlFlow();
> -      Cnt.applyAdjustmentsToRegion();
>  
>        return;
>      }
> @@ -1037,7 +1056,7 @@ void CodeGenFunction::EmitBranchOnBoolEx
>      // the conditional operator.
>      uint64_t LHSScaledTrueCount = 0;
>      if (TrueCount) {
> -      double LHSRatio = Cnt.getCount() / (double) PGO.getCurrentRegionCount();
> +      double LHSRatio = Cnt.getCount() / (double) Cnt.getParentCount();
>        LHSScaledTrueCount = TrueCount * LHSRatio;
>      }
>  
> @@ -1050,7 +1069,6 @@ void CodeGenFunction::EmitBranchOnBoolEx
>  
>      cond.begin(*this);
>      EmitBlock(RHSBlock);
> -    Cnt.beginElseRegion();
>      EmitBranchOnBoolExpr(CondOp->getRHS(), TrueBlock, FalseBlock,
>                           TrueCount - LHSScaledTrueCount);
>      cond.end(*this);
> @@ -1070,7 +1088,7 @@ void CodeGenFunction::EmitBranchOnBoolEx
>  
>    // Create branch weights based on the number of times we get here and the
>    // number of times the condition should be true.
> -  uint64_t CurrentCount = PGO.getCurrentRegionCountWithMin(TrueCount);
> +  uint64_t CurrentCount = std::max(PGO.getCurrentRegionCount(), TrueCount);
>    llvm::MDNode *Weights = PGO.createBranchWeights(TrueCount,
>                                                    CurrentCount - TrueCount);
>  
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=201528&r1=201527&r2=201528&view=diff==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Mon Feb 17 13:21:09 2014
> @@ -818,18 +818,13 @@ private:
>    llvm::DenseMap<const LabelDecl*, JumpDest> LabelMap;
>  
>    // BreakContinueStack - This keeps track of where break and continue
> -  // statements should jump to and the associated base counter for
> -  // instrumentation.
> +  // statements should jump to.
>    struct BreakContinue {
> -    BreakContinue(JumpDest Break, JumpDest Continue, RegionCounter *LoopCnt,
> -                  bool CountBreak = true)
> -      : BreakBlock(Break), ContinueBlock(Continue), LoopCnt(LoopCnt),
> -        CountBreak(CountBreak) {}
> +    BreakContinue(JumpDest Break, JumpDest Continue)
> +      : BreakBlock(Break), ContinueBlock(Continue) {}
>  
>      JumpDest BreakBlock;
>      JumpDest ContinueBlock;
> -    RegionCounter *LoopCnt;
> -    bool CountBreak;
>    };
>    SmallVector<BreakContinue, 8> BreakContinueStack;
>  
> @@ -1156,6 +1151,7 @@ public:
>    void EmitDestructorBody(FunctionArgList &Args);
>    void emitImplicitAssignmentOperatorBody(FunctionArgList &Args);
>    void EmitFunctionBody(FunctionArgList &Args, const Stmt *Body);
> +  void EmitBlockWithFallThrough(llvm::BasicBlock *BB, RegionCounter &Cnt);
>  
>    void EmitForwardingCallToLambda(const CXXMethodDecl *LambdaCallOperator,
>                                    CallArgList &CallArgs);
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenPGO.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenPGO.cpp?rev=201528&r1=201527&r2=201528&view=diff==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenPGO.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenPGO.cpp Mon Feb 17 13:21:09 2014
> @@ -284,56 +284,43 @@ namespace {
>        (*CounterMap)[S] = NextCounter++;
>        Visit(S->getSubStmt());
>      }
> -    /// Assign three counters - one for the body of the loop, one for breaks
> -    /// from the loop, and one for continues.
> -    ///
> -    /// The break and continue counters cover all such statements in this loop,
> -    /// and are used in calculations to find the number of times the condition
> -    /// and exit of the loop occur. They are needed so we can differentiate
> -    /// these statements from non-local exits like return and goto.
> +    /// Assign a counter for the body of a while loop.
>      void VisitWhileStmt(const WhileStmt *S) {
> -      (*CounterMap)[S] = NextCounter;
> -      NextCounter += 3;
> +      (*CounterMap)[S] = NextCounter++;
>        Visit(S->getCond());
>        Visit(S->getBody());
>      }
> -    /// Assign counters for the body of the loop, and for breaks and
> -    /// continues. See VisitWhileStmt.
> +    /// Assign a counter for the body of a do-while loop.
>      void VisitDoStmt(const DoStmt *S) {
> -      (*CounterMap)[S] = NextCounter;
> -      NextCounter += 3;
> +      (*CounterMap)[S] = NextCounter++;
>        Visit(S->getBody());
>        Visit(S->getCond());
>      }
> -    /// Assign counters for the body of the loop, and for breaks and
> -    /// continues. See VisitWhileStmt.
> +    /// Assign a counter for the body of a for loop.
>      void VisitForStmt(const ForStmt *S) {
> -      (*CounterMap)[S] = NextCounter;
> -      NextCounter += 3;
> +      (*CounterMap)[S] = NextCounter++;
> +      if (S->getInit())
> +        Visit(S->getInit());
>        const Expr *E;
>        if ((E = S->getCond()))
>          Visit(E);
> -      Visit(S->getBody());
>        if ((E = S->getInc()))
>          Visit(E);
> +      Visit(S->getBody());
>      }
> -    /// Assign counters for the body of the loop, and for breaks and
> -    /// continues. See VisitWhileStmt.
> +    /// Assign a counter for the body of a for-range loop.
>      void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
> -      (*CounterMap)[S] = NextCounter;
> -      NextCounter += 3;
> -      const Expr *E;
> -      if ((E = S->getCond()))
> -        Visit(E);
> +      (*CounterMap)[S] = NextCounter++;
> +      Visit(S->getRangeStmt());
> +      Visit(S->getBeginEndStmt());
> +      Visit(S->getCond());
> +      Visit(S->getLoopVarStmt());
>        Visit(S->getBody());
> -      if ((E = S->getInc()))
> -        Visit(E);
> +      Visit(S->getInc());
>      }
> -    /// Assign counters for the body of the loop, and for breaks and
> -    /// continues. See VisitWhileStmt.
> +    /// Assign a counter for the body of a for-collection loop.
>      void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
> -      (*CounterMap)[S] = NextCounter;
> -      NextCounter += 3;
> +      (*CounterMap)[S] = NextCounter++;
>        Visit(S->getElement());
>        Visit(S->getBody());
>      }
> @@ -402,6 +389,343 @@ namespace {
>        Visit(E->getRHS());
>      }
>    };
> +
> +  /// A StmtVisitor that propagates the raw counts through the AST and
> +  /// records the count at statements where the value may change.
> +  struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
> +    /// PGO state.
> +    CodeGenPGO &PGO;
> +
> +    /// A flag that is set when the current count should be recorded on the
> +    /// next statement, such as at the exit of a loop.
> +    bool RecordNextStmtCount;
> +
> +    /// The map of statements to count values.
> +    llvm::DenseMap<const Stmt*, uint64_t> *CountMap;
> +
> +    /// BreakContinueStack - Keep counts of breaks and continues inside loops. 
> +    struct BreakContinue {
> +      uint64_t BreakCount;
> +      uint64_t ContinueCount;
> +      BreakContinue() : BreakCount(0), ContinueCount(0) {}
> +    };
> +    SmallVector<BreakContinue, 8> BreakContinueStack;
> +
> +    ComputeRegionCounts(llvm::DenseMap<const Stmt*, uint64_t> *CountMap,
> +                        CodeGenPGO &PGO) :
> +      PGO(PGO), RecordNextStmtCount(false), CountMap(CountMap) {
> +    }
> +
> +    void RecordStmtCount(const Stmt *S) {
> +      if (RecordNextStmtCount) {
> +        (*CountMap)[S] = PGO.getCurrentRegionCount();
> +        RecordNextStmtCount = false;
> +      }
> +    }
> +
> +    void VisitStmt(const Stmt *S) {
> +      RecordStmtCount(S);
> +      for (Stmt::const_child_range I = S->children(); I; ++I) {
> +        if (*I)
> +         this->Visit(*I);
> +      }
> +    }
> +
> +    void VisitFunctionDecl(const FunctionDecl *S) {
> +      RegionCounter Cnt(PGO, S->getBody());
> +      Cnt.beginRegion();
> +      (*CountMap)[S->getBody()] = PGO.getCurrentRegionCount();
> +      Visit(S->getBody());
> +    }
> +
> +    void VisitReturnStmt(const ReturnStmt *S) {
> +      RecordStmtCount(S);
> +      if (S->getRetValue())
> +        Visit(S->getRetValue());
> +      PGO.setCurrentRegionUnreachable();
> +      RecordNextStmtCount = true;
> +    }
> +
> +    void VisitGotoStmt(const GotoStmt *S) {
> +      RecordStmtCount(S);
> +      PGO.setCurrentRegionUnreachable();
> +      RecordNextStmtCount = true;
> +    }
> +
> +    void VisitLabelStmt(const LabelStmt *S) {
> +      RecordNextStmtCount = false;
> +      RegionCounter Cnt(PGO, S);
> +      Cnt.beginRegion();
> +      (*CountMap)[S] = PGO.getCurrentRegionCount();
> +      Visit(S->getSubStmt());
> +    }
> +
> +    void VisitBreakStmt(const BreakStmt *S) {
> +      RecordStmtCount(S);
> +      assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
> +      BreakContinueStack.back().BreakCount += PGO.getCurrentRegionCount();
> +      PGO.setCurrentRegionUnreachable();
> +      RecordNextStmtCount = true;
> +    }
> +
> +    void VisitContinueStmt(const ContinueStmt *S) {
> +      RecordStmtCount(S);
> +      assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
> +      BreakContinueStack.back().ContinueCount += PGO.getCurrentRegionCount();
> +      PGO.setCurrentRegionUnreachable();
> +      RecordNextStmtCount = true;
> +    }
> +
> +    void VisitWhileStmt(const WhileStmt *S) {
> +      RecordStmtCount(S);
> +      RegionCounter Cnt(PGO, S);
> +      BreakContinueStack.push_back(BreakContinue());
> +      // Visit the body region first so the break/continue adjustments can be
> +      // included when visiting the condition.
> +      Cnt.beginRegion();
> +      (*CountMap)[S->getBody()] = PGO.getCurrentRegionCount();
> +      Visit(S->getBody());
> +      Cnt.adjustForControlFlow();
> +
> +      // ...then go back and propagate counts through the condition. The count
> +      // at the start of the condition is the sum of the incoming edges,
> +      // the backedge from the end of the loop body, and the edges from
> +      // continue statements.
> +      BreakContinue BC = BreakContinueStack.pop_back_val();
> +      Cnt.setCurrentRegionCount(Cnt.getParentCount() +
> +                                Cnt.getAdjustedCount() + BC.ContinueCount);
> +      (*CountMap)[S->getCond()] = PGO.getCurrentRegionCount();
> +      Visit(S->getCond());
> +      Cnt.adjustForControlFlow();
> +      Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
> +      RecordNextStmtCount = true;
> +    }
> +
> +    void VisitDoStmt(const DoStmt *S) {
> +      RecordStmtCount(S);
> +      RegionCounter Cnt(PGO, S);
> +      BreakContinueStack.push_back(BreakContinue());
> +      Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
> +      (*CountMap)[S->getBody()] = PGO.getCurrentRegionCount();
> +      Visit(S->getBody());
> +      Cnt.adjustForControlFlow();
> +
> +      BreakContinue BC = BreakContinueStack.pop_back_val();
> +      // The count at the start of the condition is equal to the count at the
> +      // end of the body. The adjusted count does not include either the
> +      // fall-through count coming into the loop or the continue count, so add
> +      // both of those separately. This is coincidentally the same equation as
> +      // with while loops but for different reasons.
> +      Cnt.setCurrentRegionCount(Cnt.getParentCount() +
> +                                Cnt.getAdjustedCount() + BC.ContinueCount);
> +      (*CountMap)[S->getCond()] = PGO.getCurrentRegionCount();
> +      Visit(S->getCond());
> +      Cnt.adjustForControlFlow();
> +      Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
> +      RecordNextStmtCount = true;
> +    }
> +
> +    void VisitForStmt(const ForStmt *S) {
> +      RecordStmtCount(S);
> +      if (S->getInit())
> +        Visit(S->getInit());
> +      RegionCounter Cnt(PGO, S);
> +      BreakContinueStack.push_back(BreakContinue());
> +      // Visit the body region first. (This is basically the same as a while
> +      // loop; see further comments in VisitWhileStmt.)
> +      Cnt.beginRegion();
> +      (*CountMap)[S->getBody()] = PGO.getCurrentRegionCount();
> +      Visit(S->getBody());
> +      Cnt.adjustForControlFlow();
> +
> +      // The increment is essentially part of the body but it needs to include
> +      // the count for all the continue statements.
> +      if (S->getInc()) {
> +        Cnt.setCurrentRegionCount(PGO.getCurrentRegionCount() +
> +                                  BreakContinueStack.back().ContinueCount);
> +        (*CountMap)[S->getInc()] = PGO.getCurrentRegionCount();
> +        Visit(S->getInc());
> +        Cnt.adjustForControlFlow();
> +      }
> +
> +      BreakContinue BC = BreakContinueStack.pop_back_val();
> +
> +      // ...then go back and propagate counts through the condition.
> +      if (S->getCond()) {
> +        Cnt.setCurrentRegionCount(Cnt.getParentCount() +
> +                                  Cnt.getAdjustedCount() +
> +                                  BC.ContinueCount);
> +        (*CountMap)[S->getCond()] = PGO.getCurrentRegionCount();
> +        Visit(S->getCond());
> +        Cnt.adjustForControlFlow();
> +      }
> +      Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
> +      RecordNextStmtCount = true;
> +    }
> +
> +    void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
> +      RecordStmtCount(S);
> +      Visit(S->getRangeStmt());
> +      Visit(S->getBeginEndStmt());
> +      RegionCounter Cnt(PGO, S);
> +      BreakContinueStack.push_back(BreakContinue());
> +      // Visit the body region first. (This is basically the same as a while
> +      // loop; see further comments in VisitWhileStmt.)
> +      Cnt.beginRegion();
> +      (*CountMap)[S->getLoopVarStmt()] = PGO.getCurrentRegionCount();
> +      Visit(S->getLoopVarStmt());
> +      Visit(S->getBody());
> +      Cnt.adjustForControlFlow();
> +
> +      // The increment is essentially part of the body but it needs to include
> +      // the count for all the continue statements.
> +      Cnt.setCurrentRegionCount(PGO.getCurrentRegionCount() +
> +                                BreakContinueStack.back().ContinueCount);
> +      (*CountMap)[S->getInc()] = PGO.getCurrentRegionCount();
> +      Visit(S->getInc());
> +      Cnt.adjustForControlFlow();
> +
> +      BreakContinue BC = BreakContinueStack.pop_back_val();
> +
> +      // ...then go back and propagate counts through the condition.
> +      Cnt.setCurrentRegionCount(Cnt.getParentCount() +
> +                                Cnt.getAdjustedCount() +
> +                                BC.ContinueCount);
> +      (*CountMap)[S->getCond()] = PGO.getCurrentRegionCount();
> +      Visit(S->getCond());
> +      Cnt.adjustForControlFlow();
> +      Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
> +      RecordNextStmtCount = true;
> +    }
> +
> +    void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
> +      RecordStmtCount(S);
> +      Visit(S->getElement());
> +      RegionCounter Cnt(PGO, S);
> +      BreakContinueStack.push_back(BreakContinue());
> +      Cnt.beginRegion();
> +      (*CountMap)[S->getBody()] = PGO.getCurrentRegionCount();
> +      Visit(S->getBody());
> +      BreakContinue BC = BreakContinueStack.pop_back_val();
> +      Cnt.adjustForControlFlow();
> +      Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
> +      RecordNextStmtCount = true;
> +    }
> +
> +    void VisitSwitchStmt(const SwitchStmt *S) {
> +      RecordStmtCount(S);
> +      Visit(S->getCond());
> +      PGO.setCurrentRegionUnreachable();
> +      BreakContinueStack.push_back(BreakContinue());
> +      Visit(S->getBody());
> +      // If the switch is inside a loop, add the continue counts.
> +      BreakContinue BC = BreakContinueStack.pop_back_val();
> +      if (!BreakContinueStack.empty())
> +        BreakContinueStack.back().ContinueCount += BC.ContinueCount;

This comment is a bit confusing. Add the continue counts to what? I
guess you're trying to say something like "continues obviously don't
apply to the switch statement, so propagate their counts down the stack
in case they find a loop there", but maybe you can wordsmith that a
little better than I did.

> +      RegionCounter ExitCnt(PGO, S);
> +      ExitCnt.beginRegion();
> +      RecordNextStmtCount = true;
> +    }
> +
> +    void VisitCaseStmt(const CaseStmt *S) {
> +      RecordNextStmtCount = false;
> +      RegionCounter Cnt(PGO, S);
> +      Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
> +      (*CountMap)[S] = Cnt.getCount();
> +      RecordNextStmtCount = true;
> +      Visit(S->getSubStmt());
> +    }
> +
> +    void VisitDefaultStmt(const DefaultStmt *S) {
> +      RecordNextStmtCount = false;
> +      RegionCounter Cnt(PGO, S);
> +      Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
> +      (*CountMap)[S] = Cnt.getCount();
> +      RecordNextStmtCount = true;
> +      Visit(S->getSubStmt());
> +    }
> +
> +    void VisitIfStmt(const IfStmt *S) {
> +      RecordStmtCount(S);
> +      RegionCounter Cnt(PGO, S);
> +      Visit(S->getCond());
> +
> +      Cnt.beginRegion();
> +      (*CountMap)[S->getThen()] = PGO.getCurrentRegionCount();
> +      Visit(S->getThen());
> +      Cnt.adjustForControlFlow();
> +
> +      if (S->getElse()) {
> +        Cnt.beginElseRegion();
> +        (*CountMap)[S->getElse()] = PGO.getCurrentRegionCount();
> +        Visit(S->getElse());
> +        Cnt.adjustForControlFlow();
> +      }
> +      Cnt.applyAdjustmentsToRegion(0);
> +      RecordNextStmtCount = true;
> +    }
> +
> +    void VisitCXXTryStmt(const CXXTryStmt *S) {
> +      RecordStmtCount(S);
> +      Visit(S->getTryBlock());
> +      for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
> +        Visit(S->getHandler(I));
> +      RegionCounter Cnt(PGO, S);
> +      Cnt.beginRegion();
> +      RecordNextStmtCount = true;
> +    }
> +
> +    void VisitCXXCatchStmt(const CXXCatchStmt *S) {
> +      RecordNextStmtCount = false;
> +      RegionCounter Cnt(PGO, S);
> +      Cnt.beginRegion();
> +      (*CountMap)[S] = PGO.getCurrentRegionCount();
> +      Visit(S->getHandlerBlock());
> +    }
> +
> +    void VisitConditionalOperator(const ConditionalOperator *E) {
> +      RecordStmtCount(E);
> +      RegionCounter Cnt(PGO, E);
> +      Visit(E->getCond());
> +
> +      Cnt.beginRegion();
> +      (*CountMap)[E->getTrueExpr()] = PGO.getCurrentRegionCount();
> +      Visit(E->getTrueExpr());
> +      Cnt.adjustForControlFlow();
> +
> +      Cnt.beginElseRegion();
> +      (*CountMap)[E->getFalseExpr()] = PGO.getCurrentRegionCount();
> +      Visit(E->getFalseExpr());
> +      Cnt.adjustForControlFlow();
> +
> +      Cnt.applyAdjustmentsToRegion(0);
> +      RecordNextStmtCount = true;
> +    }
> +
> +    void VisitBinLAnd(const BinaryOperator *E) {
> +      RecordStmtCount(E);
> +      RegionCounter Cnt(PGO, E);
> +      Visit(E->getLHS());
> +      Cnt.beginRegion();
> +      (*CountMap)[E->getRHS()] = PGO.getCurrentRegionCount();
> +      Visit(E->getRHS());
> +      Cnt.adjustForControlFlow();
> +      Cnt.applyAdjustmentsToRegion(0);
> +      RecordNextStmtCount = true;
> +    }
> +
> +    void VisitBinLOr(const BinaryOperator *E) {
> +      RecordStmtCount(E);
> +      RegionCounter Cnt(PGO, E);
> +      Visit(E->getLHS());
> +      Cnt.beginRegion();
> +      (*CountMap)[E->getRHS()] = PGO.getCurrentRegionCount();
> +      Visit(E->getRHS());
> +      Cnt.adjustForControlFlow();
> +      Cnt.applyAdjustmentsToRegion(0);
> +      RecordNextStmtCount = true;
> +    }
> +  };
>  }
>  
>  void CodeGenPGO::assignRegionCounters(GlobalDecl &GD) {
> @@ -415,8 +739,10 @@ void CodeGenPGO::assignRegionCounters(Gl
>    mapRegionCounters(D);
>    if (InstrumentRegions)
>      emitCounterVariables();
> -  if (PGOData)
> +  if (PGOData) {
>      loadRegionCounts(GD, PGOData);
> +    computeRegionCounts(D);
> +  }
>  }
>  
>  void CodeGenPGO::mapRegionCounters(const Decl *D) {
> @@ -427,6 +753,13 @@ void CodeGenPGO::mapRegionCounters(const
>    NumRegionCounters = Walker.NextCounter;
>  }
>  
> +void CodeGenPGO::computeRegionCounts(const Decl *D) {
> +  StmtCountMap = new llvm::DenseMap<const Stmt*, uint64_t>();
> +  ComputeRegionCounts Walker(StmtCountMap, *this);
> +  if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
> +    Walker.VisitFunctionDecl(FD);
> +}
> +
>  void CodeGenPGO::emitCounterVariables() {
>    llvm::LLVMContext &Ctx = CGM.getLLVMContext();
>    llvm::ArrayType *CounterTy = llvm::ArrayType::get(llvm::Type::getInt64Ty(Ctx),
> @@ -464,6 +797,8 @@ void CodeGenPGO::loadRegionCounts(Global
>  void CodeGenPGO::destroyRegionCounters() {
>    if (RegionCounterMap != 0)
>      delete RegionCounterMap;
> +  if (StmtCountMap != 0)
> +    delete StmtCountMap;
>    if (RegionCounts != 0)
>      delete RegionCounts;
>  }
> @@ -493,3 +828,18 @@ llvm::MDNode *CodeGenPGO::createBranchWe
>    }
>    return MDHelper.createBranchWeights(ScaledWeights);
>  }
> +
> +llvm::MDNode *CodeGenPGO::createLoopWeights(const Stmt *Cond,
> +                                            RegionCounter &Cnt) {
> +  if (!haveRegionCounts())
> +    return 0;
> +  uint64_t LoopCount = Cnt.getCount();
> +  uint64_t CondCount = 0;
> +  bool Found = getStmtCount(Cond, CondCount);
> +  assert(Found && "missing expected loop condition count");
> +  (void)Found;
> +  if (CondCount == 0)
> +    return 0;
> +  return createBranchWeights(LoopCount,
> +                             std::max(CondCount, LoopCount) - LoopCount);
> +}
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenPGO.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenPGO.h?rev=201528&r1=201527&r2=201528&view=diff==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenPGO.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenPGO.h Mon Feb 17 13:21:09 2014
> @@ -60,13 +60,14 @@ private:
>    unsigned NumRegionCounters;
>    llvm::GlobalVariable *RegionCounters;
>    llvm::DenseMap<const Stmt*, unsigned> *RegionCounterMap;
> +  llvm::DenseMap<const Stmt*, uint64_t> *StmtCountMap;
>    std::vector<uint64_t> *RegionCounts;
>    uint64_t CurrentRegionCount;
>  
>  public:
>    CodeGenPGO(CodeGenModule &CGM)
>      : CGM(CGM), NumRegionCounters(0), RegionCounters(0), RegionCounterMap(0),
> -      RegionCounts(0), CurrentRegionCount(0) {}
> +      StmtCountMap(0), RegionCounts(0), CurrentRegionCount(0) {}
>    ~CodeGenPGO() {}
>  
>    /// Whether or not we have PGO region data for the current function. This is
> @@ -76,22 +77,42 @@ public:
>  
>    /// Return the counter value of the current region.
>    uint64_t getCurrentRegionCount() const { return CurrentRegionCount; }
> -  /// Return the counter value of the current region, or \p Min if it is larger.
> -  uint64_t getCurrentRegionCountWithMin(uint64_t Min) {
> -    return std::max(Min, CurrentRegionCount);
> -  }
> +
>    /// Set the counter value for the current region. This is used to keep track
>    /// of changes to the most recent counter from control flow and non-local
>    /// exits.
>    void setCurrentRegionCount(uint64_t Count) { CurrentRegionCount = Count; }
> +
>    /// Indicate that the current region is never reached, and thus should have a
>    /// counter value of zero. This is important so that subsequent regions can
>    /// correctly track their parent counts.
>    void setCurrentRegionUnreachable() { setCurrentRegionCount(0); }
>  
> +  /// Check if an execution count is known for a given statement. If so, return
> +  /// true and put the value in Count; else return false.
> +  bool getStmtCount(const Stmt *S, uint64_t &Count) {
> +    if (!StmtCountMap)
> +      return false;
> +    llvm::DenseMap<const Stmt*, uint64_t>::const_iterator
> +      I = StmtCountMap->find(S);
> +    if (I == StmtCountMap->end())
> +      return false;
> +    Count = I->second;
> +    return true;
> +  }
> +
> +  /// If the execution count for the current statement is known, record that
> +  /// as the current count.
> +  void setCurrentStmt(const Stmt *S) {
> +    uint64_t Count;
> +    if (getStmtCount(S, Count))
> +      setCurrentRegionCount(Count);
> +  }
> +
>    /// Calculate branch weights appropriate for PGO data
>    llvm::MDNode *createBranchWeights(uint64_t TrueCount, uint64_t FalseCount);
>    llvm::MDNode *createBranchWeights(ArrayRef<uint64_t> Weights);
> +  llvm::MDNode *createLoopWeights(const Stmt *Cond, RegionCounter &Cnt);
>  
>    /// Assign counters to regions and configure them for PGO of a given
>    /// function. Does nothing if instrumentation is not enabled and either
> @@ -109,6 +130,7 @@ public:
>  
>  private:
>    void mapRegionCounters(const Decl *D);
> +  void computeRegionCounts(const Decl *D);
>    void loadRegionCounts(GlobalDecl &GD, PGOProfileData *PGOData);
>    void emitCounterVariables();
>  
> @@ -157,6 +179,7 @@ public:
>    /// the region of the counter was entered, but for switch labels it's the
>    /// number of direct jumps to that label.
>    uint64_t getCount() const { return Count; }
> +
>    /// Get the value of the counter with adjustments applied. Adjustments occur
>    /// when control enters or leaves the region abnormally; i.e., if there is a
>    /// jump to a label within the region, or if the function can return from
> @@ -166,43 +189,27 @@ public:
>      assert((Adjust > 0 || (uint64_t)(-Adjust) <= Count) && "Negative count");
>      return Count + Adjust;
>    }
> +
>    /// Get the value of the counter in this region's parent, i.e., the region
>    /// that was active when this region began. This is useful for deriving
>    /// counts in implicitly counted regions, like the false case of a condition
>    /// or the normal exits of a loop.
>    uint64_t getParentCount() const { return ParentCount; }
>  
> -  /// Get the number of times the condition of a loop will evaluate false. This
> -  /// is the number of times we enter the loop, adjusted by the difference
> -  /// between entering and exiting the loop body normally, excepting that
> -  /// 'continue' statements also bring us back here.
> -  ///
> -  /// Undefined if this counter is not counting a loop.
> -  uint64_t getLoopExitCount() const {
> -    return getParentCount() + getContinueCounter().getCount() +
> -      getAdjustedCount() - getCount();
> -  }
> -  /// Get the associated break counter. Undefined if this counter is not
> -  /// counting a loop.
> -  RegionCounter getBreakCounter() const {
> -    return RegionCounter(*PGO, Counter + 1);
> -  }
> -  /// Get the associated continue counter. Undefined if this counter is not
> -  /// counting a loop.
> -  RegionCounter getContinueCounter() const {
> -    return RegionCounter(*PGO, Counter + 2);
> -  }
> -

>    /// Activate the counter by emitting an increment and starting to track
>    /// adjustments. If AddIncomingFallThrough is true, the current region count
>    /// will be added to the counter for the purposes of tracking the region.
>    void beginRegion(CGBuilderTy &Builder, bool AddIncomingFallThrough=false) {
> +    beginRegion(AddIncomingFallThrough);
> +    PGO->emitCounterIncrement(Builder, Counter);
> +  }
> +  void beginRegion(bool AddIncomingFallThrough=false) {
>      RegionCount = Count;
>      if (AddIncomingFallThrough)
>        RegionCount += PGO->getCurrentRegionCount();
>      PGO->setCurrentRegionCount(RegionCount);
> -    PGO->emitCounterIncrement(Builder, Counter);
>    }

These overloads are awkward, and I'm not really convinced the version
that emits a counter increment is necessary. The callers that have a
builder are all in the CodeGen path, so they really only want to
increment the counter here - the various calls to setCurrentStmt should
ensure that CurrentRegionCount is up to date.

Can we get away with only keeping the overload that doesn't take a
builder, and CodeGen can own incrementing the counter as I described
above?

> +
>    /// For counters on boolean branches, begins tracking adjustments for the
>    /// uncounted path.
>    void beginElseRegion() {
> @@ -210,17 +217,28 @@ public:
>      PGO->setCurrentRegionCount(RegionCount);
>    }
>  
> +  /// Reset the current region count.
> +  void setCurrentRegionCount(uint64_t CurrentCount) {
> +    RegionCount = CurrentCount;
> +    PGO->setCurrentRegionCount(RegionCount);
> +  }
> +
>    /// Adjust for non-local control flow after emitting a subexpression or
>    /// substatement. This must be called to account for constructs such as gotos,
>    /// labels, and returns, so that we can ensure that our region's count is
>    /// correct in the code that follows.
>    void adjustForControlFlow() {
>      Adjust += PGO->getCurrentRegionCount() - RegionCount;
> +    // Reset the region count in case this is called again later.
> +    RegionCount = PGO->getCurrentRegionCount();
>    }
> -  /// Commit all adjustments to the current region. This should be called after
> -  /// all blocks that adjust for control flow count have been emitted.
> -  void applyAdjustmentsToRegion() {
> -    PGO->setCurrentRegionCount(ParentCount + Adjust);
> +
> +  /// Commit all adjustments to the current region. If the region is a loop,
> +  /// the LoopAdjust value should be the count of all the breaks and continues
> +  /// from the loop, to compensate for those counts being deducted from the
> +  /// adjustments for the body of the loop.
> +  void applyAdjustmentsToRegion(uint64_t LoopAdjust) {
> +    PGO->setCurrentRegionCount(ParentCount + Adjust + LoopAdjust);
>    }
>  };
>  
>
> Modified: cfe/trunk/test/CodeGen/Inputs/instr-profile.pgodata
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/Inputs/instr-profile.pgodata?rev=201528&r1=201527&r2=201528&view=diff==============================================================================
> --- cfe/trunk/test/CodeGen/Inputs/instr-profile.pgodata (original)
> +++ cfe/trunk/test/CodeGen/Inputs/instr-profile.pgodata Mon Feb 17 13:21:09 2014
> @@ -1,20 +1,12 @@
> -simple_loops 10
> +simple_loops 4
>  1
>  100
> -0
> -0
>  100
> -0
> -0
> -76
> -0
> -0
> +75
>  
> -conditionals 13
> +conditionals 11
>  1
>  100
> -0
> -0
>  50
>  50
>  33
> @@ -25,7 +17,7 @@ conditionals 13
>  99
>  100
>  
> -early_exits 13
> +early_exits 9
>  1
>  0
>  51
> @@ -34,23 +26,15 @@ early_exits 13
>  1
>  25
>  1
> -26
> -0
> -0
> -1
>  0
>  
> -jumps 30
> +jumps 22
>  1
>  1
>  0
> -0
> -0
>  1
>  0
>  0
> -0
> -0
>  1
>  0
>  1
> @@ -58,8 +42,6 @@ jumps 30
>  3
>  2
>  0
> -0
> -0
>  3
>  0
>  1
> @@ -67,22 +49,18 @@ jumps 30
>  1
>  10
>  0
> -0
> -0
>  10
>  9
>  
> -switches 21
> +switches 19
>  1
>  1
>  1
>  15
> -0
> -7
>  7
>  1
>  0
> -3
> +2
>  2
>  3
>  3
> @@ -95,15 +73,13 @@ switches 21
>  1
>  0
>  
> -big_switch 19
> +big_switch 17
>  1
>  32
> -0
> -0
>  32
>  1
>  0
> -2
> +1
>  1
>  11
>  11
> @@ -119,11 +95,9 @@ big_switch 19
>  issue_with_one_counter 1
>  0
>  
> -boolean_operators 10
> +boolean_operators 8
>  1
>  100
> -0
> -0
>  34
>  66
>  17
> @@ -131,6 +105,17 @@ boolean_operators 10
>  33
>  50
>  
> +boolop_loops 9
> +1
> +50
> +51
> +50
> +26
> +50
> +51
> +50
> +26
> +
>  no_usable_data 5
>  1
>  1
> @@ -140,3 +125,4 @@ no_usable_data 5
>  
>  main 1
>  1
> +
>
> Modified: cfe/trunk/test/CodeGen/instr-profile.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/instr-profile.c?rev=201528&r1=201527&r2=201528&view=diff==============================================================================
> --- cfe/trunk/test/CodeGen/instr-profile.c (original)
> +++ cfe/trunk/test/CodeGen/instr-profile.c Mon Feb 17 13:21:09 2014
> @@ -8,13 +8,14 @@
>  // RUN: %clang %s -o - -emit-llvm -S -fprofile-instr-generate | FileCheck -check-prefix=PGOGEN %s
>  // RUN: %clang %s -o - -emit-llvm -S -fprofile-instr-use=%S/Inputs/instr-profile.pgodata | FileCheck -check-prefix=PGOUSE %s
>  
> -// PGOGEN: @[[SLC:__llvm_pgo_ctr[0-9]*]] = private global [10 x i64] zeroinitializer
> -// PGOGEN: @[[IFC:__llvm_pgo_ctr[0-9]*]] = private global [13 x i64] zeroinitializer
> -// PGOGEN: @[[EEC:__llvm_pgo_ctr[0-9]*]] = private global [13 x i64] zeroinitializer
> -// PGOGEN: @[[JMC:__llvm_pgo_ctr[0-9]*]] = private global [30 x i64] zeroinitializer
> -// PGOGEN: @[[SWC:__llvm_pgo_ctr[0-9]*]] = private global [21 x i64] zeroinitializer
> -// PGOGEN: @[[BSC:__llvm_pgo_ctr[0-9]*]] = private global [19 x i64] zeroinitializer
> -// PGOGEN: @[[BOC:__llvm_pgo_ctr[0-9]*]] = private global [10 x i64]  zeroinitializer
> +// PGOGEN: @[[SLC:__llvm_pgo_ctr[0-9]*]] = private global [4 x i64] zeroinitializer
> +// PGOGEN: @[[IFC:__llvm_pgo_ctr[0-9]*]] = private global [11 x i64] zeroinitializer
> +// PGOGEN: @[[EEC:__llvm_pgo_ctr[0-9]*]] = private global [9 x i64] zeroinitializer
> +// PGOGEN: @[[JMC:__llvm_pgo_ctr[0-9]*]] = private global [22 x i64] zeroinitializer
> +// PGOGEN: @[[SWC:__llvm_pgo_ctr[0-9]*]] = private global [19 x i64] zeroinitializer
> +// PGOGEN: @[[BSC:__llvm_pgo_ctr[0-9]*]] = private global [17 x i64] zeroinitializer
> +// PGOGEN: @[[BOC:__llvm_pgo_ctr[0-9]*]] = private global [8 x i64]  zeroinitializer
> +// PGOGEN: @[[BLC:__llvm_pgo_ctr[0-9]*]] = private global [9 x i64]  zeroinitializer
>  // PGOGEN: @[[NOC:__llvm_pgo_ctr[0-9]*]] = private global [2 x i64]  zeroinitializer
>  // PGOGEN: @[[MAC:__llvm_pgo_ctr[0-9]*]] = private global [1 x i64]  zeroinitializer
>  
> @@ -27,11 +28,11 @@ void simple_loops() {
>    // PGOUSE: br {{.*}} !prof ![[SL1:[0-9]+]]
>    for (i = 0; i < 100; ++i) {
>    }
> -  // PGOGEN: store {{.*}} @[[SLC]], i64 0, i64 4
> +  // PGOGEN: store {{.*}} @[[SLC]], i64 0, i64 2
>    // PGOUSE: br {{.*}} !prof ![[SL2:[0-9]+]]
>    while (i > 0)
>      i--;
> -  // PGOGEN: store {{.*}} @[[SLC]], i64 0, i64 7
> +  // PGOGEN: store {{.*}} @[[SLC]], i64 0, i64 3
>    // PGOUSE: br {{.*}} !prof ![[SL3:[0-9]+]]
>    do {} while (i++ < 75);
>  
> @@ -46,30 +47,30 @@ void conditionals() {
>    // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 1
>    // PGOUSE: br {{.*}} !prof ![[IF1:[0-9]+]]
>    for (int i = 0; i < 100; ++i) {
> -    // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 4
> +    // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 2
>      // PGOUSE: br {{.*}} !prof ![[IF2:[0-9]+]]
>      if (i % 2) {
> -      // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 5
> +      // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 3
>        // PGOUSE: br {{.*}} !prof ![[IF3:[0-9]+]]
>        if (i) {}
> -    // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 6
> +    // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 4
>      // PGOUSE: br {{.*}} !prof ![[IF4:[0-9]+]]
>      } else if (i % 3) {
> -      // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 7
> +      // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 5
>        // PGOUSE: br {{.*}} !prof ![[IF5:[0-9]+]]
>        if (i) {}
>      } else {
> -      // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 8
> +      // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 6
>        // PGOUSE: br {{.*}} !prof ![[IF6:[0-9]+]]
>        if (i) {}
>      }
>  
> -    // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 10
> -    // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 9
> +    // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 8
> +    // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 7
>      // PGOUSE: br {{.*}} !prof ![[IF7:[0-9]+]]
>      if (1 && i) {}
> -    // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 12
> -    // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 11
> +    // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 10
> +    // PGOGEN: store {{.*}} @[[IFC]], i64 0, i64 9
>      // PGOUSE: br {{.*}} !prof ![[IF8:[0-9]+]]
>      if (0 || i) {}
>    }
> @@ -92,25 +93,23 @@ void early_exits() {
>    // PGOUSE: br {{.*}} !prof ![[EE2:[0-9]+]]
>    while (i < 100) {
>      i++;
> -    // PGOGEN: store {{.*}} @[[EEC]], i64 0, i64 5
> +    // PGOGEN: store {{.*}} @[[EEC]], i64 0, i64 3
>      // PGOUSE: br {{.*}} !prof ![[EE3:[0-9]+]]
>      if (i > 50)
> -      // PGOGEN: store {{.*}} @[[EEC]], i64 0, i64 3
>        break;
> -    // PGOGEN: store {{.*}} @[[EEC]], i64 0, i64 6
> +    // PGOGEN: store {{.*}} @[[EEC]], i64 0, i64 4
>      // PGOUSE: br {{.*}} !prof ![[EE4:[0-9]+]]
>      if (i % 2)
> -      // PGOGEN: store {{.*}} @[[EEC]], i64 0, i64 4
>        continue;
>    }
>  
> -  // PGOGEN: store {{.*}} @[[EEC]], i64 0, i64 7
> +  // PGOGEN: store {{.*}} @[[EEC]], i64 0, i64 5
>    // PGOUSE: br {{.*}} !prof ![[EE5:[0-9]+]]
>    if (i) {}
>  
> -  // PGOGEN: store {{.*}} @[[EEC]], i64 0, i64 8
> +  // PGOGEN: store {{.*}} @[[EEC]], i64 0, i64 6
>    do {
> -    // PGOGEN: store {{.*}} @[[EEC]], i64 0, i64 11
> +    // PGOGEN: store {{.*}} @[[EEC]], i64 0, i64 7
>      // PGOUSE: br {{.*}} !prof ![[EE6:[0-9]+]]
>      if (i > 75)
>        return;
> @@ -119,7 +118,7 @@ void early_exits() {
>    // PGOUSE: br {{.*}} !prof ![[EE7:[0-9]+]]
>    } while (i < 100);
>  
> -  // PGOGEN: store {{.*}} @[[EEC]], i64 0, i64 12
> +  // PGOGEN: store {{.*}} @[[EEC]], i64 0, i64 8
>    // Never reached -> no weights
>    if (i) {}
>  
> @@ -140,67 +139,67 @@ void jumps() {
>      // Never reached -> no weights
>      if (i) {}
>    }
> -// PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 5
> +// PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 3
>  outofloop:
> -  // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 6
> +  // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 4
>    // PGOUSE: br {{.*}} !prof ![[JM2:[0-9]+]]
>    if (i) {}
>  
>    goto loop1;
>  
> -  // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 7
> +  // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 5
>    // PGOUSE: br {{.*}} !prof ![[JM3:[0-9]+]]
>    while (i) {
> -  // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 10
> +  // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 6
>    loop1:
> -    // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 11
> +    // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 7
>      // PGOUSE: br {{.*}} !prof ![[JM4:[0-9]+]]
>      if (i) {}
>    }
>  
>    goto loop2;
> -// PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 12
> +// PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 8
>  first:
> -// PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 13
> +// PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 9
>  second:
> -// PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 14
> +// PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 10
>  third:
>    i++;
> -  // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 15
> +  // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 11
>    // PGOUSE: br {{.*}} !prof ![[JM5:[0-9]+]]
>    if (i < 3)
>      goto loop2;
>  
> -  // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 16
> +  // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 12
>    // PGOUSE: br {{.*}} !prof ![[JM6:[0-9]+]]
>    while (i < 3) {
> -  // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 19
> +  // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 13
>    loop2:
>      // PGOUSE: switch {{.*}} [
>      // PGOUSE: ], !prof ![[JM7:[0-9]+]]
>      switch (i) {
> -    // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 21
> +    // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 15
>      case 0:
>        goto first;
> -    // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 22
> +    // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 16
>      case 1:
>        goto second;
> -    // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 23
> +    // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 17
>      case 2:
>        goto third;
>      }
> -    // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 20
> +    // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 14
>    }
>  
> -  // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 24
> +  // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 18
>    // PGOUSE: br {{.*}} !prof ![[JM8:[0-9]+]]
>    for (i = 0; i < 10; ++i) {
>      goto withinloop;
>      // never reached -> no weights
>      if (i) {}
> -  // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 28
> +  // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 20
>    withinloop:
> -    // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 29
> +    // PGOGEN: store {{.*}} @[[JMC]], i64 0, i64 21
>      // PGOUSE: br {{.*}} !prof ![[JM9:[0-9]+]]
>      if (i) {}
>    }
> @@ -229,52 +228,52 @@ void switches() {
>      // PGOUSE: switch {{.*}} [
>      // PGOUSE: ], !prof ![[SW2:[0-9]+]]
>      switch (i[weights]) {
> -    // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 7
> +    // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 5
>      case 1:
> -      // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 8
> +      // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 6
>        // PGOUSE: br {{.*}} !prof ![[SW3:[0-9]+]]
>        if (i) {}
>        // fallthrough
> -    // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 9
> +    // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 7
>      case 2:
> -      // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 10
> +      // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 8
>        // PGOUSE: br {{.*}} !prof ![[SW4:[0-9]+]]
>        if (i) {}
>        break;
> -    // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 11
> +    // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 9
>      case 3:
> -      // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 12
> +      // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 10
>        // PGOUSE: br {{.*}} !prof ![[SW5:[0-9]+]]
>        if (i) {}
>        continue;
> -    // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 13
> +    // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 11
>      case 4:
> -      // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 14
> +      // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 12
>        // PGOUSE: br {{.*}} !prof ![[SW6:[0-9]+]]
>        if (i) {}
>        // PGOUSE: switch {{.*}} [
>        // PGOUSE: ], !prof ![[SW7:[0-9]+]]
>        switch (i) {
> -      // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 16
> +      // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 14
>        case 6 ... 9:
> -        // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 17
> +        // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 15
>          // PGOUSE: br {{.*}} !prof ![[SW8:[0-9]+]]
>          if (i) {}
>          continue;
>        }
> -      // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 15
> +      // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 13
>  
> -    // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 18
> +    // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 16
>      default:
> -      // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 19
> +      // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 17
>        // PGOUSE: br {{.*}} !prof ![[SW9:[0-9]+]]
>        if (i == len - 1)
>          return;
>      }
> -    // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 6
> +    // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 4
>    }
>  
> -  // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 20
> +  // PGOGEN: store {{.*}} @[[SWC]], i64 0, i64 18
>    // Never reached -> no weights
>    if (weights[0]) {}
>  
> @@ -292,56 +291,56 @@ void big_switch() {
>      // PGOUSE: switch {{.*}} [
>      // PGOUSE: ], !prof ![[BS2:[0-9]+]]
>      switch (1 << i) {
> -    // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 5
> +    // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 3
>      case (1 << 0):
> -      // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 6
> +      // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 4
>        // PGOUSE: br {{.*}} !prof ![[BS3:[0-9]+]]
>        if (i) {}
>        // fallthrough
> -    // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 7
> +    // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 5
>      case (1 << 1):
> -      // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 8
> +      // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 6
>        // PGOUSE: br {{.*}} !prof ![[BS4:[0-9]+]]
>        if (i) {}
>        break;
> -    // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 9
> +    // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 7
>      case (1 << 2) ... (1 << 12):
> -      // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 10
> +      // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 8
>        // PGOUSE: br {{.*}} !prof ![[BS5:[0-9]+]]
>        if (i) {}
>        break;
>      // The branch for the large case range above appears after the case body
>      // PGOUSE: br {{.*}} !prof ![[BS6:[0-9]+]]
>  
> -    // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 11
> +    // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 9
>      case (1 << 13):
> -      // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 12
> +      // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 10
>        // PGOUSE: br {{.*}} !prof ![[BS7:[0-9]+]]
>        if (i) {}
>        break;
> -    // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 13
> +    // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 11
>      case (1 << 14) ... (1 << 28):
> -      // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 14
> +      // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 12
>        // PGOUSE: br {{.*}} !prof ![[BS8:[0-9]+]]
>        if (i) {}
>        break;
>      // The branch for the large case range above appears after the case body
>      // PGOUSE: br {{.*}} !prof ![[BS9:[0-9]+]]
>  
> -    // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 15
> +    // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 13
>      case (1 << 29) ... ((1 << 29) + 1):
> -      // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 16
> +      // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 14
>        // PGOUSE: br {{.*}} !prof ![[BS10:[0-9]+]]
>        if (i) {}
>        break;
> -    // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 17
> +    // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 15
>      default:
> -      // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 18
> +      // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 16
>        // PGOUSE: br {{.*}} !prof ![[BS11:[0-9]+]]
>        if (i) {}
>        break;
>      }
> -    // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 4
> +    // PGOGEN: store {{.*}} @[[BSC]], i64 0, i64 2
>    }
>  
>    // PGOGEN-NOT: store {{.*}} @[[BSC]],
> @@ -357,28 +356,64 @@ void boolean_operators() {
>    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 1
>    // PGOUSE: br {{.*}} !prof ![[BO1:[0-9]+]]
>    for (int i = 0; i < 100; ++i) {
> -    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 4
> +    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 2
>      // PGOUSE: br {{.*}} !prof ![[BO2:[0-9]+]]
>      v = i % 3 || i;
>  
> -    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 5
> +    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 3
>      // PGOUSE: br {{.*}} !prof ![[BO3:[0-9]+]]
>      v = i % 3 && i;
>  
> -    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 7
> -    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 6
> +    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 5
> +    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 4
>      // PGOUSE: br {{.*}} !prof ![[BO4:[0-9]+]]
>      // PGOUSE: br {{.*}} !prof ![[BO5:[0-9]+]]
>      v = i % 3 || i % 2 || i;
>  
> -    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 9
> -    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 8
> +    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 7
> +    // PGOGEN: store {{.*}} @[[BOC]], i64 0, i64 6
>      // PGOUSE: br {{.*}} !prof ![[BO6:[0-9]+]]
>      // PGOUSE: br {{.*}} !prof ![[BO7:[0-9]+]]
>      v = i % 2 && i % 3 && i;
>    }
>  
> -  // PGOGEN-NOT: store {{.*}} @[BOC]],
> +  // PGOGEN-NOT: store {{.*}} @[[BOC]],
> +  // PGOUSE-NOT: br {{.*}} !prof ![0-9]+
> +}
> +
> +// PGOGEN-LABEL: @boolop_loops()
> +// PGOUSE-LABEL: @boolop_loops()
> +// PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 0
> +void boolop_loops() {
> +  int i = 100;
> +
> +  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 2
> +  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 1
> +  // PGOUSE: br {{.*}} !prof ![[BL1:[0-9]+]]
> +  // PGOUSE: br {{.*}} !prof ![[BL2:[0-9]+]]
> +  while (i && i > 50)
> +    i--;
> +
> +  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 4
> +  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 3
> +  // PGOUSE: br {{.*}} !prof ![[BL3:[0-9]+]]
> +  // PGOUSE: br {{.*}} !prof ![[BL4:[0-9]+]]
> +  while ((i % 2) || (i > 0))
> +    i--;
> +
> +  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 6
> +  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 5
> +  // PGOUSE: br {{.*}} !prof ![[BL5:[0-9]+]]
> +  // PGOUSE: br {{.*}} !prof ![[BL6:[0-9]+]]
> +  for (i = 100; i && i > 50; --i);
> +
> +  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 8
> +  // PGOGEN: store {{.*}} @[[BLC]], i64 0, i64 7
> +  // PGOUSE: br {{.*}} !prof ![[BL7:[0-9]+]]
> +  // PGOUSE: br {{.*}} !prof ![[BL8:[0-9]+]]
> +  for (; (i % 2) || (i > 0); --i);
> +
> +  // PGOGEN-NOT: store {{.*}} @[[BLC]],
>    // PGOUSE-NOT: br {{.*}} !prof ![0-9]+
>  }
>  
> @@ -457,7 +492,14 @@ void no_usable_data() {
>  // PGOUSE-DAG: ![[BO5]] = metadata !{metadata !"branch_weights", i32 18, i32 18}
>  // PGOUSE-DAG: ![[BO6]] = metadata !{metadata !"branch_weights", i32 51, i32 51}
>  // PGOUSE-DAG: ![[BO7]] = metadata !{metadata !"branch_weights", i32 34, i32 18}
> -
> +// PGOUSE-DAG: ![[BL1]] = metadata !{metadata !"branch_weights", i32 52, i32 1}
> +// PGOUSE-DAG: ![[BL2]] = metadata !{metadata !"branch_weights", i32 51, i32 2}
> +// PGOUSE-DAG: ![[BL3]] = metadata !{metadata !"branch_weights", i32 26, i32 27}
> +// PGOUSE-DAG: ![[BL4]] = metadata !{metadata !"branch_weights", i32 51, i32 2}
> +// PGOUSE-DAG: ![[BL5]] = metadata !{metadata !"branch_weights", i32 52, i32 1}
> +// PGOUSE-DAG: ![[BL6]] = metadata !{metadata !"branch_weights", i32 51, i32 2}
> +// PGOUSE-DAG: ![[BL7]] = metadata !{metadata !"branch_weights", i32 26, i32 27}
> +// PGOUSE-DAG: ![[BL8]] = metadata !{metadata !"branch_weights", i32 51, i32 2}
>  
>  int main(int argc, const char *argv[]) {
>    simple_loops();
> @@ -467,6 +509,7 @@ int main(int argc, const char *argv[]) {
>    switches();
>    big_switch();
>    boolean_operators();
> +  boolop_loops();
>    no_usable_data();
>    return 0;
>  }
>
> Modified: cfe/trunk/test/CodeGenCXX/Inputs/instr-profile-throws.pgodata
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/Inputs/instr-profile-throws.pgodata?rev=201528&r1=201527&r2=201528&view=diff==============================================================================
> --- cfe/trunk/test/CodeGenCXX/Inputs/instr-profile-throws.pgodata (original)
> +++ cfe/trunk/test/CodeGenCXX/Inputs/instr-profile-throws.pgodata Mon Feb 17 13:21:09 2014
> @@ -1,8 +1,6 @@
> -_Z6throwsv 11
> +_Z6throwsv 9
>  1
>  100
> -0
> -0
>  100
>  66
>  33
>
> Modified: cfe/trunk/test/CodeGenCXX/instr-profile-throws.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/instr-profile-throws.cpp?rev=201528&r1=201527&r2=201528&view=diff==============================================================================
> --- cfe/trunk/test/CodeGenCXX/instr-profile-throws.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/instr-profile-throws.cpp Mon Feb 17 13:21:09 2014
> @@ -13,8 +13,8 @@
>  // RUN: %clang %s -o - -emit-llvm -S -fprofile-instr-use=%S/Inputs/instr-profile-throws.pgodata -target %itanium_abi_triple | FileCheck -check-prefix=PGOUSE %s
>  // RUN: %clang %s -o - -emit-llvm -S -fprofile-instr-use=%S/Inputs/instr-profile-throws.pgodata -target %itanium_abi_triple | FileCheck -check-prefix=PGOUSE-EXC %s
>  
> -// PGOGEN: @[[THC:__llvm_pgo_ctr[0-9]*]] = private global [11 x i64] zeroinitializer
> -// PGOGEN-EXC: @[[THC:__llvm_pgo_ctr[0-9]*]] = private global [11 x i64] zeroinitializer
> +// PGOGEN: @[[THC:__llvm_pgo_ctr[0-9]*]] = private global [9 x i64] zeroinitializer
> +// PGOGEN-EXC: @[[THC:__llvm_pgo_ctr[0-9]*]] = private global [9 x i64] zeroinitializer
>  
>  // PGOGEN-LABEL: @_Z6throwsv()
>  // PGOUSE-LABEL: @_Z6throwsv()
> @@ -24,10 +24,10 @@ void throws() {
>    // PGOUSE: br {{.*}} !prof ![[TH1:[0-9]+]]
>    for (int i = 0; i < 100; ++i) {
>      try {
> -      // PGOGEN: store {{.*}} @[[THC]], i64 0, i64 5
> +      // PGOGEN: store {{.*}} @[[THC]], i64 0, i64 3
>        // PGOUSE: br {{.*}} !prof ![[TH2:[0-9]+]]
>        if (i % 3) {
> -        // PGOGEN: store {{.*}} @[[THC]], i64 0, i64 6
> +        // PGOGEN: store {{.*}} @[[THC]], i64 0, i64 4
>          // PGOUSE: br {{.*}} !prof ![[TH3:[0-9]+]]
>          if (i < 50)
>            throw 1;
> @@ -38,7 +38,7 @@ void throws() {
>          // PGOUSE: if.else{{.*}}:
>          // PGOGEN: if.else{{.*}}:
>  
> -        // PGOGEN: store {{.*}} @[[THC]], i64 0, i64 7
> +        // PGOGEN: store {{.*}} @[[THC]], i64 0, i64 5
>          // PGOUSE: br {{.*}} !prof ![[TH4:[0-9]+]]
>          if (i >= 50)
>            throw 0;
> @@ -47,14 +47,14 @@ void throws() {
>        // PGOUSE-EXC: catch{{.*}}:
>        // PGOGEN-EXC: catch{{.*}}:
>  
> -      // PGOGEN-EXC: store {{.*}} @[[THC]], i64 0, i64 8
> -      // PGOGEN-EXC: store {{.*}} @[[THC]], i64 0, i64 9
> +      // PGOGEN-EXC: store {{.*}} @[[THC]], i64 0, i64 6
> +      // PGOGEN-EXC: store {{.*}} @[[THC]], i64 0, i64 7
>        // PGOUSE-EXC: br {{.*}} !prof ![[TH5:[0-9]+]]
>        if (e) {}
>      }
> -    // PGOGEN: store {{.*}} @[[THC]], i64 0, i64 4
> +    // PGOGEN: store {{.*}} @[[THC]], i64 0, i64 2
>  
> -    // PGOGEN: store {{.*}} @[[THC]], i64 0, i64 10
> +    // PGOGEN: store {{.*}} @[[THC]], i64 0, i64 8
>      // PGOUSE: br {{.*}} !prof ![[TH6:[0-9]+]]
>      if (i < 100) {}
>    }
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list