-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
[SelectionDAG] Do not build illegal nodes with users #108573
Conversation
@llvm/pr-subscribers-llvm-selectiondag Author: None (ErikHogeman) ChangesWhen we build a node with illegal type which has a user, it's possible that it can end up being processed by the DAG combiner later before it's removed, which can trigger an assert expecting the types to be legalized already. Full diff: https://github.com/llvm/llvm-project/pull/108573.diff 1 Files Affected:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 29505f444b7650..44ec6f7cab145a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6799,14 +6799,17 @@ SDValue SelectionDAG::FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL,
// Constant fold the scalar operands.
SDValue ScalarResult = getNode(Opcode, DL, SVT, ScalarOps, Flags);
- // Legalize the (integer) scalar constant if necessary.
- if (LegalSVT != SVT)
- ScalarResult = getNode(ExtendCode, DL, LegalSVT, ScalarResult);
-
// Scalar folding only succeeded if the result is a constant or UNDEF.
if (!ScalarResult.isUndef() && ScalarResult.getOpcode() != ISD::Constant &&
ScalarResult.getOpcode() != ISD::ConstantFP)
return SDValue();
+
+ // Legalize the (integer) scalar constant if necessary. We only do
+ // this once we know the folding succeeded, since otherwise we would
+ // get a node with illegal type which has a user.
+ if (LegalSVT != SVT)
+ ScalarResult = getNode(ExtendCode, DL, LegalSVT, ScalarResult);
+
ScalarResults.push_back(ScalarResult);
}
|
Hi, this code is triggering some asserts in our downstream target. I have tried to reproduce it with a test that can run on an upstream target, but it has been very difficult. What happens is basically this:
The tricky part here is to get another node optimized after the i1 node is created, to trigger it to get inserted into the worklist again before it gets removed later. I have some IR where this happens on our downstream target, but I haven't managed to create IR that makes this happen on an upstream target. So at this point, I only have a code change, no test. I realize that is not ideal, but I still thought I should open this request to see what opinion people have about it. I'm also happy to give it another try to write a test, if someone has a good idea of anything I can try. |
I managed to simplify our case down to this:
Running selection on this for x86_64 target, it will create the illegal i1 node. However, it happens during DAG combining just after type legalization, but the DAG combiner will only run LegalizeOp if it's AfterLegalizeDAG, and on top of that the illegal node is not added to the worklist again anyway since I didn't get other optimizations to trigger in such a way that this happens, so this prevents me from reproducing it. It's tricky since there's no way (at least I'm aware of?) to write selection DAG IR manually and run specific passes or transforms on it. If there's any feedback about what I could try with the IR for an upstream target, or whether or not the change itself would be OK without a test, please let me know. |
@bogner , I believe you are listed as the code owner of the SelectionDAG part of LLVM. If/when you have time, could you help me add the relevant people to review this change? |
@ErikHogeman That IR is building OK for me - what are your command args? Can you repro it in godbolt? |
Hi, apologies if I wasn't clear in the comments, I have not been able to reproduce it on an upstream target. This IR was the closest I got since it builds the invalid node, but as I wrote it happens too early (needs to happen after LegalizeDAG), plus another optimization needs to insert the illegal node back to the DAG combiner worklist before it gets removed later. I tried to explain what happens in my first comment, so I have been trying to write something that triggers those same steps in an upstream target. EDIT: These nodes are built after type legalization, inside 'FoldConstantArithmetic':
In our downstream target, t96 is then further inserted into the DAG combiner worklist, and when it runs 'LegalizeOp' this asserts because the type is illegal. |
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 by inspection
When we build a node with illegal type which has a user, it's possible that it can end up being processed by the DAG combiner later before it's removed, which can trigger an assert expecting the types to be legalized already.
e632028
to
a2bda4b
Compare
Thanks! |
Should this be backported to 19.x? |
Given that the only report is for a out of tree target (that can maintain their own minimal local changes in a branch) I don't think this is necessary. |
Agreed. |
When we build a node with illegal type which has a user, it's possible that it can end up being processed by the DAG combiner later before it's removed, which can trigger an assert expecting the types to be legalized already.