diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprComplex.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 8 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjC.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmt.cpp | 141 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 34 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 12 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenPGO.cpp | 414 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenPGO.h | 80 | ||||
-rw-r--r-- | clang/test/CodeGen/Inputs/instr-profile.pgodata | 58 | ||||
-rw-r--r-- | clang/test/CodeGen/instr-profile.c | 207 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/Inputs/instr-profile-throws.pgodata | 4 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/instr-profile-throws.cpp | 18 |
14 files changed, 657 insertions, 334 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 8ed30045291..40ca5889398 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -85,6 +85,7 @@ llvm::AllocaInst *CodeGenFunction::CreateMemTemp(QualType Ty, /// 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 AbstractConditionalOperator *expr) { 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 AbstractConditionalOperator *expr) { // 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"); diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index ef56c0b06f2..313b8d2afcb 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -903,7 +903,6 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { 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 AbstractConditionalOperator *E) { 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) { diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index 938b0b331d7..1f84c86ad6e 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -760,20 +760,16 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { 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"); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 0a49ea5a5e9..78bd037e83d 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2934,7 +2934,6 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) { 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(const BinaryOperator *E) { 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(const BinaryOperator *E) { CGF.EmitBlock(RHSBlock); Cnt.beginRegion(Builder); Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS()); - Cnt.adjustForControlFlow(); eval.end(CGF); @@ -3028,7 +3025,6 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) { // 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 AbstractConditionalOperator *E) { 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) diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 9a0b15d434c..7ca10575c12 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -1628,7 +1628,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ 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()); diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 353d8f075c1..918103fcbd5 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -43,6 +43,7 @@ void CodeGenFunction::EmitStopPoint(const Stmt *S) { 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 GotoStmt &S) { 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::EmitIndirectGotoStmt(const IndirectGotoStmt &S) { 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 IfStmt &S) { RunCleanupsScope ThenScope(*this); EmitStmt(S.getThen()); } - Cnt.adjustForControlFlow(); EmitBranch(ContBlock); // Emit the 'else' code if present. @@ -489,12 +486,10 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) { 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 IfStmt &S) { // 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(const WhileStmt &S) { 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(const WhileStmt &S) { // 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(const WhileStmt &S) { 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(const WhileStmt &S) { 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(const WhileStmt &S) { // 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 DoStmt &S) { 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 DoStmt &S) { 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 DoStmt &S) { } 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 ForStmt &S) { 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 ForStmt &S) { 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 ForStmt &S) { // 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 ForStmt &S) { 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 ForStmt &S) { // 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::EmitCXXForRangeStmt(const CXXForRangeStmt &S) { 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::EmitCXXForRangeStmt(const CXXForRangeStmt &S) { // 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::EmitCXXForRangeStmt(const CXXForRangeStmt &S) { 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::EmitCXXForRangeStmt(const CXXForRangeStmt &S) { // 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::EmitCXXForRangeStmt(const CXXForRangeStmt &S) { // 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(RValue RV, QualType Ty) { /*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(const ReturnStmt &S) { cleanupScope.ForceCleanup(); EmitBranchThroughCleanup(ReturnBlock); - PGO.setCurrentRegionUnreachable(); } void CodeGenFunction::EmitDeclStmt(const DeclStmt &S) { @@ -943,14 +905,7 @@ void CodeGenFunction::EmitBreakStmt(const BreakStmt &S) { 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(const ContinueStmt &S) { 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(const CaseStmt &S) { // 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(const CaseStmt &S) { // 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(const CaseStmt &S) { 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 CaseStmt &S) { // 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 CaseStmt &S) { } } - 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 CaseStmt &S) { 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(const DefaultStmt &S) { 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(const SwitchStmt &S) { // 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()); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 715af365c38..409d1141b81 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -688,6 +688,26 @@ void CodeGenFunction::EmitFunctionBody(FunctionArgList &Args, 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); +} + /// 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::EmitBranchOnBoolExpr(const Expr *Cond, 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::EmitBranchOnBoolExpr(const Expr *Cond, 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::EmitBranchOnBoolExpr(const Expr *Cond, EmitBranchOnBoolExpr(CondBOp->getRHS(), TrueBlock, FalseBlock, RHSCount); eval.end(*this); - Cnt.adjustForControlFlow(); - Cnt.applyAdjustmentsToRegion(); return; } @@ -1037,7 +1056,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond, // 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::EmitBranchOnBoolExpr(const Expr *Cond, cond.begin(*this); EmitBlock(RHSBlock); - Cnt.beginElseRegion(); EmitBranchOnBoolExpr(CondOp->getRHS(), TrueBlock, FalseBlock, TrueCount - LHSScaledTrueCount); cond.end(*this); @@ -1070,7 +1088,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond, // 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); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index a1f6721ae81..185e25ccb29 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -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); diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp index f81cbecd5d3..ec53fdb0225 100644 --- a/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/clang/lib/CodeGen/CodeGenPGO.cpp @@ -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; + 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(GlobalDecl &GD) { 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 Decl *D) { 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(GlobalDecl &GD, PGOProfileData *PGOData) { 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::createBranchWeights(ArrayRef<uint64_t> Weights) { } 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); +} diff --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h index 38923d1b98f..083e5466c66 100644 --- a/clang/lib/CodeGen/CodeGenPGO.h +++ b/clang/lib/CodeGen/CodeGenPGO.h @@ -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); } + /// 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); } }; diff --git a/clang/test/CodeGen/Inputs/instr-profile.pgodata b/clang/test/CodeGen/Inputs/instr-profile.pgodata index 0eaea30ae21..1a445ed7e86 100644 --- a/clang/test/CodeGen/Inputs/instr-profile.pgodata +++ b/clang/test/CodeGen/Inputs/instr-profile.pgodata @@ -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 + diff --git a/clang/test/CodeGen/instr-profile.c b/clang/test/CodeGen/instr-profile.c index c8e75a7e8c9..b5062f4c908 100644 --- a/clang/test/CodeGen/instr-profile.c +++ b/clang/test/CodeGen/instr-profile.c @@ -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; } diff --git a/clang/test/CodeGenCXX/Inputs/instr-profile-throws.pgodata b/clang/test/CodeGenCXX/Inputs/instr-profile-throws.pgodata index 1b64261f5c7..a49522f5584 100644 --- a/clang/test/CodeGenCXX/Inputs/instr-profile-throws.pgodata +++ b/clang/test/CodeGenCXX/Inputs/instr-profile-throws.pgodata @@ -1,8 +1,6 @@ -_Z6throwsv 11 +_Z6throwsv 9 1 100 -0 -0 100 66 33 diff --git a/clang/test/CodeGenCXX/instr-profile-throws.cpp b/clang/test/CodeGenCXX/instr-profile-throws.cpp index 7b870c352b5..33e02514e4e 100644 --- a/clang/test/CodeGenCXX/instr-profile-throws.cpp +++ b/clang/test/CodeGenCXX/instr-profile-throws.cpp @@ -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) {} } |