Extend the existing combineADDDToWMACC DAG combine to also match
RISCVISD::WMULSU and produce RISCVISD::WMACCSU. This is similar to
how ADDD+UMUL_LOHI is combined to WMACCU and ADDD+SMUL_LOHI is
combined to WMACC.
This patch was generated by AI, but I reviewed it.
Combine the pattern:
ADDD(addlo, addhi, UMUL_LOHI(x, y).0, UMUL_LOHI(x, y).1)
into:
WMACCU(x, y, addlo, addhi)
And similarly for SMUL_LOHI -> WMACC.
This patch was written with AI, but I reviewed it carefully.
Order the operands so the the low and high part of the rs1 regpair are
first, followed by the low and high part of the rs2 regpair.
Also change the type to use v4i8 for the result so that it's only
shuffling elements not combining elements into a larger elment.
I'm planning to add ADDD and SUBD opcodes that will be defined with the
same operand order allowing RISCVISelDAGToDAG.cpp code to be shared.
The enablePExtCodeGen was only intended to block vector code while
it is still in development. This code uses scalar types so we only
need to check for the extension.
Make sure the constant isn't already sign extended before calling these
functions.
Also add some elses to prevent checks where we already know the value
has been optimized.
We can use the default legalization which will create an i32 load
followed by a v2i32 scalar_to_vector followed by a bitcast. We can isel
the scalar_to_vector like a bitcast and not generate any instructions
for it.
This is the initial support of P extension codegen, it only includes
small part of instructions:
PADD_H, PADD_B,
PSADD_H, PSADD_B,
PAADD_H, PAADD_B,
PSADDU_H, PSADDU_B,
PAADDU_H, PAADDU_B,
PSUB_H, PSUB_B,
PDIF_H, PDIF_B,
PSSUB_H, PSSUB_B,
PASUB_H, PASUB_B,
PDIFU_H, PDIFU_B,
PSSUBU_H, PSSUBU_B,
PASUBU_H, PASUBU_B
These instructions both extract single bit to bit 0 and fill the upper
bits with 0.
There's at least one place where we check for BEXTI but not TH_TST. I
wanted to keep this patch NFC so that will be a follow up fix.
If we don't fold all uses, we end up with an LUI that is used by an ADDI
and some loads/stores. This requires the LUI to write a different
register than the ADDI or the load/stores uses have to be scheduled
between the LUI and ADDI. It prevents macrofusion of the LUI+ADDI on
CPUs that support it. It prevents the use of PseudoMovAddr which
prevents the LUI+ADDI from being rematerializable.
This is based on a patch we have had in our downstream for a while that
we originally wrote because of macrofusion and rematerialization. I no
longer have any relevant performance or code size numbers for it.
---------
Co-authored-by: Jesse Huang <jesse.huang@sifive.com>
Co-authored-by: Luke Lau <luke_lau@icloud.com>
These instructions are being used by the scalar efficiency SIG to
determine if we should have a standard instruction. Improving our
support for these instructions may give better data for their analysis.
I'll follow up by adding this to RISCVOptWInstrs too which will remove
the 'w' suffixes added here.
Before this patch, the selection for `QC_INSB` and `QC_INSBI` entirely
happens in C++, and does not support more than one non-constant input.
This patch seeks to rectify this shortcoming, by moving the C++ into a
target-specific DAGCombine, and adding `RISCV::QC_INSB`. One advantage
is this simplifies the code for handling `QC_INSBI`, as the C++ no
longer needs to choose between the two instructions based on the
inserted value (this is still done, but via ISel Patterns).
Another advantage of the DAGCombine is that this introduction can also
shift the inserted value to the `QC_INSB`, which our patterns need (and
were previously doing to the constant), and this shift can be
CSE'd/optimised with any prior shifts, if they exist. This allows the
inserted value to be variable, rather than a constant.
Generate QC_INSB/QC_INSBI from `or (and X, MaskImm), OrImm` iff the
value being inserted only sets known zero bits. This is based on a
similar DAG to DAG transform done in `AArch64`.
This patch adds CodeGen support for qc.insbi and qc.insb instructions
defined in the Qualcomm uC Xqcibm extension. qc.insbi and qc.insb
inserts bits into destination register from immediate and register
operand respectively.
A sequence of `xor`, `and` & `xor` depending on appropriate conditions
are converted to `qc.insbi` or `qc.insb` which depends on the
immediate's value.
-Only fold if the ADD can be folded into all uses.
-Don't reassociate an ADDI if the shl+add can be a shxadd or similar
instruction.
-Only reassociate a single ADDI. If there are 2 addis it's the same
number of instructions as shl+add. If there are more than 2 that it
would increase instructions over folding the addis into the
loads/stores.
Rename UnwrapShl->SelectShl. Make it only responsible for matching
a SHL by constant.
Handle the fallback case of reg+reg with no scale outside of SelectShl.
Reorder the check so RHS is checked for shift first. The base pointer
is most likely on the LHS. It's very unlikely both operands are shifts.
This is preparation for adding better costing decisions to this code.
The transformation done in #147349 was incorrect since we were not
passing the input node of the `OR` instruction to the `QC.INSBI`
instruction leading to the generated instruction doing the wrong thing.
In order to do this we first needed to add the output register to
`QC.INSBI` as being both an input and output.
The code produced after the above fix will need a copy (mv) to preserve
the register input to the OR instruction if it has more than one use
making the transformation net neutral ( `6-byte QC.E.ORI/ORAI` vs
`2-byte C.MV + 4-byte QC.INSB`I). Avoid doing the transformation if
there is more than one use of the input register to the OR instruction.