forked from OSchip/llvm-project
[DSE] Hoist partial store merging code into function (NFC).
Hoist the general logic into a new function, because it can be re-used by the MemorySSA backed DSE as well.
This commit is contained in:
parent
1ac8451a9b
commit
71a91b9837
|
@ -1150,6 +1150,52 @@ static bool eliminateNoopStore(Instruction *Inst, BasicBlock::iterator &BBI,
|
|||
return false;
|
||||
}
|
||||
|
||||
static Constant *
|
||||
tryToMergePartialOverlappingStores(StoreInst *Earlier, StoreInst *Later,
|
||||
int64_t InstWriteOffset,
|
||||
int64_t DepWriteOffset, const DataLayout &DL,
|
||||
AliasAnalysis *AA, DominatorTree *DT) {
|
||||
|
||||
if (Earlier && isa<ConstantInt>(Earlier->getValueOperand()) &&
|
||||
DL.typeSizeEqualsStoreSize(Earlier->getValueOperand()->getType()) &&
|
||||
Later && isa<ConstantInt>(Later->getValueOperand()) &&
|
||||
DL.typeSizeEqualsStoreSize(Later->getValueOperand()->getType()) &&
|
||||
memoryIsNotModifiedBetween(Earlier, Later, AA, DL, DT)) {
|
||||
// If the store we find is:
|
||||
// a) partially overwritten by the store to 'Loc'
|
||||
// b) the later store is fully contained in the earlier one and
|
||||
// c) they both have a constant value
|
||||
// d) none of the two stores need padding
|
||||
// Merge the two stores, replacing the earlier store's value with a
|
||||
// merge of both values.
|
||||
// TODO: Deal with other constant types (vectors, etc), and probably
|
||||
// some mem intrinsics (if needed)
|
||||
|
||||
APInt EarlierValue =
|
||||
cast<ConstantInt>(Earlier->getValueOperand())->getValue();
|
||||
APInt LaterValue = cast<ConstantInt>(Later->getValueOperand())->getValue();
|
||||
unsigned LaterBits = LaterValue.getBitWidth();
|
||||
assert(EarlierValue.getBitWidth() > LaterValue.getBitWidth());
|
||||
LaterValue = LaterValue.zext(EarlierValue.getBitWidth());
|
||||
|
||||
// Offset of the smaller store inside the larger store
|
||||
unsigned BitOffsetDiff = (InstWriteOffset - DepWriteOffset) * 8;
|
||||
unsigned LShiftAmount = DL.isBigEndian() ? EarlierValue.getBitWidth() -
|
||||
BitOffsetDiff - LaterBits
|
||||
: BitOffsetDiff;
|
||||
APInt Mask = APInt::getBitsSet(EarlierValue.getBitWidth(), LShiftAmount,
|
||||
LShiftAmount + LaterBits);
|
||||
// Clear the bits we'll be replacing, then OR with the smaller
|
||||
// store, shifted appropriately.
|
||||
APInt Merged = (EarlierValue & ~Mask) | (LaterValue << LShiftAmount);
|
||||
LLVM_DEBUG(dbgs() << "DSE: Merge Stores:\n Earlier: " << *Earlier
|
||||
<< "\n Later: " << *Later
|
||||
<< "\n Merged Value: " << Merged << '\n');
|
||||
return ConstantInt::get(Earlier->getValueOperand()->getType(), Merged);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA,
|
||||
MemoryDependenceResults *MD, DominatorTree *DT,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
|
@ -1297,51 +1343,11 @@ static bool eliminateDeadStores(BasicBlock &BB, AliasAnalysis *AA,
|
|||
OR == OW_PartialEarlierWithFullLater) {
|
||||
auto *Earlier = dyn_cast<StoreInst>(DepWrite);
|
||||
auto *Later = dyn_cast<StoreInst>(Inst);
|
||||
if (Earlier && isa<ConstantInt>(Earlier->getValueOperand()) &&
|
||||
DL.typeSizeEqualsStoreSize(
|
||||
Earlier->getValueOperand()->getType()) &&
|
||||
Later && isa<ConstantInt>(Later->getValueOperand()) &&
|
||||
DL.typeSizeEqualsStoreSize(
|
||||
Later->getValueOperand()->getType()) &&
|
||||
memoryIsNotModifiedBetween(Earlier, Later, AA, DL, DT)) {
|
||||
// If the store we find is:
|
||||
// a) partially overwritten by the store to 'Loc'
|
||||
// b) the later store is fully contained in the earlier one and
|
||||
// c) they both have a constant value
|
||||
// d) none of the two stores need padding
|
||||
// Merge the two stores, replacing the earlier store's value with a
|
||||
// merge of both values.
|
||||
// TODO: Deal with other constant types (vectors, etc), and probably
|
||||
// some mem intrinsics (if needed)
|
||||
|
||||
APInt EarlierValue =
|
||||
cast<ConstantInt>(Earlier->getValueOperand())->getValue();
|
||||
APInt LaterValue =
|
||||
cast<ConstantInt>(Later->getValueOperand())->getValue();
|
||||
unsigned LaterBits = LaterValue.getBitWidth();
|
||||
assert(EarlierValue.getBitWidth() > LaterValue.getBitWidth());
|
||||
LaterValue = LaterValue.zext(EarlierValue.getBitWidth());
|
||||
|
||||
// Offset of the smaller store inside the larger store
|
||||
unsigned BitOffsetDiff = (InstWriteOffset - DepWriteOffset) * 8;
|
||||
unsigned LShiftAmount =
|
||||
DL.isBigEndian()
|
||||
? EarlierValue.getBitWidth() - BitOffsetDiff - LaterBits
|
||||
: BitOffsetDiff;
|
||||
APInt Mask =
|
||||
APInt::getBitsSet(EarlierValue.getBitWidth(), LShiftAmount,
|
||||
LShiftAmount + LaterBits);
|
||||
// Clear the bits we'll be replacing, then OR with the smaller
|
||||
// store, shifted appropriately.
|
||||
APInt Merged =
|
||||
(EarlierValue & ~Mask) | (LaterValue << LShiftAmount);
|
||||
LLVM_DEBUG(dbgs() << "DSE: Merge Stores:\n Earlier: " << *DepWrite
|
||||
<< "\n Later: " << *Inst
|
||||
<< "\n Merged Value: " << Merged << '\n');
|
||||
|
||||
if (Constant *C = tryToMergePartialOverlappingStores(
|
||||
Earlier, Later, InstWriteOffset, DepWriteOffset, DL, AA,
|
||||
DT)) {
|
||||
auto *SI = new StoreInst(
|
||||
ConstantInt::get(Earlier->getValueOperand()->getType(), Merged),
|
||||
Earlier->getPointerOperand(), false, Earlier->getAlign(),
|
||||
C, Earlier->getPointerOperand(), false, Earlier->getAlign(),
|
||||
Earlier->getOrdering(), Earlier->getSyncScopeID(), DepWrite);
|
||||
|
||||
unsigned MDToKeep[] = {LLVMContext::MD_dbg, LLVMContext::MD_tbaa,
|
||||
|
|
Loading…
Reference in New Issue