[PATCH] D157628: [AArch64][SVE2] Change the cost of extends with S/URHADD to 0
Sander de Smalen via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 15 08:47:30 PDT 2023
sdesmalen added inline comments.
================
Comment at: llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp:2047-2056
+// Where SVE2 is enabled, we can combine an add of 1, add & shift right by 1
+// to a single s/urhadd instruction. Some extends can be folded into the
+// instruction and will be 'free', e.g.
+// %zext1 = zext i8 %a to i16
+// %zext2 = zext i8 %b to i16
+// %add1 = add nuw nsw i16 %zext1, 1
+// %add2 = add nuw nsw i16 %add1, %zext2
----------------
nit: I find the description a bit confusing, how about:
s/urhadd instructions implements the following pattern, making the extends free:
%x = (zext i8 -> i16)
%y = (zext i8 -> i16) + 1)
trunc i16 (shl (add %x, %y), 1)) -> i8
?
================
Comment at: llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp:2057
+//
+bool isExtShiftRightAdd(const Instruction *I, const Instruction *Ext, Type *Dst,
+ Type *Src) {
----------------
nit: Perhaps better to make this a `CastInst`, because it it must be?
================
Comment at: llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp:2057
+//
+bool isExtShiftRightAdd(const Instruction *I, const Instruction *Ext, Type *Dst,
+ Type *Src) {
----------------
sdesmalen wrote:
> nit: Perhaps better to make this a `CastInst`, because it it must be?
Can you give `I` a more descriptive name? Or add some documentation above to explain what the relationship between `I` and `Ext` is?
================
Comment at: llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp:2069
+ // if this is an add.
+ auto *Op = I->getOperand(0) == Ext ? I->getOperand(1) : I->getOperand(0);
+
----------------
This code is puzzling me quite a bit.
Because of how this function is called (`I` is the only user of `Ext`), the only possible inputs we can have is:
add ( Ext, ... )
add ( ..., Ext )
So if `Op1` is not a constant, then the input must be `add (..., Ext)`. Here you're asking the question if `... == Ext`, which we know is `false`, after which `Op` is assigned `...`. It then changes the meaning of `I`, at which point I'm a bit lost :) It's a lot easier to use the Patterns from PatternMatch.h for this, that way you can do things like:
if (match(I, m_c_Add(m_Specific(Ext),
m_c_Add(m_ZExt(m_Value(V)), m_SpecificInt(1)))))
which also handles the commutativity of the add.
Note that instead of directly matching for m_ZExt, you could match `m_UnOp` and have another check to see that it's either `ZExt` (if `Ext` is a `ZExt`), or a SExt (if `Ext` is a `SExt`).
================
Comment at: llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp:2086
+ // The add should only have one user, a right shift of 1.
+ auto *Add = cast<Instruction>(*I->user_begin());
+ if (Add->getOpcode() != Instruction::Add || !Add->hasOneUser())
----------------
Is it worth first checking if this add has a single user which is a `LShr`, which itself has a single user that's a `Trunc`? That way you avoid having to match the whole expression, only to find out that the user of the `add(add(..), Ext)` isn't used by a `LShr`.
It probably makes it a lot easier to match the entire pattern once you know you have a `Trunc(LShr(Add(..), ..))` expression on your hands, when you take my suggestion above to use the `m_<patterns>` from PatternMatch.h.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D157628/new/
https://reviews.llvm.org/D157628
More information about the llvm-commits
mailing list