-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DeadStoreElimination] Optimize tautological assignments #75744
Conversation
@llvm/pr-subscribers-llvm-transforms Author: Shreyansh Chouhan (BK1603) ChangesIf 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 Needed help with two things:
cc @nikic for review Full diff: https://github.com/llvm/llvm-project/pull/75744.diff 1 Files Affected:
diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
index dd0a290252dae3..0455fa1770e50a 100644
--- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
@@ -1926,6 +1926,36 @@ struct DSEState {
if (InitC && InitC == StoredConstant)
return MSSA.isLiveOnEntryDef(
MSSA.getSkipSelfWalker()->getClobberingMemoryAccess(Def, BatchAA));
+
+ // If there is a dominating condition, that ensures that the value
+ // being stored in a memory location is already present at the
+ // memory location, the store is a noop.
+ BasicBlock *StoreBB = DefI->getParent();
+ auto *StorePtr = Store->getOperand(1);
+
+ DomTreeNode *IDom = DT.getNode(StoreBB)->getIDom();
+ auto *TI = IDom->getBlock()->getTerminator();
+ ICmpInst::Predicate Pred;
+ BasicBlock *TrueBB, *FalseBB;
+
+ if (!match(TI, m_Br(m_ICmp(Pred, m_Load(m_Specific(StorePtr)),
+ m_Specific(StoredConstant)),
+ TrueBB, FalseBB)))
+ return false;
+
+ MemoryAccess *LastMod =
+ MSSA.getSkipSelfWalker()->getClobberingMemoryAccess(Def, BatchAA);
+ DomTreeNode *CDom = DT.getNode(LastMod->getBlock());
+ if (!DT.dominates(CDom, IDom))
+ return false;
+
+ if (Pred == ICmpInst::ICMP_EQ && StoreBB == TrueBB)
+ return true;
+
+ if (Pred == ICmpInst::ICMP_NE && StoreBB == FalseBB)
+ return true;
+
+ return false;
}
if (!Store)
|
At a guess, it crashes because IDom can be nullptr (e.g. a store in the entry block will not have an idom). |
8bc635a
to
f9eed0d
Compare
@nikic, you were right, I ran this under gdb and it seems that I've fixed the patch and added the test case as well. Please review. Thanks |
e464dc0
to
db3710d
Compare
Ping |
ad7578e
to
bfe0692
Compare
It looks like this patch introduces or exposes a miscompile in clang. There are crashes in stage2 binaries: http://llvm-compile-time-tracker.com/show_error.php?commit=0a5d24448bdf49ec6d7bc37bd8fe40203659b065 |
c2c6835
to
3427de7
Compare
Hi @nikic, I am able to build target stage2 locally without any issues after the latest push.
I'm not sure how the job is triggered for remote builds, can you please retrigger them with the latest push? |
Just tried again, and there are still crashes. To clarify though, stage2 itself does build successfully, but when you try to build https://github.com/llvm/llvm-test-suite using this stage2 it crashes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code looks correct to me.
a764d59
to
23d953a
Compare
Hi @nikic, might have to retrigger the build for it to pass. It failed while fetching the commit.
Can replicate this locally. I'm investigating. |
// Check if there is a dominating condition, that implies that the value | ||
// being stored in a ptr is already present in the ptr. | ||
bool dominatingConditionImpliesValue(MemoryDef *Def) { | ||
auto *StoreI = dyn_cast<StoreInst>(Def->getMemoryInst()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens when dyn_cast returns nullptr?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should only reach this function if the store is valid (we check for Store
before calling this)
bool dominatingConditionImpliesValue(MemoryDef *Def) { | ||
auto *StoreI = dyn_cast<StoreInst>(Def->getMemoryInst()); | ||
BasicBlock *StoreBB = StoreI->getParent(); | ||
Value *StorePtr = StoreI->getPointerOperand(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: We don't need StorePtr and StoreVal until later, so we might move these down.
@@ -1931,6 +1976,9 @@ struct DSEState { | |||
if (!Store) | |||
return false; | |||
|
|||
if (dominatingConditionImpliesValue(Def)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should pass the Store
instruction here to avoid confusion in the callee. That will also remove a dyn_cast you have there.
Just an update, still looking into this (I only get time for this during weekends.) The crash is happening during the RegAllocGreedy pass. Specifically when we call
Instead of getting the actual pointer to the cache entry, we are getting the index of the entry. This later causes a segfault when we try to call |
There are two issues with the code.
@nikic What are your thoughts on the optimisation happening in 1? Is it expected? Any ideas as to why I am unable to reproduce it using the following test case (in
cc @hiraditya |
Duh, sorry for missing that. What you want to do is replace checks like
I applied your patch and tried that example, and the store does get (incorrectly) optimized away for me. |
23d953a
to
dda966e
Compare
I have updated the commit with a fix and a new test case for checking 2
This isn't correct, I was confused by The latest commit should solve stage 2 bin crashes. (I tried building stage 3 locally, and was able to get to the link step, without any crashes during compilation. But I cannot link the generated binaries due to memory constraints on my laptop.) |
Please also update the PR description. |
ddb2b7d
to
a7cae25
Compare
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 llvm#63419
a7cae25
to
39eb0a4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
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