gulfem created this revision. Herald added subscribers: ellis, wenlei, hiraditya. Herald added a project: All. gulfem requested review of this revision. Herald added projects: clang, LLVM. Herald added subscribers: llvm-commits, cfe-commits.
This patch inserts 1-byte boolean counters instead of an 8-byte counters into llvm profiles for source-based code coverage. The origial idea was proposed as "block-cov" for PGO, and this patch reuses that idea for coverage. https://groups.google.com/g/llvm-dev/c/r03Z6JoN7d4 This is a WIP prototype implementation which only implements boolean counters for only a handful of control-flow statements (while, for, if, switch). I will continue to extend it for other control-flow statements. The current 8-byte counters mechanism add counters to minimal regions, and infer the counters in the remaining regions via adding or subtracting counters. Whenever there is control-flow merge, it adds the counters from all the incoming regions. When we use boolean counters, we can use a new counter expression called `or` instead of an and for such cases. Therefore, this patch adds an Or kind into CounterExpression. Similarly, 8-byte counters mechanism infers the counters in some regions by subtracting counters. For example, it infers the counter in the `if.else` region by subtracting the counters between `if.entry` and `if.then` regions in an if statement. However, we are not going to be able to infer counters by subtracting two execution counts when using boolean counters. Therefore, we need to insert additional counters for the cases where we need to subtract counters. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D127040 Files: clang/lib/CodeGen/CGStmt.cpp clang/lib/CodeGen/CodeGenModule.cpp clang/lib/CodeGen/CodeGenPGO.cpp clang/lib/CodeGen/CodeGenPGO.h clang/lib/CodeGen/CoverageMappingGen.cpp clang/test/CoverageMapping/boolean-counters.cpp llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h llvm/lib/ProfileData/Coverage/CoverageMapping.cpp llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
Index: llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp =================================================================== --- llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp @@ -197,7 +197,8 @@ Tag -= Counter::Expression; switch (Tag) { case CounterExpression::Subtract: - case CounterExpression::Add: { + case CounterExpression::Add: + case CounterExpression::Or: { auto ID = Value >> Counter::EncodingTagBits; if (ID >= Expressions.size()) return make_error<CoverageMapError>(coveragemap_error::malformed); Index: llvm/lib/ProfileData/Coverage/CoverageMapping.cpp =================================================================== --- llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -134,6 +134,14 @@ return Simplify ? simplify(Cnt) : Cnt; } +Counter CounterExpressionBuilder::orCounters(Counter LHS, Counter RHS) { + if (LHS.getKind() == Counter::Zero) + return Counter::getCounter(RHS.getCounterID()); + if (RHS.getKind() == Counter::Zero) + return Counter::getCounter(LHS.getCounterID()); + return get(CounterExpression(CounterExpression::Or, LHS, RHS)); +} + void CounterMappingContext::dump(const Counter &C, raw_ostream &OS) const { switch (C.getKind()) { case Counter::Zero: @@ -148,7 +156,10 @@ const auto &E = Expressions[C.getExpressionID()]; OS << '('; dump(E.LHS, OS); - OS << (E.Kind == CounterExpression::Subtract ? " - " : " + "); + if (E.Kind == CounterExpression::Or) + OS << " || "; + else + OS << (E.Kind == CounterExpression::Subtract ? " - " : " + "); dump(E.RHS, OS); OS << ')'; break; @@ -182,6 +193,9 @@ Expected<int64_t> RHS = evaluate(E.RHS); if (!RHS) return RHS; + if (E.Kind == CounterExpression::Or) + return *RHS || *LHS; + return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS; } } Index: llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h =================================================================== --- llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h +++ llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h @@ -93,8 +93,8 @@ /// The CounterExpression kind (Add or Subtract) is encoded in bit 0 next to /// the CounterKind. This means CounterKind has to leave bit 0 free. enum CounterKind { Zero, CounterValueReference, Expression }; - static const unsigned EncodingTagBits = 2; - static const unsigned EncodingTagMask = 0x3; + static const unsigned EncodingTagBits = 3; + static const unsigned EncodingTagMask = 0x7; static const unsigned EncodingCounterTagAndExpansionRegionTagBits = EncodingTagBits + 1; @@ -147,7 +147,7 @@ /// A Counter expression is a value that represents an arithmetic operation /// with two counters. struct CounterExpression { - enum ExprKind { Subtract, Add }; + enum ExprKind { Subtract, Add, Or }; ExprKind Kind; Counter LHS, RHS; @@ -200,6 +200,9 @@ /// Return a counter that represents the expression that subtracts RHS from /// LHS. Counter subtract(Counter LHS, Counter RHS, bool Simplify = true); + + /// Return a counter that represents the expression RHS || LHS + Counter orCounters(Counter LHS, Counter RHS); }; using LineColPair = std::pair<unsigned, unsigned>; Index: clang/test/CoverageMapping/boolean-counters.cpp =================================================================== --- /dev/null +++ clang/test/CoverageMapping/boolean-counters.cpp @@ -0,0 +1,112 @@ +// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -mllvm -enable-boolean-counters=true -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name return.c %s | FileCheck %s + +// CHECK: _Z6testIfi +int testIf(int x) { // CHECK-NEXT: File 0, [[@LINE]]:19 -> [[@LINE+10]]:2 = #0 + // CHECK-NEXT: File 0, [[@LINE+5]]:7 -> [[@LINE+5]]:13 = #0 + // CHECK-NEXT: Gap,File 0, [[@LINE+4]]:14 -> [[@LINE+5]]:5 = #2 + // CHECK-NEXT: File 0, [[@LINE+4]]:5 -> [[@LINE+4]]:16 = #2 + // CHECK-NEXT: File 0, [[@LINE+5]]:3 -> [[@LINE+5]]:16 = #1 + int result = 0; + if (x == 0) + result = -1; + + return result; +} + +// CHECK-NEXT: _Z10testIfElsei +int testIfElse(int x) { // CHECK-NEXT: File 0, [[@LINE]]:23 -> [[@LINE+13]]:2 = #0 + // CHECK-NEXT: File 0, [[@LINE+7]]:7 -> [[@LINE+7]]:12 = #0 + // CHECK-NEXT: Gap,File 0, [[@LINE+6]]:13 -> [[@LINE+7]]:5 = #1 + // CHECK-NEXT: File 0, [[@LINE+6]]:5 -> [[@LINE+6]]:15 = #1 + // CHECK-NEXT: Gap,File 0, [[@LINE+5]]:16 -> [[@LINE+7]]:5 = #2 + // CHECK-NEXT: File 0, [[@LINE+6]]:5 -> [[@LINE+6]]:19 = #2 + // CHECK-NEXT: File 0, [[@LINE+6]]:3 -> [[@LINE+6]]:16 = (#1 || #2) + int result = 0; + if (x < 0) + result = 0; + else + result = x * x; + return result; +} + +// CHECK-NEXT: _Z16testIfElseReturni +int testIfElseReturn(int x) { // CHECK-NEXT: File 0, [[@LINE]]:29 -> [[@LINE+14]]:2 = #0 + // CHECK-NEXT: File 0, [[@LINE+8]]:7 -> [[@LINE+8]]:12 = #0 + // CHECK-NEXT: Gap,File 0, [[@LINE+7]]:13 -> [[@LINE+8]]:5 = #1 + // CHECK-NEXT: File 0, [[@LINE+7]]:5 -> [[@LINE+7]]:19 = #1 + // CHECK-NEXT: Gap,File 0, [[@LINE+6]]:20 -> [[@LINE+8]]:5 = #2 + // CHECK-NEXT: File 0, [[@LINE+7]]:5 -> [[@LINE+7]]:13 = #2 + // CHECK-NEXT: Gap,File 0, [[@LINE+6]]:14 -> [[@LINE+7]]:3 = #1 + // CHECK-NEXT: File 0, [[@LINE+6]]:3 -> [[@LINE+6]]:16 = #1 + int result = 0; + if (x > 0) + result = x * x; + else + return 0; + return result; +} + +// CHECK-NEXT: _Z10testSwitchi +int testSwitch(int x) { // CHECK-NEXT: File 0, [[@LINE]]:23 -> [[@LINE+22]]:2 = #0 + // CHECK-NEXT: Gap,File 0, [[@LINE+9]]:14 -> [[@LINE+17]]:15 = 0 + // CHECK-NEXT: File 0, [[@LINE+9]]:3 -> [[@LINE+11]]:10 = #2 + // CHECK-NEXT: Gap,File 0, [[@LINE+10]]:11 -> [[@LINE+11]]:3 = 0 + // CHECK-NEXT: File 0, [[@LINE+10]]:3 -> [[@LINE+12]]:10 = #3 + // CHECK-NEXT: Gap,File 0, [[@LINE+11]]:11 -> [[@LINE+12]]:3 = 0 + // CHECK-NEXT: File 0, [[@LINE+11]]:3 -> [[@LINE+12]]:15 = #4 + // CHECK-NEXT: Gap,File 0, [[@LINE+12]]:4 -> [[@LINE+14]]:3 = #1 + // CHECK-NEXT: File 0, [[@LINE+13]]:3 -> [[@LINE+13]]:16 = #1 + int result; + switch (x) { + case 1: + result = 1; + break; + case 2: + result = 2; + break; + default: + result = 0; + } + + return result; +} + +// CHECK-NEXT: _Z9testWhilei +int testWhile(int x) { // CHECK-NEXT: File 0, [[@LINE]]:22 -> [[@LINE+13]]:2 = #0 + // CHECK-NEXT: File 0, [[@LINE+6]]:10 -> [[@LINE+6]]:16 = #0 + // CHECK-NEXT: Gap,File 0, [[@LINE+5]]:17 -> [[@LINE+5]]:18 = #2 + // CHECK-NEXT: File 0, [[@LINE+4]]:18 -> [[@LINE+7]]:4 = #2 + // CHECK-NEXT: File 0, [[@LINE+8]]:3 -> [[@LINE+8]]:13 = #1 + int i = x; + int sum = 0; + while (i < 10) { + sum += i; + i++; + } + + return sum; +} + +// CHECK-NEXT: _Z12testContinuei +int testContinue(int x) { // CHECK-NEXT: File 0, [[@LINE]]:25 -> [[@LINE+21]]:2 = #0 + // CHECK-NEXT: File 0, [[@LINE+12]]:10 -> [[@LINE+12]]:16 = ((#0 || #3) || #4) + // CHECK-NEXT: Gap,File 0, [[@LINE+11]]:17 -> [[@LINE+11]]:18 = #2 + // CHECK-NEXT: File 0, [[@LINE+10]]:18 -> [[@LINE+15]]:4 = #2 + // CHECK-NEXT: File 0, [[@LINE+10]]:9 -> [[@LINE+10]]:15 = #2 + // CHECK-NEXT: Gap,File 0, [[@LINE+9]]:16 -> [[@LINE+10]]:7 = #4 + // CHECK-NEXT: File 0, [[@LINE+9]]:7 -> [[@LINE+9]]:15 = #4 + // CHECK-NEXT: Gap,File 0, [[@LINE+8]]:16 -> [[@LINE+9]]:5 = #3 + // CHECK-NEXT: File 0, [[@LINE+8]]:5 -> [[@LINE+10]]:4 = #3 + // CHECK-NEXT: Gap,File 0, [[@LINE+9]]:4 -> [[@LINE+11]]:3 = #1 + // CHECK-NEXT: File 0, [[@LINE+10]]:3 -> [[@LINE+10]]:13 = #1 + int i = x; + int sum = 0; + while (i < 10) { + if (i == 4) + continue; + sum += i; + i++; + } + + return sum; +} Index: clang/lib/CodeGen/CoverageMappingGen.cpp =================================================================== --- clang/lib/CodeGen/CoverageMappingGen.cpp +++ clang/lib/CodeGen/CoverageMappingGen.cpp @@ -31,6 +31,10 @@ // is textually included. #define COVMAP_V3 +namespace llvm { +extern cl::opt<bool> EnableBooleanCounters; +} + static llvm::cl::opt<bool> EmptyLineCommentCoverage( "emptyline-comment-coverage", llvm::cl::desc("Emit emptylines and comment lines as skipped regions (only " @@ -564,6 +568,15 @@ return addCounters(addCounters(C1, C2, Simplify), C3, Simplify); } + /// Return a counter for the result of \c LHS or \c RHS. + Counter orCounters(Counter LHS, Counter RHS) { + return Builder.orCounters(LHS, RHS); + } + + Counter orCounters(Counter C1, Counter C2, Counter C3) { + return orCounters(orCounters(C1, C2), C3); + } + /// Return the region counter for the given statement. /// /// This should only be called on statements that have a dedicated counter. @@ -1045,8 +1058,12 @@ void VisitBreakStmt(const BreakStmt *S) { assert(!BreakContinueStack.empty() && "break not in a loop or switch!"); - BreakContinueStack.back().BreakCount = addCounters( - BreakContinueStack.back().BreakCount, getRegion().getCounter()); + if (llvm::EnableBooleanCounters) + BreakContinueStack.back().BreakCount = orCounters( + BreakContinueStack.back().BreakCount, getRegion().getCounter()); + else + BreakContinueStack.back().BreakCount = addCounters( + BreakContinueStack.back().BreakCount, getRegion().getCounter()); // FIXME: a break in a switch should terminate regions for all preceding // case statements, not just the most recent one. terminateRegion(S); @@ -1054,8 +1071,12 @@ void VisitContinueStmt(const ContinueStmt *S) { assert(!BreakContinueStack.empty() && "continue stmt not in a loop!"); - BreakContinueStack.back().ContinueCount = addCounters( - BreakContinueStack.back().ContinueCount, getRegion().getCounter()); + if (llvm::EnableBooleanCounters) + BreakContinueStack.back().ContinueCount = orCounters( + BreakContinueStack.back().ContinueCount, getRegion().getCounter()); + else + BreakContinueStack.back().ContinueCount = addCounters( + BreakContinueStack.back().ContinueCount, getRegion().getCounter()); terminateRegion(S); } @@ -1073,7 +1094,9 @@ extendRegion(S); Counter ParentCount = getRegion().getCounter(); - Counter BodyCount = getRegionCounter(S); + Counter BodyCount = llvm::EnableBooleanCounters + ? getRegionCounter(S->getBody()) + : getRegionCounter(S); // Handle the body first so that we can get the backedge count. BreakContinueStack.push_back(BreakContinue()); @@ -1086,7 +1109,10 @@ // Go back to handle the condition. Counter CondCount = - addCounters(ParentCount, BackedgeCount, BC.ContinueCount); + llvm::EnableBooleanCounters + ? orCounters(ParentCount, BackedgeCount, BC.ContinueCount) + : addCounters(ParentCount, BackedgeCount, BC.ContinueCount); + propagateCounts(CondCount, S->getCond()); adjustForOutOfOrderTraversal(getEnd(S)); @@ -1096,7 +1122,11 @@ fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount); Counter OutCount = - addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount)); + llvm::EnableBooleanCounters + ? getRegionCounter(S) + : addCounters(BC.BreakCount, + subtractCounters(CondCount, BodyCount)); + if (OutCount != ParentCount) { pushRegion(OutCount); GapRegionCounter = OutCount; @@ -1105,8 +1135,9 @@ } // Create Branch Region around condition. - createBranchRegion(S->getCond(), BodyCount, - subtractCounters(CondCount, BodyCount)); + if (!llvm::EnableBooleanCounters) + createBranchRegion(S->getCond(), BodyCount, + subtractCounters(CondCount, BodyCount)); } void VisitDoStmt(const DoStmt *S) { @@ -1148,7 +1179,9 @@ Visit(S->getInit()); Counter ParentCount = getRegion().getCounter(); - Counter BodyCount = getRegionCounter(S); + Counter BodyCount = llvm::EnableBooleanCounters + ? getRegionCounter(S->getBody()) + : getRegionCounter(S); // The loop increment may contain a break or continue. if (S->getInc()) @@ -1167,14 +1200,23 @@ // the count for all the continue statements. BreakContinue IncrementBC; if (const Stmt *Inc = S->getInc()) { - propagateCounts(addCounters(BackedgeCount, BodyBC.ContinueCount), Inc); + if (llvm::EnableBooleanCounters) + propagateCounts(orCounters(BackedgeCount, BodyBC.ContinueCount), Inc); + else + propagateCounts(addCounters(BackedgeCount, BodyBC.ContinueCount), Inc); IncrementBC = BreakContinueStack.pop_back_val(); } // Go back to handle the condition. - Counter CondCount = addCounters( - addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount), - IncrementBC.ContinueCount); + Counter CondCount = + llvm::EnableBooleanCounters + ? orCounters( + orCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount), + IncrementBC.ContinueCount) + : addCounters( + addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount), + IncrementBC.ContinueCount); + if (const Expr *Cond = S->getCond()) { propagateCounts(CondCount, Cond); adjustForOutOfOrderTraversal(getEnd(S)); @@ -1185,8 +1227,11 @@ if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount); - Counter OutCount = addCounters(BodyBC.BreakCount, IncrementBC.BreakCount, - subtractCounters(CondCount, BodyCount)); + Counter OutCount = + llvm::EnableBooleanCounters + ? getRegionCounter(S) + : addCounters(BodyBC.BreakCount, IncrementBC.BreakCount, + subtractCounters(CondCount, BodyCount)); if (OutCount != ParentCount) { pushRegion(OutCount); GapRegionCounter = OutCount; @@ -1195,8 +1240,9 @@ } // Create Branch Region around condition. - createBranchRegion(S->getCond(), BodyCount, - subtractCounters(CondCount, BodyCount)); + if (!llvm::EnableBooleanCounters) + createBranchRegion(S->getCond(), BodyCount, + subtractCounters(CondCount, BodyCount)); } void VisitCXXForRangeStmt(const CXXForRangeStmt *S) { @@ -1311,6 +1357,11 @@ MostRecentLocation = getStart(S); handleFileExit(ExitLoc); + // Early return so do not create branch regions when boolean counters are + // enabled. + if (llvm::EnableBooleanCounters) + return; + // Create a Branch Region around each Case. Subtract the case's // counter from the Parent counter to track the "False" branch count. Counter CaseCountSum; @@ -1372,7 +1423,9 @@ extendRegion(S->getCond()); Counter ParentCount = getRegion().getCounter(); - Counter ThenCount = getRegionCounter(S); + Counter ThenCount = llvm::EnableBooleanCounters + ? getRegionCounter(S->getThen()) + : getRegionCounter(S); // Emitting a counter for the condition makes it easier to interpret the // counter for the body when looking at the coverage. @@ -1386,7 +1439,13 @@ extendRegion(S->getThen()); Counter OutCount = propagateCounts(ThenCount, S->getThen()); - Counter ElseCount = subtractCounters(ParentCount, ThenCount); + Counter ElseCount; + if (llvm::EnableBooleanCounters) { + if (S->getElse()) + ElseCount = getRegionCounter(S->getElse()); + } else + ElseCount = subtractCounters(ParentCount, ThenCount); + if (const Stmt *Else = S->getElse()) { bool ThenHasTerminateStmt = HasTerminateStmt; HasTerminateStmt = false; @@ -1396,12 +1455,16 @@ if (Gap) fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount); extendRegion(Else); - OutCount = addCounters(OutCount, propagateCounts(ElseCount, Else)); + Counter ElseOutCount = propagateCounts(ElseCount, Else); + OutCount = llvm::EnableBooleanCounters + ? orCounters(OutCount, ElseOutCount) + : addCounters(OutCount, ElseOutCount); if (ThenHasTerminateStmt) HasTerminateStmt = true; } else - OutCount = addCounters(OutCount, ElseCount); + OutCount = llvm::EnableBooleanCounters ? getRegionCounter(S) + : addCounters(OutCount, ElseCount); if (OutCount != ParentCount) { pushRegion(OutCount); @@ -1409,8 +1472,9 @@ } // Create Branch Region around condition. - createBranchRegion(S->getCond(), ThenCount, - subtractCounters(ParentCount, ThenCount)); + if (!llvm::EnableBooleanCounters) + createBranchRegion(S->getCond(), ThenCount, + subtractCounters(ParentCount, ThenCount)); } void VisitCXXTryStmt(const CXXTryStmt *S) { Index: clang/lib/CodeGen/CodeGenPGO.h =================================================================== --- clang/lib/CodeGen/CodeGenPGO.h +++ clang/lib/CodeGen/CodeGenPGO.h @@ -91,6 +91,8 @@ // Set a module flag indicating if value profiling is enabled. void setValueProfilingFlag(llvm::Module &M); + void setProfileVersion(llvm::Module &M); + private: void setFuncName(llvm::Function *Fn); void setFuncName(StringRef Name, llvm::GlobalValue::LinkageTypes Linkage); Index: clang/lib/CodeGen/CodeGenPGO.cpp =================================================================== --- clang/lib/CodeGen/CodeGenPGO.cpp +++ clang/lib/CodeGen/CodeGenPGO.cpp @@ -15,6 +15,7 @@ #include "CoverageMappingGen.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/StmtVisitor.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/MDBuilder.h" #include "llvm/Support/CommandLine.h" @@ -22,6 +23,13 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/MD5.h" +namespace llvm { +cl::opt<bool> EnableBooleanCounters("enable-boolean-counters", + llvm::cl::ZeroOrMore, + llvm::cl::desc("Enable boolean counters"), + llvm::cl::Hidden, llvm::cl::init(false)); +} // namespace llvm + static llvm::cl::opt<bool> EnableValueProfiling("enable-value-profiling", llvm::cl::ZeroOrMore, llvm::cl::desc("Enable value profiling"), @@ -234,20 +242,75 @@ return Base::TraverseIfStmt(If); // Otherwise, keep track of which branch we're in while traversing. - VisitStmt(If); + // When boolean counters are enabled and if has an else part, + // do not add a counter for IfStmt, but still include in the function hash. + if (llvm::EnableBooleanCounters && If->getElse()) { + auto Type = getHashType(PGO_HASH_V1, If); + if (Hash.getHashVersion() != PGO_HASH_V1) + Type = getHashType(Hash.getHashVersion(), If); + if (Type != PGOHash::None) + Hash.combine(Type); + } else + VisitStmt(If); + for (Stmt *CS : If->children()) { if (!CS) continue; - if (CS == If->getThen()) + if (CS == If->getThen()) { Hash.combine(PGOHash::IfThenBranch); - else if (CS == If->getElse()) + if (llvm::EnableBooleanCounters) + CounterMap[If->getThen()] = NextCounter++; + } else if (CS == If->getElse()) { Hash.combine(PGOHash::IfElseBranch); + if (llvm::EnableBooleanCounters) + CounterMap[If->getElse()] = NextCounter++; + } TraverseStmt(CS); } Hash.combine(PGOHash::EndOfScope); return true; } + bool TraverseWhileStmt(WhileStmt *While) { + // If we used the V1 hash, use the default traversal. + if (Hash.getHashVersion() == PGO_HASH_V1) + return Base::TraverseWhileStmt(While); + + VisitStmt(While); + for (Stmt *CS : While->children()) { + if (!CS) + continue; + if (llvm::EnableBooleanCounters && CS == While->getBody()) + CounterMap[While->getBody()] = NextCounter++; + TraverseStmt(CS); + } + + if (Hash.getHashVersion() != PGO_HASH_V1) + Hash.combine(PGOHash::EndOfScope); + + return true; + } + + bool TraverseForStmt(ForStmt *For) { + // If we used the V1 hash, use the default traversal. + if (Hash.getHashVersion() == PGO_HASH_V1) + return Base::TraverseForStmt(For); + VisitStmt(For); + for (Stmt *CS : For->children()) { + if (!CS) + continue; + if (CS == For->getBody()) { + if (llvm::EnableBooleanCounters) + CounterMap[For->getBody()] = NextCounter++; + } + TraverseStmt(CS); + } + + if (Hash.getHashVersion() != PGO_HASH_V1) + Hash.combine(PGOHash::EndOfScope); + return true; + } + // If the statement type \p N is nestable, and its nesting impacts profile // stability, define a custom traversal which tracks the end of the statement // in the hash (provided we're not using the V1 hash). @@ -259,9 +322,7 @@ return true; \ } - DEFINE_NESTABLE_TRAVERSAL(WhileStmt) DEFINE_NESTABLE_TRAVERSAL(DoStmt) - DEFINE_NESTABLE_TRAVERSAL(ForStmt) DEFINE_NESTABLE_TRAVERSAL(CXXForRangeStmt) DEFINE_NESTABLE_TRAVERSAL(ObjCForCollectionStmt) DEFINE_NESTABLE_TRAVERSAL(CXXTryStmt) @@ -961,13 +1022,19 @@ Builder.getInt64(FunctionHash), Builder.getInt32(NumRegionCounters), Builder.getInt32(Counter), StepV}; - if (!StepV) - Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment), + + if (llvm::EnableBooleanCounters) + Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_cover), makeArrayRef(Args, 4)); - else - Builder.CreateCall( - CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step), - makeArrayRef(Args)); + else { + if (!StepV) + Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment), + makeArrayRef(Args, 4)); + else + Builder.CreateCall( + CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step), + makeArrayRef(Args)); + } } void CodeGenPGO::setValueProfilingFlag(llvm::Module &M) { @@ -976,6 +1043,29 @@ uint32_t(EnableValueProfiling)); } +void CodeGenPGO::setProfileVersion(llvm::Module &M) { + if (CGM.getCodeGenOpts().hasProfileClangInstr() && + llvm::EnableBooleanCounters) { + const StringRef VarName(INSTR_PROF_QUOTE(INSTR_PROF_RAW_VERSION_VAR)); + llvm::Type *IntTy64 = llvm::Type::getInt64Ty(M.getContext()); + uint64_t ProfileVersion = + (INSTR_PROF_RAW_VERSION | VARIANT_MASK_BYTE_COVERAGE); + + auto IRLevelVersionVariable = new llvm::GlobalVariable( + M, IntTy64, true, llvm::GlobalValue::WeakAnyLinkage, + llvm::Constant::getIntegerValue(IntTy64, + llvm::APInt(64, ProfileVersion)), + VarName); + + IRLevelVersionVariable->setVisibility(llvm::GlobalValue::DefaultVisibility); + llvm::Triple TT(M.getTargetTriple()); + if (TT.supportsCOMDAT()) { + IRLevelVersionVariable->setLinkage(llvm::GlobalValue::ExternalLinkage); + IRLevelVersionVariable->setComdat(M.getOrInsertComdat(VarName)); + } + } +} + // This method either inserts a call to the profile run-time during // instrumentation or puts profile data into metadata for PGO use. void CodeGenPGO::valueProfile(CGBuilderTy &Builder, uint32_t ValueKind, Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -548,6 +548,7 @@ checkAliases(); EmitDeferredUnusedCoverageMappings(); CodeGenPGO(*this).setValueProfilingFlag(getModule()); + CodeGenPGO(*this).setProfileVersion(getModule()); if (CoverageMapping) CoverageMapping->emit(); if (CodeGenOpts.SanitizeCfiCrossDso) { Index: clang/lib/CodeGen/CGStmt.cpp =================================================================== --- clang/lib/CodeGen/CGStmt.cpp +++ clang/lib/CodeGen/CGStmt.cpp @@ -40,6 +40,10 @@ // Statement Emission //===----------------------------------------------------------------------===// +namespace llvm { +extern cl::opt<bool> EnableBooleanCounters; +} + void CodeGenFunction::EmitStopPoint(const Stmt *S) { if (CGDebugInfo *DI = getDebugInfo()) { SourceLocation Loc; @@ -807,7 +811,10 @@ // Emit the 'then' code. EmitBlock(ThenBlock); - incrementProfileCounter(&S); + if (llvm::EnableBooleanCounters) + incrementProfileCounter(S.getThen()); + else + incrementProfileCounter(&S); { RunCleanupsScope ThenScope(*this); EmitStmt(S.getThen()); @@ -821,6 +828,9 @@ auto NL = ApplyDebugLocation::CreateEmpty(*this); EmitBlock(ElseBlock); } + // When boolean counters are enabled, add a counter to else block. + if (llvm::EnableBooleanCounters) + incrementProfileCounter(Else); { RunCleanupsScope ElseScope(*this); EmitStmt(Else); @@ -834,6 +844,9 @@ // Emit the continuation block for code after the if. EmitBlock(ContBlock, true); + // When there is no else, add a counter to continuation block. + if (llvm::EnableBooleanCounters && !S.getElse()) + incrementProfileCounter(&S); } void CodeGenFunction::EmitWhileStmt(const WhileStmt &S, @@ -910,7 +923,10 @@ { RunCleanupsScope BodyScope(*this); EmitBlock(LoopBody); - incrementProfileCounter(&S); + if (llvm::EnableBooleanCounters) + incrementProfileCounter(S.getBody()); + else + incrementProfileCounter(&S); EmitStmt(S.getBody()); } @@ -932,6 +948,10 @@ // a branch, try to erase it. if (!EmitBoolCondBranch) SimplifyForwardingBlocks(LoopHeader.getBlock()); + + // When boolean counters are enabled, add a counter to continuation block. + if (llvm::EnableBooleanCounters) + incrementProfileCounter(&S); } void CodeGenFunction::EmitDoStmt(const DoStmt &S, @@ -1082,8 +1102,11 @@ // Treat it as a non-zero constant. Don't even create a new block for the // body, just fall into it. } - incrementProfileCounter(&S); + if (llvm::EnableBooleanCounters) + incrementProfileCounter(S.getBody()); + else + incrementProfileCounter(&S); { // Create a separate cleanup scope for the body, in case it is not // a compound statement. @@ -1110,6 +1133,10 @@ // Emit the fall-through block. EmitBlock(LoopExit.getBlock(), true); + + // When boolean counters are enabled, add a counter to continuation block. + if (llvm::EnableBooleanCounters) + incrementProfileCounter(&S); } void
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits