Author: NAKAMURA Takumi Date: 2026-01-15T09:08:06+09:00 New Revision: 779c05a62548b694750be985d86fa193b0983fa7
URL: https://github.com/llvm/llvm-project/commit/779c05a62548b694750be985d86fa193b0983fa7 DIFF: https://github.com/llvm/llvm-project/commit/779c05a62548b694750be985d86fa193b0983fa7.diff LOG: [MC/DC] Create dedicated MCDCCondBitmapAddr for each Decision (#125411) MCDCCondBitmapAddr is moved from `CodeGenFunction` into `MCDCState` and created for each Decision. In `maybeCreateMCDCCondBitmap`, Allocate bitmaps for all valid Decisions and emit them order by ID, to prevent nondeterminism. Added: Modified: clang/lib/CodeGen/CodeGenFunction.h clang/lib/CodeGen/CodeGenPGO.cpp clang/lib/CodeGen/CodeGenPGO.h clang/lib/CodeGen/MCDCState.h clang/test/Profile/c-mcdc-logicalop-ternary.c Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index caf68f28d4661..1073de1d25ec7 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1644,9 +1644,6 @@ class CodeGenFunction : public CodeGenTypeCache { std::unique_ptr<CodeGenPGO> PGO; - /// Bitmap used by MC/DC to track condition outcomes of a boolean expression. - Address MCDCCondBitmapAddr = Address::invalid(); - /// Calculate branch weights appropriate for PGO data llvm::MDNode *createProfileWeights(uint64_t TrueCount, uint64_t FalseCount) const; diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp index 9cd53208f8abd..d4d1abd50af42 100644 --- a/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/clang/lib/CodeGen/CodeGenPGO.cpp @@ -1265,9 +1265,29 @@ void CodeGenPGO::emitMCDCParameters(CGBuilderTy &Builder) { CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_parameters), Args); } +/// Fill mcdc.addr order by ID. +std::vector<Address *> +CodeGenPGO::getMCDCCondBitmapAddrArray(CGBuilderTy &Builder) { + std::vector<Address *> Result; + + if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState) + return Result; + + SmallVector<std::pair<unsigned, Address *>> SortedPair; + for (auto &[_, V] : RegionMCDCState->DecisionByStmt) + if (V.isValid()) + SortedPair.emplace_back(V.ID, &V.MCDCCondBitmapAddr); + + llvm::sort(SortedPair); + + for (auto &[_, MCDCCondBitmapAddr] : SortedPair) + Result.push_back(MCDCCondBitmapAddr); + + return Result; +} + void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr, CodeGenFunction &CGF) { if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState) return; @@ -1278,6 +1298,10 @@ void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, if (DecisionStateIter == RegionMCDCState->DecisionByStmt.end()) return; + auto &MCDCCondBitmapAddr = DecisionStateIter->second.MCDCCondBitmapAddr; + if (!MCDCCondBitmapAddr.isValid()) + return; + // Don't create tvbitmap_update if the record is allocated but excluded. // Or `bitmap |= (1 << 0)` would be wrongly executed to the next bitmap. if (DecisionStateIter->second.Indices.size() == 0) @@ -1300,14 +1324,16 @@ void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_tvbitmap_update), Args); } -void CodeGenPGO::emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr) { +void CodeGenPGO::emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S) { if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState) return; - S = S->IgnoreParens(); + auto I = RegionMCDCState->DecisionByStmt.find(S->IgnoreParens()); + if (I == RegionMCDCState->DecisionByStmt.end()) + return; - if (!RegionMCDCState->DecisionByStmt.contains(S)) + auto &MCDCCondBitmapAddr = I->second.MCDCCondBitmapAddr; + if (!MCDCCondBitmapAddr.isValid()) return; // Emit intrinsic that resets a dedicated temporary value on the stack to 0. @@ -1315,7 +1341,6 @@ void CodeGenPGO::emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S, } void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr, llvm::Value *Val, CodeGenFunction &CGF) { if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState) @@ -1345,6 +1370,10 @@ void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, if (DecisionIter == RegionMCDCState->DecisionByStmt.end()) return; + auto &MCDCCondBitmapAddr = DecisionIter->second.MCDCCondBitmapAddr; + if (!MCDCCondBitmapAddr.isValid()) + return; + const auto &TVIdxs = DecisionIter->second.Indices[Branch.ID]; auto *CurTV = Builder.CreateLoad(MCDCCondBitmapAddr, @@ -1558,7 +1587,12 @@ void CodeGenFunction::markStmtMaybeUsed(const Stmt *S) { void CodeGenFunction::maybeCreateMCDCCondBitmap() { if (isMCDCCoverageEnabled()) { PGO->emitMCDCParameters(Builder); - MCDCCondBitmapAddr = CreateIRTemp(getContext().UnsignedIntTy, "mcdc.addr"); + + // Set up MCDCCondBitmapAddr for each Decision. + // Note: This doesn't initialize Addrs in invalidated Decisions. + for (auto *MCDCCondBitmapAddr : PGO->getMCDCCondBitmapAddrArray(Builder)) + *MCDCCondBitmapAddr = + CreateIRTemp(getContext().UnsignedIntTy, "mcdc.addr"); } } bool CodeGenFunction::isMCDCDecisionExpr(const Expr *E) const { @@ -1569,13 +1603,13 @@ bool CodeGenFunction::isMCDCBranchExpr(const Expr *E) const { } void CodeGenFunction::maybeResetMCDCCondBitmap(const Expr *E) { if (isMCDCCoverageEnabled() && isBinaryLogicalOp(E)) { - PGO->emitMCDCCondBitmapReset(Builder, E, MCDCCondBitmapAddr); + PGO->emitMCDCCondBitmapReset(Builder, E); PGO->setCurrentStmt(E); } } void CodeGenFunction::maybeUpdateMCDCTestVectorBitmap(const Expr *E) { if (isMCDCCoverageEnabled() && isBinaryLogicalOp(E)) { - PGO->emitMCDCTestVectorBitmapUpdate(Builder, E, MCDCCondBitmapAddr, *this); + PGO->emitMCDCTestVectorBitmapUpdate(Builder, E, *this); PGO->setCurrentStmt(E); } } @@ -1583,7 +1617,7 @@ void CodeGenFunction::maybeUpdateMCDCTestVectorBitmap(const Expr *E) { void CodeGenFunction::maybeUpdateMCDCCondBitmap(const Expr *E, llvm::Value *Val) { if (isMCDCCoverageEnabled()) { - PGO->emitMCDCCondBitmapUpdate(Builder, E, MCDCCondBitmapAddr, Val, *this); + PGO->emitMCDCCondBitmapUpdate(Builder, E, Val, *this); PGO->setCurrentStmt(E); } } diff --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h index 05cb9d497b91e..5e2d72e8427fb 100644 --- a/clang/lib/CodeGen/CodeGenPGO.h +++ b/clang/lib/CodeGen/CodeGenPGO.h @@ -129,14 +129,12 @@ class CodeGenPGO { bool UseFalsePath, bool UseBoth, llvm::Value *StepV); void emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr, CodeGenFunction &CGF); void emitMCDCParameters(CGBuilderTy &Builder); - void emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr); + std::vector<Address *> getMCDCCondBitmapAddrArray(CGBuilderTy &Builder); + void emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S); void emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr, llvm::Value *Val, - CodeGenFunction &CGF); + llvm::Value *Val, CodeGenFunction &CGF); void markStmtAsUsed(bool Skipped, const Stmt *S) { // Do nothing. diff --git a/clang/lib/CodeGen/MCDCState.h b/clang/lib/CodeGen/MCDCState.h index 4b89ddd12d672..583157409b02f 100644 --- a/clang/lib/CodeGen/MCDCState.h +++ b/clang/lib/CodeGen/MCDCState.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_LIB_CODEGEN_MCDCSTATE_H #define LLVM_CLANG_LIB_CODEGEN_MCDCSTATE_H +#include "Address.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ProfileData/Coverage/MCDCTypes.h" @@ -38,6 +39,7 @@ struct State { unsigned BitmapIdx; IndicesTy Indices; unsigned ID = InvalidID; + Address MCDCCondBitmapAddr = Address::invalid(); bool isValid() const { return ID != InvalidID; } diff --git a/clang/test/Profile/c-mcdc-logicalop-ternary.c b/clang/test/Profile/c-mcdc-logicalop-ternary.c index 18ce0b4e5dc14..18682ffdbfec3 100644 --- a/clang/test/Profile/c-mcdc-logicalop-ternary.c +++ b/clang/test/Profile/c-mcdc-logicalop-ternary.c @@ -13,12 +13,14 @@ int test(int a, int b, int c, int d, int e, int f) { // ALLOCATE MCDC TEMP AND ZERO IT. // MCDC-LABEL: @test( -// MCDC: %mcdc.addr = alloca i32, align 4 -// MCDC: store i32 0, ptr %mcdc.addr, align 4 +// MCDC: %[[ADDR0:mcdc.+]] = alloca i32, align 4 +// MCDC: %[[ADDR1:mcdc.+]] = alloca i32, align 4 +// MCDC: %[[ADDR2:mcdc.+]] = alloca i32, align 4 +// MCDC: store i32 0, ptr %[[ADDR0]], align 4 // TERNARY TRUE SHOULD UPDATE THE BITMAP WITH RESULT AT ELEMENT 0. // MCDC-LABEL: cond.true: -// MCDC-DAG: %[[TEMP0:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4 +// MCDC-DAG: %[[TEMP0:mcdc.temp[0-9]*]] = load i32, ptr %[[ADDR0]], align 4 // MCDC: %[[TEMP:[0-9]+]] = add i32 %[[TEMP0]], 0 // MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3 // MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm_test, i32 %[[LAB1]] @@ -30,12 +32,12 @@ int test(int a, int b, int c, int d, int e, int f) { // MCDC: store i8 %[[LAB9]], ptr %[[LAB4]], align 1 // CHECK FOR ZERO OF MCDC TEMP -// MCDC: store i32 0, ptr %mcdc.addr, align 4 +// MCDC: store i32 0, ptr %[[ADDR1]], align 4 // TERNARY TRUE YIELDS TERNARY LHS LOGICAL-AND. // TERNARY LHS LOGICAL-AND SHOULD UPDATE THE BITMAP WITH RESULT AT ELEMENT 1. // MCDC-LABEL: land.end: -// MCDC-DAG: %[[TEMP0:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4 +// MCDC-DAG: %[[TEMP0:mcdc.temp[0-9]*]] = load i32, ptr %[[ADDR1]], align 4 // MCDC: %[[TEMP:[0-9]+]] = add i32 %[[TEMP0]], 3 // MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3 // MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm_test, i32 %[[LAB1]] @@ -48,7 +50,7 @@ int test(int a, int b, int c, int d, int e, int f) { // TERNARY FALSE SHOULD UPDATE THE BITMAP WITH RESULT AT ELEMENT 0. // MCDC-LABEL: cond.false: -// MCDC-DAG: %[[TEMP0:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4 +// MCDC-DAG: %[[TEMP0:mcdc.+]] = load i32, ptr %[[ADDR0]], align 4 // MCDC: %[[TEMP:[0-9]+]] = add i32 %[[TEMP0]], 0 // MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3 // MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm_test, i32 %[[LAB1]] @@ -60,12 +62,12 @@ int test(int a, int b, int c, int d, int e, int f) { // MCDC: store i8 %[[LAB9]], ptr %[[LAB4]], align 1 // CHECK FOR ZERO OF MCDC TEMP -// MCDC: store i32 0, ptr %mcdc.addr, align 4 +// MCDC: store i32 0, ptr %[[ADDR2]], align 4 // TERNARY FALSE YIELDS TERNARY RHS LOGICAL-OR. // TERNARY RHS LOGICAL-OR SHOULD UPDATE THE BITMAP WITH RESULT AT ELEMENT 2. // MCDC-LABEL: lor.end: -// MCDC-DAG: %[[TEMP0:mcdc.temp[0-9]*]] = load i32, ptr %mcdc.addr, align 4 +// MCDC-DAG: %[[TEMP0:mcdc.temp[0-9]*]] = load i32, ptr %[[ADDR2]], align 4 // MCDC: %[[TEMP:[0-9]+]] = add i32 %[[TEMP0]], 6 // MCDC: %[[LAB1:[0-9]+]] = lshr i32 %[[TEMP]], 3 // MCDC: %[[LAB4:[0-9]+]] = getelementptr inbounds i8, ptr @__profbm_test, i32 %[[LAB1]] _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
