Skip to content

Commit 4329a31

Browse files
author
zhuyunxing
committed
coverage. Adapt to llvm optimization for conditions limits
1 parent 83e4720 commit 4329a31

File tree

19 files changed

+329
-365
lines changed

19 files changed

+329
-365
lines changed

compiler/rustc_codegen_llvm/src/builder.rs

+13-50
Original file line numberDiff line numberDiff line change
@@ -1751,9 +1751,9 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17511751
&mut self,
17521752
fn_name: &'ll Value,
17531753
hash: &'ll Value,
1754-
bitmap_bytes: &'ll Value,
1754+
bitmap_bits: &'ll Value,
17551755
) {
1756-
debug!("mcdc_parameters() with args ({:?}, {:?}, {:?})", fn_name, hash, bitmap_bytes);
1756+
debug!("mcdc_parameters() with args ({:?}, {:?}, {:?})", fn_name, hash, bitmap_bits);
17571757

17581758
assert!(llvm_util::get_version() >= (19, 0, 0), "MCDC intrinsics require LLVM 19 or later");
17591759

@@ -1762,7 +1762,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17621762
&[self.cx.type_ptr(), self.cx.type_i64(), self.cx.type_i32()],
17631763
self.cx.type_void(),
17641764
);
1765-
let args = &[fn_name, hash, bitmap_bytes];
1765+
let args = &[fn_name, hash, bitmap_bits];
17661766
let args = self.check_call("call", llty, llfn, args);
17671767

17681768
unsafe {
@@ -1782,29 +1782,22 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
17821782
&mut self,
17831783
fn_name: &'ll Value,
17841784
hash: &'ll Value,
1785-
bitmap_bytes: &'ll Value,
17861785
bitmap_index: &'ll Value,
17871786
mcdc_temp: &'ll Value,
17881787
) {
17891788
debug!(
1790-
"mcdc_tvbitmap_update() with args ({:?}, {:?}, {:?}, {:?}, {:?})",
1791-
fn_name, hash, bitmap_bytes, bitmap_index, mcdc_temp
1789+
"mcdc_tvbitmap_update() with args ({:?}, {:?}, {:?}, {:?})",
1790+
fn_name, hash, bitmap_index, mcdc_temp
17921791
);
17931792
assert!(llvm_util::get_version() >= (19, 0, 0), "MCDC intrinsics require LLVM 19 or later");
17941793

17951794
let llfn =
17961795
unsafe { llvm::LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(self.cx().llmod) };
17971796
let llty = self.cx.type_func(
1798-
&[
1799-
self.cx.type_ptr(),
1800-
self.cx.type_i64(),
1801-
self.cx.type_i32(),
1802-
self.cx.type_i32(),
1803-
self.cx.type_ptr(),
1804-
],
1797+
&[self.cx.type_ptr(), self.cx.type_i64(), self.cx.type_i32(), self.cx.type_ptr()],
18051798
self.cx.type_void(),
18061799
);
1807-
let args = &[fn_name, hash, bitmap_bytes, bitmap_index, mcdc_temp];
1800+
let args = &[fn_name, hash, bitmap_index, mcdc_temp];
18081801
let args = self.check_call("call", llty, llfn, args);
18091802
unsafe {
18101803
let _ = llvm::LLVMRustBuildCall(
@@ -1820,42 +1813,12 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
18201813
self.store(self.const_i32(0), mcdc_temp, self.tcx.data_layout.i32_align.abi);
18211814
}
18221815

1823-
pub(crate) fn mcdc_condbitmap_update(
1824-
&mut self,
1825-
fn_name: &'ll Value,
1826-
hash: &'ll Value,
1827-
cond_loc: &'ll Value,
1828-
mcdc_temp: &'ll Value,
1829-
bool_value: &'ll Value,
1830-
) {
1831-
debug!(
1832-
"mcdc_condbitmap_update() with args ({:?}, {:?}, {:?}, {:?}, {:?})",
1833-
fn_name, hash, cond_loc, mcdc_temp, bool_value
1834-
);
1816+
pub(crate) fn mcdc_condbitmap_update(&mut self, cond_index: &'ll Value, mcdc_temp: &'ll Value) {
1817+
debug!("mcdc_condbitmap_update() with args ({:?}, {:?})", cond_index, mcdc_temp);
18351818
assert!(llvm_util::get_version() >= (19, 0, 0), "MCDC intrinsics require LLVM 19 or later");
1836-
let llfn = unsafe { llvm::LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(self.cx().llmod) };
1837-
let llty = self.cx.type_func(
1838-
&[
1839-
self.cx.type_ptr(),
1840-
self.cx.type_i64(),
1841-
self.cx.type_i32(),
1842-
self.cx.type_ptr(),
1843-
self.cx.type_i1(),
1844-
],
1845-
self.cx.type_void(),
1846-
);
1847-
let args = &[fn_name, hash, cond_loc, mcdc_temp, bool_value];
1848-
self.check_call("call", llty, llfn, args);
1849-
unsafe {
1850-
let _ = llvm::LLVMRustBuildCall(
1851-
self.llbuilder,
1852-
llty,
1853-
llfn,
1854-
args.as_ptr() as *const &llvm::Value,
1855-
args.len() as c_uint,
1856-
[].as_ptr(),
1857-
0 as c_uint,
1858-
);
1859-
}
1819+
let align = self.tcx.data_layout.i32_align.abi;
1820+
let current_tv_index = self.load(self.cx.type_i32(), mcdc_temp, align);
1821+
let new_tv_index = self.add(current_tv_index, cond_index);
1822+
self.store(new_tv_index, mcdc_temp, align);
18601823
}
18611824
}

compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs

+11-18
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,14 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
9999
};
100100

101101
// If there are no MC/DC bitmaps to set up, return immediately.
102-
if function_coverage_info.mcdc_bitmap_bytes == 0 {
102+
if function_coverage_info.mcdc_bitmap_bits == 0 {
103103
return;
104104
}
105105

106106
let fn_name = self.get_pgo_func_name_var(instance);
107107
let hash = self.const_u64(function_coverage_info.function_source_hash);
108-
let bitmap_bytes = self.const_u32(function_coverage_info.mcdc_bitmap_bytes);
109-
self.mcdc_parameters(fn_name, hash, bitmap_bytes);
108+
let bitmap_bits = self.const_u32(function_coverage_info.mcdc_bitmap_bits as u32);
109+
self.mcdc_parameters(fn_name, hash, bitmap_bits);
110110

111111
// Create pointers named `mcdc.addr.{i}` to stack-allocated condition bitmaps.
112112
let mut cond_bitmaps = vec![];
@@ -186,35 +186,28 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
186186
CoverageKind::ExpressionUsed { id } => {
187187
func_coverage.mark_expression_id_seen(id);
188188
}
189-
CoverageKind::CondBitmapUpdate { id, value, decision_depth } => {
189+
CoverageKind::CondBitmapUpdate { index, decision_depth } => {
190190
drop(coverage_map);
191-
assert_ne!(
192-
id.as_u32(),
193-
0,
194-
"ConditionId of evaluated conditions should never be zero"
195-
);
196191
let cond_bitmap = coverage_context
197192
.try_get_mcdc_condition_bitmap(&instance, decision_depth)
198193
.expect("mcdc cond bitmap should have been allocated for updating");
199-
let cond_loc = bx.const_i32(id.as_u32() as i32 - 1);
200-
let bool_value = bx.const_bool(value);
201-
let fn_name = bx.get_pgo_func_name_var(instance);
202-
let hash = bx.const_u64(function_coverage_info.function_source_hash);
203-
bx.mcdc_condbitmap_update(fn_name, hash, cond_loc, cond_bitmap, bool_value);
194+
let cond_index = bx.const_i32(index as i32);
195+
bx.mcdc_condbitmap_update(cond_index, cond_bitmap);
204196
}
205197
CoverageKind::TestVectorBitmapUpdate { bitmap_idx, decision_depth } => {
206198
drop(coverage_map);
207199
let cond_bitmap = coverage_context
208200
.try_get_mcdc_condition_bitmap(&instance, decision_depth)
209201
.expect("mcdc cond bitmap should have been allocated for merging into the global bitmap");
210-
let bitmap_bytes = function_coverage_info.mcdc_bitmap_bytes;
211-
assert!(bitmap_idx < bitmap_bytes, "bitmap index of the decision out of range");
202+
assert!(
203+
bitmap_idx as usize <= function_coverage_info.mcdc_bitmap_bits,
204+
"bitmap index of the decision out of range"
205+
);
212206

213207
let fn_name = bx.get_pgo_func_name_var(instance);
214208
let hash = bx.const_u64(function_coverage_info.function_source_hash);
215-
let bitmap_bytes = bx.const_u32(bitmap_bytes);
216209
let bitmap_index = bx.const_u32(bitmap_idx);
217-
bx.mcdc_tvbitmap_update(fn_name, hash, bitmap_bytes, bitmap_index, cond_bitmap);
210+
bx.mcdc_tvbitmap_update(fn_name, hash, bitmap_index, cond_bitmap);
218211
}
219212
}
220213
}

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1640,7 +1640,6 @@ unsafe extern "C" {
16401640
pub fn LLVMRustGetInstrProfIncrementIntrinsic(M: &Module) -> &Value;
16411641
pub fn LLVMRustGetInstrProfMCDCParametersIntrinsic(M: &Module) -> &Value;
16421642
pub fn LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(M: &Module) -> &Value;
1643-
pub fn LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(M: &Module) -> &Value;
16441643

16451644
pub fn LLVMRustBuildCall<'a>(
16461645
B: &Builder<'a>,

compiler/rustc_middle/src/mir/coverage.rs

+5-11
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ pub enum CoverageKind {
128128

129129
/// Marks the point in MIR control flow represented by a evaluated condition.
130130
///
131-
/// This is eventually lowered to `llvm.instrprof.mcdc.condbitmap.update` in LLVM IR.
132-
CondBitmapUpdate { id: ConditionId, value: bool, decision_depth: u16 },
131+
/// This is eventually lowered to instruments updating mcdc temp variables.
132+
CondBitmapUpdate { index: u32, decision_depth: u16 },
133133

134134
/// Marks the point in MIR control flow represented by a evaluated decision.
135135
///
@@ -145,14 +145,8 @@ impl Debug for CoverageKind {
145145
BlockMarker { id } => write!(fmt, "BlockMarker({:?})", id.index()),
146146
CounterIncrement { id } => write!(fmt, "CounterIncrement({:?})", id.index()),
147147
ExpressionUsed { id } => write!(fmt, "ExpressionUsed({:?})", id.index()),
148-
CondBitmapUpdate { id, value, decision_depth } => {
149-
write!(
150-
fmt,
151-
"CondBitmapUpdate({:?}, {:?}, depth={:?})",
152-
id.index(),
153-
value,
154-
decision_depth
155-
)
148+
CondBitmapUpdate { index, decision_depth } => {
149+
write!(fmt, "CondBitmapUpdate(index={:?}, depth={:?})", index, decision_depth)
156150
}
157151
TestVectorBitmapUpdate { bitmap_idx, decision_depth } => {
158152
write!(fmt, "TestVectorUpdate({:?}, depth={:?})", bitmap_idx, decision_depth)
@@ -253,7 +247,7 @@ pub struct Mapping {
253247
pub struct FunctionCoverageInfo {
254248
pub function_source_hash: u64,
255249
pub num_counters: usize,
256-
pub mcdc_bitmap_bytes: u32,
250+
pub mcdc_bitmap_bits: usize,
257251
pub expressions: IndexVec<ExpressionId, Expression>,
258252
pub mappings: Vec<Mapping>,
259253
/// The depth of the deepest decision is used to know how many

compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@ use rustc_span::Span;
1212
use crate::build::Builder;
1313
use crate::errors::MCDCExceedsConditionLimit;
1414

15-
/// The MCDC bitmap scales exponentially (2^n) based on the number of conditions seen,
16-
/// So llvm sets a maximum value prevents the bitmap footprint from growing too large without the user's knowledge.
17-
/// This limit may be relaxed if the [upstream change](https://github.com/llvm/llvm-project/pull/82448) is merged.
18-
const MAX_CONDITIONS_IN_DECISION: usize = 6;
15+
/// LLVM uses `i16` to represent condition id. Hence `i16::MAX` is the hard limit for number of
16+
/// conditions in a decision.
17+
const MAX_CONDITIONS_IN_DECISION: usize = i16::MAX as usize;
1918

2019
#[derive(Default)]
2120
struct MCDCDecisionCtx {

0 commit comments

Comments
 (0)