-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Miscompilation with libstdc++'s std::optional<int> and -O1 #98753
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
Comments
Reproducer: https://alive2.llvm.org/ce/z/p4ZGxe
cc @nikic |
A bit simpler using just instsimplify: https://alive2.llvm.org/ce/z/tnkf6A |
I expect the fix here is to perform replacements with |
The final case in Simplify (where Res == Absorber and the predicate is inverted) is not generally safe when the simplification is a refinement. In particular, we may simplify assuming a specific value for undef, but then chose a different one later. However, it *is* safe to refine poison in this context, unlike in the equivalent select folds. This is the reason why this fold did not use AllowRefinement=false in the first place, and using that option would introduce a lot of test regressions. This patch takes the middle path of disabling undef refinements in particular using the getWithoutUndef() SimplifyQuery option. However, this option doesn't actually work in this case, because the problematic fold is inside constant folding, and we currently don't propagate this option all the way from InstSimplify over ConstantFolding to ConstantFold. Work around this by explicitly checking for undef operands in simplifyWithOpReplaced(). Finally, make sure that places where AllowRefinement=false also use Q.getWithoutUndef(). I don't have a specific test case for this (the original one does not work because we don't simplify selects with constant condition in this mode in the first place) but this seems like the correct thing to do to be conservative. Fixes llvm#98753.
) The final case in Simplify (where Res == Absorber and the predicate is inverted) is not generally safe when the simplification is a refinement. In particular, we may simplify assuming a specific value for undef, but then chose a different one later. However, it *is* safe to refine poison in this context, unlike in the equivalent select folds. This is the reason why this fold did not use AllowRefinement=false in the first place, and using that option would introduce a lot of test regressions. This patch takes the middle path of disabling undef refinements in particular using the getWithoutUndef() SimplifyQuery option. However, this option doesn't actually work in this case, because the problematic fold is inside constant folding, and we currently don't propagate this option all the way from InstSimplify over ConstantFolding to ConstantFold. Work around this by explicitly checking for undef operands in simplifyWithOpReplaced(). Finally, make sure that places where AllowRefinement=false also use Q.getWithoutUndef(). I don't have a specific test case for this (the original one does not work because we don't simplify selects with constant condition in this mode in the first place) but this seems like the correct thing to do to be conservative. Fixes #98753.
Thanks a lot for fixing this so quickly! I wonder if this should be included in 18.1.9? |
The LLVM 18 branch is already closed, there will be no further releases. |
I'll add the milestone anyway as it's easier to track for downstream backports then. |
) Summary: The final case in Simplify (where Res == Absorber and the predicate is inverted) is not generally safe when the simplification is a refinement. In particular, we may simplify assuming a specific value for undef, but then chose a different one later. However, it *is* safe to refine poison in this context, unlike in the equivalent select folds. This is the reason why this fold did not use AllowRefinement=false in the first place, and using that option would introduce a lot of test regressions. This patch takes the middle path of disabling undef refinements in particular using the getWithoutUndef() SimplifyQuery option. However, this option doesn't actually work in this case, because the problematic fold is inside constant folding, and we currently don't propagate this option all the way from InstSimplify over ConstantFolding to ConstantFold. Work around this by explicitly checking for undef operands in simplifyWithOpReplaced(). Finally, make sure that places where AllowRefinement=false also use Q.getWithoutUndef(). I don't have a specific test case for this (the original one does not work because we don't simplify selects with constant condition in this mode in the first place) but this seems like the correct thing to do to be conservative. Fixes #98753. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60251555
Uh oh!
There was an error while loading. Please reload this page.
https://godbolt.org/z/KjEreWf57
With Clang 18.1 and libstdc++, we get different behavior when compared to Clang 17 in the code below.
EDIT: requires at least -O1.
With Clang 17, we get
SHOULD BE PRINTED
, while with with Clang 18.1 we getSHOULD NOT BE PRINTED: *opt = 5
.With git-bisect, I found that this is caused by 060de41.
An isomorphic example to reproduce this (https://godbolt.org/z/9PsjY17sT):
Note in the generated LLVM IR that
was reduced to only
The text was updated successfully, but these errors were encountered: