A bug was found within InstCombineCasts where a function call
is only implemented to work with FixedVectors. This caused a
crash when a ScalableVector was passed to this function.
This commit introduces a regression test which recreates the
failure and a bug fix.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | ||
---|---|---|
1582 | This is not correct, because we can't iterate the number of elements in a vector of which we don't know how many elements there are. The choice here is to either:
| |
llvm/test/Transforms/InstCombine/instcombine-vectors.ll | ||
1 ↗ | (On Diff #329660) | nit: SVE is a feature of Armv8.2. Regardless, the specific architecture version isn't that relevant here. What is important is that it knows its target is aarch64 (e.g. -mtriple=aarch64-none-linux-gnu) and that the SVE attribute is enabled (-mattr=+sve). |
4 ↗ | (On Diff #329660) | Just checking the label is not sufficient. It is good practice to check the output and make sure the output from the RUN line is sensible. In this case, I would expect InstCombine to optimize the operation in some way, but I can't see if that has happened without the added CHECK lines. |
Hey Nash,
I also added some comments.
I hope it is ok.
Carol
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | ||
---|---|---|
1598 | Just in case, I don't think that you should cast this to be ScalableVectorType. | |
llvm/test/Transforms/InstCombine/instcombine-vectors.ll | ||
2 ↗ | (On Diff #329660) | Usually we also add this line in our tests: ; If this check fails please read test/CodeGen/AArch64/README for instructions on how to resolve it.$ And I believe this test should be in inside test/Transforms/InstCombine/AArch64 |
Response to Carol and Sander's comments. I have gone for an
approach which implements an optimisation for the case
where we have a trunc op of the following form
fptrunc (OpI (fpextend v) (fpextend u))
and in the case where one or both of u and v
are scalable splat vectors, we truncate to the lowest
common FP width which maintains precision. I have also
implemented a test which showcases this optimisation.
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | ||
---|---|---|
1602 | Hi @nasherm, is it possible to just add code to this function that does something like this? if (auto *CV = dyn_cast<Constant>(V)) if (auto *FPExt = dyn_cast<FPExtInst>(CV->getOperand(0))) return FPExt->getOperand(0)->getType(); Then in shrinkFPConstantVector you could just bail out early on for scalable vectors? Does that give you the same effect? |
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | ||
---|---|---|
1602 | That doesn't work as the the second dyn_cast will fail. It seems like FPExt within a Constant can't be cast in that way. |
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | ||
---|---|---|
1605 | I think the reason it gets to shrinkFPConstant is because the above dyn_cast<FPExtInst> returns false, even though V is a fpext constant expression. If you add: + if (auto *FPCExt = dyn_cast<ConstantExpr>(V)) + if (FPCExt->getOpcode() == Instruction::FPExt) + return FPCExt->getOperand(0)->getType(); Then your test will pass. The problem is quite specific to scalable vector splat-operations which cannot constant fold into something simpler, thus leading to a ConstantExpression. I'm not entirely sure if we should duplicate such code for ConstantExprs. In this case it seems like a pretty trivial fix that isn't that much more complicated than bailing out for scalable vectors, so perhaps this is fine, but it does seem a bit arbitrary. Personally I would be happy to go either way, either the proposed solution or bailing out and avoiding this improvement until we hit this as something that needs fixing. |
In response to Sander and David's approach, I have
refactored the solution to use the simpler check
for splat vectors i.e. checking with constant
fpext expressions
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | ||
---|---|---|
1572 | If you change VectorType to FixedVectorType here, it will automatically bail out on line 1573, and then you can undo the remaining changes in this function. |
Addressed Sander's comment on casting to FixedVectorType as well
as Carol's suggestion for regression test.
LGTM! Hi @nasherm, thanks for addressing all the review comments! I just have a few minor nits.
Perhaps it's worth renaming the test file from sve-splat.ll to something like 'sve-const-fp-splat.ll'? The reason being that sve-splat.ll is quite generic and could apply to many operations in different situations, including splats of non-constant values.
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | ||
---|---|---|
1580 | nit: I think it's probably better to use the same terminology as used elsewhere in this function, i.e. minimal type? | |
1614 | nit: I think it's probably sufficient just to say something like: // We can only correctly find a minimum type for a scalable vector when it is a splat. // For splats of constant values the fpext is wrapped up as a ConstantExpr. |
llvm/test/Transforms/InstCombine/AArch64/sve-splat.ll | ||
---|---|---|
1 ↗ | (On Diff #331880) | Do you really need anything other than plain -instcombine here? |
llvm/test/Transforms/InstCombine/AArch64/sve-splat.ll | ||
---|---|---|
1 ↗ | (On Diff #331880) | No, in practice there's no need. I added the triple and attributes to be in-line with the rest of the AArch64 tests. |
llvm/test/Transforms/InstCombine/AArch64/sve-splat.ll | ||
---|---|---|
1 ↗ | (On Diff #331880) | This shouldn't even be a target-specific test, it doesn't test anything aarch64-specific. |
llvm/test/Transforms/InstCombine/AArch64/sve-splat.ll | ||
---|---|---|
1 ↗ | (On Diff #331880) | I'm writing a (very) small new patch which will generalise this test per your previous comment. I'll add you to the subscribers/reviewers list once it's on phabricator. :) |
If you change VectorType to FixedVectorType here, it will automatically bail out on line 1573, and then you can undo the remaining changes in this function.