Skip to content

Commit ddb2b7d

Browse files
committed
[DeadStoreElimination] Optimize tautological assignments
If a store is immediately 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 0871c4b commit ddb2b7d

File tree

2 files changed

+420
-0
lines changed

2 files changed

+420
-0
lines changed

llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1901,6 +1901,58 @@ struct DSEState {
19011901
return true;
19021902
}
19031903

1904+
// Check if there is a dominating condition, that implies that the value
1905+
// being stored in a ptr is already present in the ptr.
1906+
bool dominatingConditionImpliesValue(MemoryDef *Def) {
1907+
auto *StoreI = dyn_cast<StoreInst>(Def->getMemoryInst());
1908+
BasicBlock *StoreBB = StoreI->getParent();
1909+
Value *StorePtr = StoreI->getPointerOperand();
1910+
Value *StoreVal = StoreI->getValueOperand();
1911+
1912+
DomTreeNode *IDom = DT.getNode(StoreBB)->getIDom();
1913+
if (!IDom)
1914+
return false;
1915+
1916+
auto *BI = dyn_cast<BranchInst>(IDom->getBlock()->getTerminator());
1917+
if (!BI || !BI->isConditional())
1918+
return false;
1919+
1920+
// In case both blocks are the same, it is not possible to determine
1921+
// if optimization is possible. (We would not want to optimize a store
1922+
// in the FalseBB if condition is true and vice versa.)
1923+
if (BI->getSuccessor(0) == BI->getSuccessor(1))
1924+
return false;
1925+
1926+
// In case the else blocks also branches to the if block or the other way
1927+
// around it is not possible to determine if the optimization is possible.
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+
if (Pred == ICmpInst::ICMP_EQ &&
1940+
!DT.dominates(BasicBlockEdge(BI->getParent(), BI->getSuccessor(0)),
1941+
StoreBB))
1942+
return false;
1943+
1944+
if (Pred == ICmpInst::ICMP_NE &&
1945+
!DT.dominates(BasicBlockEdge(BI->getParent(), BI->getSuccessor(1)),
1946+
StoreBB))
1947+
return false;
1948+
1949+
MemoryAccess *LoadAcc = MSSA.getMemoryAccess(ICmpL);
1950+
MemoryAccess *ClobAcc =
1951+
MSSA.getSkipSelfWalker()->getClobberingMemoryAccess(Def, BatchAA);
1952+
1953+
return MSSA.dominates(ClobAcc, LoadAcc);
1954+
}
1955+
19041956
/// \returns true if \p Def is a no-op store, either because it
19051957
/// directly stores back a loaded value or stores zero to a calloced object.
19061958
bool storeIsNoop(MemoryDef *Def, const Value *DefUO) {
@@ -1931,6 +1983,9 @@ struct DSEState {
19311983
if (!Store)
19321984
return false;
19331985

1986+
if (dominatingConditionImpliesValue(Def))
1987+
return true;
1988+
19341989
if (auto *LoadI = dyn_cast<LoadInst>(Store->getOperand(0))) {
19351990
if (LoadI->getPointerOperand() == Store->getOperand(1)) {
19361991
// Get the defining access for the load.

0 commit comments

Comments
 (0)