This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] move extend after insertelement if both operands are extended
ClosedPublic

Authored by spatel on Sep 9 2021, 12:19 PM.

Details

Summary

I was wondering how instcombine does on the examples in D109236, and we're missing what looks like a basic transform:

inselt (ext X), (ext Y), Index --> ext (inselt X, Y, Index)

https://alive2.llvm.org/ce/z/z2aBu9

If this looks ok, then instcombine can handle the relatively simple tests in the other patch.
So we might want to make those a bit longer to show the power of the more general approach in -aggressive-instcombine.

Diff Detail

Event Timeline

spatel created this revision.Sep 9 2021, 12:19 PM
spatel requested review of this revision.Sep 9 2021, 12:19 PM
Herald added a project: Restricted Project. · View Herald TranscriptSep 9 2021, 12:19 PM
spatel edited reviewers, added: lebedev.ri; removed: andreil99.Sep 9 2021, 12:22 PM
lebedev.ri added inline comments.Sep 9 2021, 12:37 PM
llvm/test/Transforms/InstCombine/insert-ext.ll
62–64

I guess it will depend on our profitability/correctness reasoning for this transform,
but under standard instcombine profitability model we should be fine producing

%s = sext i8 %y to i16
%i = insertelement <2 x i16> %x, i16 %s, i32 %index
%r = sext <2 x i16> %i to <2 x i32>
spatel added inline comments.Sep 9 2021, 12:53 PM
llvm/test/Transforms/InstCombine/insert-ext.ll
62–64

Yes - I thought about including this one, but it seemed improbable and makes the use check a bit more restrictive. Ie, if we're creating 3 new insts, then we need one-use on both of the operands.

And I wasn't sure, but it does seem to hold for fpext too:
https://alive2.llvm.org/ce/z/QNQKWt

I can make that a TODO if that's ok.

Should we handle trunc as well? https://alive2.llvm.org/ce/z/93QN9g

I want to check that codegen isn't impacted by using insertelement on a wider (possible illegal type) vector op, but I think the answer is 'yes'.

In fact, we should probably do this for all cast opcodes to be consistent. I have to go through the whole opcode list (and add piles of tests) to be sure, but it works for these at least:
https://alive2.llvm.org/ce/z/HxH4AC (fptosi / fptoui / sitofp / uitofp)
https://alive2.llvm.org/ce/z/Rh_dqv (bitcast)

Another TODO for this patch, or do we prefer to handle it all in one patch?

Just noticed that we already have this one at line 1436 of the existing source file:

// If the vector and scalar are both bitcast from the same element type, do
// the insert in that source type followed by bitcast.

Should we handle trunc as well? https://alive2.llvm.org/ce/z/93QN9g

I want to check that codegen isn't impacted by using insertelement on a wider (possible illegal type) vector op, but I think the answer is 'yes'.

We would need to deal with something like this in the backend to be safe:
https://godbolt.org/z/E1nKvd6e3

Should we handle trunc as well? https://alive2.llvm.org/ce/z/93QN9g

I want to check that codegen isn't impacted by using insertelement on a wider (possible illegal type) vector op, but I think the answer is 'yes'.

We would need to deal with something like this in the backend to be safe:
https://godbolt.org/z/E1nKvd6e3

Yeah, there's going to be a number of these - in particular for integer insertions

If this looks ok, then instcombine can handle the relatively simple tests in the other patch.
So we might want to make those a bit longer to show the power of the more general approach in -aggressive-instcombine.

No one of tests touched by D109236 isn't processed by this patch, since they are not matched by inselt (ext X), (ext Y), Index pattern.

llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
1430

Move hasOneUse() check above, before matching? Or should be here in light of TODO?

spatel updated this revision to Diff 372690.Sep 15 2021, 6:22 AM

Patch updated:

  1. Moved use check up.
  2. Added TODO comments - up to 3 now :)

If this looks ok, then instcombine can handle the relatively simple tests in the other patch.
So we might want to make those a bit longer to show the power of the more general approach in -aggressive-instcombine.

No one of tests touched by D109236 isn't processed by this patch, since they are not matched by inselt (ext X), (ext Y), Index pattern.

What I meant is that the tests in that patch are reduced by instcombine after this patch, so there's nothing left for AIC to do if regular instcombine runs first:

$ opt -instcombine 109236.ll -S

define <2 x i16> @extract_insert(<2 x i8> %a, <2 x i8> %b) {
  %1 = shufflevector <2 x i8> %b, <2 x i8> %a, <2 x i32> <i32 0, i32 2>
  %trunc = zext <2 x i8> %1 to <2 x i16>
  ret <2 x i16> %trunc
}

define <2 x i16> @insert_poison(i8 %a) {
  %1 = zext i8 %a to i16
  %trunc = insertelement <2 x i16> undef, i16 %1, i32 0
  ret <2 x i16> %trunc
}
spatel updated this revision to Diff 372695.Sep 15 2021, 6:31 AM

Patch updated:
I missed moving the code comment above the hasOneUse() check in the previous draft.

spatel marked an inline comment as done.Sep 15 2021, 6:32 AM

What I meant is that the tests in that patch are reduced by instcombine after this patch, so there's nothing left for AIC to do if regular instcombine runs first:

$ opt -instcombine 109236.ll -S

define <2 x i16> @extract_insert(<2 x i8> %a, <2 x i8> %b) {
  %1 = shufflevector <2 x i8> %b, <2 x i8> %a, <2 x i32> <i32 0, i32 2>
  %trunc = zext <2 x i8> %1 to <2 x i16>
  ret <2 x i16> %trunc
}

define <2 x i16> @insert_poison(i8 %a) {
  %1 = zext i8 %a to i16
  %trunc = insertelement <2 x i16> undef, i16 %1, i32 0
  ret <2 x i16> %trunc
}

Ok, I see. Rebased D109236 agains new test added.

This revision is now accepted and ready to land.Sep 15 2021, 10:07 AM