This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] shrinkFPConstantVector(): scalable vector support
ClosedPublic

Authored by nasherm on Mar 10 2021, 7:25 AM.

Details

Summary

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.

Diff Detail

Event Timeline

nasherm created this revision.Mar 10 2021, 7:25 AM
nasherm requested review of this revision.Mar 10 2021, 7:25 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 10 2021, 7:25 AM
sdesmalen added inline comments.
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:

  • Check if V is a splatvector of some FP constant, and then try to shrink that FP constant's Type to something smaller. This is only useful if the code that calls this function can actually do something with that information for scalable vectors.
  • Return nullptr if the type is a ScalableVectorType, possibly with a FIXME added.
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.
I believe you can leave the return as it is originally
Especially if Sander is saying to have an earlier return when doing the for.

llvm/test/Transforms/InstCombine/instcombine-vectors.ll
2 ↗(On Diff #329660)

Usually we also add this line in our tests:
; RUN: FileCheck --check-prefix=WARN --allow-empty %s <%t

; If this check fails please read test/CodeGen/AArch64/README for instructions on how to resolve it.$
; WARN-NOT: warning

And I believe this test should be in inside test/Transforms/InstCombine/AArch64

nasherm updated this revision to Diff 331196.Mar 17 2021, 3:00 AM

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.

david-arm added inline comments.Mar 17 2021, 3:50 AM
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?

nasherm added inline comments.Mar 17 2021, 5:52 AM
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.

sdesmalen added inline comments.Mar 17 2021, 7:32 AM
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.

nasherm updated this revision to Diff 331596.Mar 18 2021, 9:55 AM

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

sdesmalen added inline comments.Mar 18 2021, 10:21 AM
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.

Just in case ...

llvm/test/Transforms/InstCombine/AArch64/sve-splat.ll
9 ↗(On Diff #331596)

; CHECK-NEXT: %1 = fadd -> ; CHECK-NEXT: %[[FADD:.*]] = fadd ....
or something like this.

10 ↗(On Diff #331596)

ret <vscale x 2 x float> %1 -> ret <vscale x 2 x float> %[[FADD]]

lebedev.ri retitled this revision from [llvm-opt] Bug fix within combining FP vectors to [InstCombine] shrinkFPConstantVector(): scalable vector suppot.Mar 18 2021, 10:47 AM
sdesmalen retitled this revision from [InstCombine] shrinkFPConstantVector(): scalable vector suppot to [InstCombine] shrinkFPConstantVector(): scalable vector support.Mar 18 2021, 1:34 PM
nasherm updated this revision to Diff 331880.Mar 19 2021, 7:59 AM
nasherm marked 6 inline comments as done.

Addressed Sander's comment on casting to FixedVectorType as well
as Carol's suggestion for regression test.

david-arm accepted this revision.Mar 22 2021, 7:20 AM

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.
This revision is now accepted and ready to land.Mar 22 2021, 7:20 AM
lebedev.ri added inline comments.
llvm/test/Transforms/InstCombine/AArch64/sve-splat.ll
1 ↗(On Diff #331880)

Do you really need anything other than plain -instcombine here?

nasherm updated this revision to Diff 332628.Mar 23 2021, 5:06 AM
nasherm marked 2 inline comments as done.

Response to David's comments

This revision was landed with ongoing or failed builds.Mar 23 2021, 5:14 AM
This revision was automatically updated to reflect the committed changes.
nasherm added inline comments.Mar 23 2021, 5:38 AM
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.

lebedev.ri added inline comments.Mar 23 2021, 5:40 AM
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.

nasherm marked an inline comment as done.Mar 23 2021, 6:07 AM
nasherm added inline comments.
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. :)