mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-05 01:20:51 +03:00
Add -cov-increment option to specify the type of increment instruction. Add atomic, non-atomic, and boolean increment types. (#3724)
This commit is contained in:
parent
217e0b9c44
commit
f9147a6f62
4 changed files with 104 additions and 7 deletions
|
@ -10,6 +10,7 @@
|
|||
#include "gen/coverage.h"
|
||||
|
||||
#include "dmd/module.h"
|
||||
#include "driver/cl_options.h"
|
||||
#include "gen/irstate.h"
|
||||
#include "gen/logger.h"
|
||||
|
||||
|
@ -30,21 +31,52 @@ void emitCoverageLinecountInc(const Loc &loc) {
|
|||
IF_LOG Logger::println("Coverage: increment _d_cover_data[%d]", line);
|
||||
LOG_SCOPE;
|
||||
|
||||
// Get GEP into _d_cover_data array
|
||||
// Increment the line counter:
|
||||
// Get GEP into _d_cover_data array...
|
||||
LLConstant *idxs[] = {DtoConstUint(0), DtoConstUint(line)};
|
||||
LLValue *ptr = llvm::ConstantExpr::getGetElementPtr(
|
||||
LLArrayType::get(LLType::getInt32Ty(gIR->context()), m->numlines),
|
||||
m->d_cover_data, idxs, true);
|
||||
// ...and generate the "increment" instruction(s)
|
||||
switch (opts::coverageIncrement) {
|
||||
case opts::CoverageIncrement::_default: // fallthrough
|
||||
case opts::CoverageIncrement::atomic:
|
||||
// Do an atomic increment, so this works when multiple threads are executed.
|
||||
gIR->ir->CreateAtomicRMW(llvm::AtomicRMWInst::Add, ptr, DtoConstUint(1),
|
||||
llvm::AtomicOrdering::Monotonic);
|
||||
break;
|
||||
case opts::CoverageIncrement::nonatomic: {
|
||||
// Do a non-atomic increment, user is responsible for correct results with
|
||||
// multithreaded execution
|
||||
llvm::LoadInst *load = gIR->ir->CreateAlignedLoad(ptr, LLAlign(4));
|
||||
llvm::StoreInst *store = gIR->ir->CreateAlignedStore(
|
||||
gIR->ir->CreateAdd(load, DtoConstUint(1)), ptr, LLAlign(4));
|
||||
// add !nontemporal attribute, to inform the optimizer that caching is not
|
||||
// needed
|
||||
llvm::MDNode *node = llvm::MDNode::get(
|
||||
gIR->context(), llvm::ConstantAsMetadata::get(DtoConstInt(1)));
|
||||
load->setMetadata("nontemporal", node);
|
||||
store->setMetadata("nontemporal", node);
|
||||
break;
|
||||
}
|
||||
case opts::CoverageIncrement::boolean: {
|
||||
// Do a boolean set, avoiding a memory read (blocking) and threading issues
|
||||
// at the cost of not "counting"
|
||||
llvm::StoreInst *store =
|
||||
gIR->ir->CreateAlignedStore(DtoConstUint(1), ptr, LLAlign(4));
|
||||
// add !nontemporal attribute, to inform the optimizer that caching is not
|
||||
// needed
|
||||
llvm::MDNode *node = llvm::MDNode::get(
|
||||
gIR->context(), llvm::ConstantAsMetadata::get(DtoConstInt(1)));
|
||||
store->setMetadata("nontemporal", node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Do an atomic increment, so this works when multiple threads are executed.
|
||||
gIR->ir->CreateAtomicRMW(llvm::AtomicRMWInst::Add, ptr, DtoConstUint(1),
|
||||
llvm::AtomicOrdering::Monotonic);
|
||||
|
||||
// Set the 'counter valid' bit to 1 for this line of code
|
||||
unsigned num_sizet_bits = gDataLayout->getTypeSizeInBits(DtoSize_t());
|
||||
unsigned idx = line / num_sizet_bits;
|
||||
unsigned bitidx = line % num_sizet_bits;
|
||||
|
||||
IF_LOG Logger::println("_d_cover_valid[%d] |= (1 << %d)", idx, bitidx);
|
||||
|
||||
m->d_cover_valid_init[idx] |= (size_t(1) << bitidx);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue