If constants are hidden behind G_ANYEXT we can treat them same way as G_SEXT.
For that purpose we extend getConstantVRegValWithLookThrough with option
to handle G_ANYEXT same way as G_SEXT.
Details
Diff Detail
Event Timeline
llvm/lib/Target/AMDGPU/SIFoldOperands.cpp | ||
---|---|---|
980–988 ↗ | (On Diff #308003) | I would prefer not to add more ad hoc constant folding to this pass. Can you work out where the un-folded pack instructions are coming from in the first place, and fix it there instead? |
Specific case from one of the tests:
%5:sgpr(s16) = G_FCONSTANT half 0xH4000 %7:sgpr(s32) = G_ANYEXT %5:sgpr(s16) %4:sreg_32(<2 x s16>) = G_BUILD_VECTOR_TRUNC %7:sgpr(s32), %7:sgpr(s32)
will now be:
%4:sreg_32 = S_MOV_B32 1073758208
instead of:
%5:sreg_32 = S_MOV_B32 16384 %4:sreg_32 = S_PACK_LL_B32_B16 %5:sreg_32, %5:sreg_32
llvm/include/llvm/CodeGen/GlobalISel/Utils.h | ||
---|---|---|
146 | I'm not sure if we need a flag for this. Could we do it unconditionally? @qcolombet ? |
llvm/include/llvm/CodeGen/GlobalISel/Utils.h | ||
---|---|---|
146 | There were no regressions for check-all when I tried it that way, but I wasn't sure if I should leave it like that. |
llvm/include/llvm/CodeGen/GlobalISel/Utils.h | ||
---|---|---|
146 | I think it's probably safe to treat anyext the same as zext in this function, but maybe wait for comments from other globalisel maintainers (who may be on thanksgiving vacation). |
Specific case from one of the tests:
%5:sgpr(s16) = G_FCONSTANT half 0xH4000 %7:sgpr(s32) = G_ANYEXT %5:sgpr(s16) %4:sreg_32(<2 x s16>) = G_BUILD_VECTOR_TRUNC %7:sgpr(s32), %7:sgpr(s32)
Perhaps there should be a combine that simplifies this to G_BUILD_VECTOR %5, %5.
This is specifically avoiding 16-bit inputs, we expanded the other direction. It could be a bitcast of a scalar constant. I'm trying a somewhat different strategy for 16-bit vectors than the DAG but not sure what the end state is going to look like
I think this looks good, and we could even get rid of the AnyExtAsZext flag and do it unconditionally. Adding some globalisel folks to see if there are any objections.
llvm/include/llvm/CodeGen/GlobalISel/Utils.h | ||
---|---|---|
146 | Maybe this should be LookThroughAnyExt? I imagine there are situations where we might want to treat G_ANYEXT as a sign extend. e.g. %cst:_(s32) = G_CONSTANT i32 -1 %cst_wide:_(s64) = G_ANYEXT %cst ... %y:_(s64) = ... %x:_(s64) = G_ADD %y, %cst_wide |
llvm/include/llvm/CodeGen/GlobalISel/Utils.h | ||
---|---|---|
146 | You mean, change the name of the argument to LookThroughAnyExt? But what would it do? Currently this function has to either sign- or zero-extend whatever constant it finds, so that it can return a value of the right bit width. |
llvm/include/llvm/CodeGen/GlobalISel/Utils.h | ||
---|---|---|
146 |
I think Jessica was pointing out that which extend (if any) is the correct thing to do is context and target dependent. To add to the target dependent side of that: G_ANYEXT is an extension with undefined bits and you're allowed to pick zero/sign-extend if that's convenient for your target but different targets will prefer sign or zero extend and some won't care either way (e.g. because they can operate on the smaller bitwidth). In the case of Mips, it's potentially width dependent due to some quirks of forward compatibility on that target where registers are theoretically sign extended to infinite width even if the value is supposed to be zero extended. |
I'm not sure if we need a flag for this. Could we do it unconditionally? @qcolombet ?