Skip to content

Commit 65b5647

Browse files
authored
[DeadStoreElimination] Optimize tautological assignments (#75744)
If a store is dominated by a condition that ensures that the value being stored in a memory location is already present at that memory location, consider the store a noop. Fixes #63419
1 parent cb8f910 commit 65b5647

File tree

2 files changed

+411
-0
lines changed

2 files changed

+411
-0
lines changed

llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1904,6 +1904,57 @@ struct DSEState {
19041904
return true;
19051905
}
19061906

1907+
// Check if there is a dominating condition, that implies that the value
1908+
// being stored in a ptr is already present in the ptr.
1909+
bool dominatingConditionImpliesValue(MemoryDef *Def) {
1910+
auto *StoreI = cast<StoreInst>(Def->getMemoryInst());
1911+
BasicBlock *StoreBB = StoreI->getParent();
1912+
Value *StorePtr = StoreI->getPointerOperand();
1913+
Value *StoreVal = StoreI->getValueOperand();
1914+
1915+
DomTreeNode *IDom = DT.getNode(StoreBB)->getIDom();
1916+
if (!IDom)
1917+
return false;
1918+
1919+
auto *BI = dyn_cast<BranchInst>(IDom->getBlock()->getTerminator());
1920+
if (!BI || !BI->isConditional())
1921+
return false;
1922+
1923+
// In case both blocks are the same, it is not possible to determine
1924+
// if optimization is possible. (We would not want to optimize a store
1925+
// in the FalseBB if condition is true and vice versa.)
1926+
if (BI->getSuccessor(0) == BI->getSuccessor(1))
1927+
return false;
1928+
1929+
Instruction *ICmpL;
1930+
ICmpInst::Predicate Pred;
1931+
if (!match(BI->getCondition(),
1932+
m_c_ICmp(Pred,
1933+
m_CombineAnd(m_Load(m_Specific(StorePtr)),
1934+
m_Instruction(ICmpL)),
1935+
m_Specific(StoreVal))) ||
1936+
!ICmpInst::isEquality(Pred))
1937+
return false;
1938+
1939+
// In case the else blocks also branches to the if block or the other way
1940+
// around it is not possible to determine if the optimization is possible.
1941+
if (Pred == ICmpInst::ICMP_EQ &&
1942+
!DT.dominates(BasicBlockEdge(BI->getParent(), BI->getSuccessor(0)),
1943+
StoreBB))
1944+
return false;
1945+
1946+
if (Pred == ICmpInst::ICMP_NE &&
1947+
!DT.dominates(BasicBlockEdge(BI->getParent(), BI->getSuccessor(1)),
1948+
StoreBB))
1949+
return false;
1950+
1951+
MemoryAccess *LoadAcc = MSSA.getMemoryAccess(ICmpL);
1952+
MemoryAccess *ClobAcc =
1953+
MSSA.getSkipSelfWalker()->getClobberingMemoryAccess(Def, BatchAA);
1954+
1955+
return MSSA.dominates(ClobAcc, LoadAcc);
1956+
}
1957+
19071958
/// \returns true if \p Def is a no-op store, either because it
19081959
/// directly stores back a loaded value or stores zero to a calloced object.
19091960
bool storeIsNoop(MemoryDef *Def, const Value *DefUO) {
@@ -1934,6 +1985,9 @@ struct DSEState {
19341985
if (!Store)
19351986
return false;
19361987

1988+
if (dominatingConditionImpliesValue(Def))
1989+
return true;
1990+
19371991
if (auto *LoadI = dyn_cast<LoadInst>(Store->getOperand(0))) {
19381992
if (LoadI->getPointerOperand() == Store->getOperand(1)) {
19391993
// Get the defining access for the load.

0 commit comments

Comments
 (0)