This is an archive of the discontinued LLVM Phabricator instance.

[AArch64][GISel] Optimize 8 and 16 bit variants of uaddo.
ClosedPublic

Authored by fhahn on Oct 15 2021, 7:03 AM.

Details

Summary

Try simplify G_UADDO with 8 or 16 bit operands to wide G_ADD and TBNZ if
result is only used in the no-overflow case. It is restricted to cases
where we know that the high-bits of the operands are 0. If there's an
overflow, then the the 9th or 17th bit must be set, which can be checked
using TBNZ.

This is my first GISel patch so this is probably not the right place :)
I also couldn't find a convenient way to get MRI other than getting it
from the helper.

Diff Detail

Event Timeline

fhahn created this revision.Oct 15 2021, 7:03 AM
fhahn requested review of this revision.Oct 15 2021, 7:03 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 15 2021, 7:03 AM
paquette added inline comments.Oct 15 2021, 10:09 AM
llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp
254

You can get MRI from the builder.

274

Pull OpTy.getScalarSizeInBits() into a variable?

279

I think the !WideTy1.isScalar() check is redundant

286
  • Reuse MRI variable
  • Avoid debug value weirdness
305

Typically we do the "actually combining the thing" part in a separate function.

(I'm not actually sure if it matters though...?)

306

I don't think you need to tell the observer when you're deleting an instruction?

aemerson added inline comments.Oct 15 2021, 10:38 AM
llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp
305

Yeah, if we're bypassing the tablegen combiner I don't think we have to split it into separate functions.

316–320

use buildAnd()?

321–324

If we're going to replace ResStatus anyway, I think this can be written more succinctly IMO as:

B.buildICmp(CmpInst::ICMP_NE, ResStatus, CondBit, B.buildConstant(LLT::scalar(32), 0));

and then later delete MI which should take care of the original def of ResStatus.

foad added a comment.Oct 18 2021, 1:03 AM

I think this could handle G_USUBO in exactly the same way, if you want to.

fhahn updated this revision to Diff 380310.Oct 18 2021, 1:50 AM
fhahn marked 8 inline comments as done.

Address comments, thanks!

I also added tests with DBG_VALUE uses and made sure those are ignored.

paquette added inline comments.Oct 25 2021, 10:23 AM
llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp
256

In this case, you want to match

%op0 = G_TRUNC ...
...
%op1 = G_TRUNC ...
%.., %... = G_UADDO %op0, %op1

right?

I think you can do

if (!mi_match(MI.getOperand(2).getReg(), MRI, m_GTrunc(m_Reg(Op0Wide)) ||
    !mi_match(MI.getOperand(3).getReg(), MRI, m_GTrunc(m_Reg(Op1Wide)))
   return false;
268

Any reason to not use getVRegDef here?

(I would recommend getOpcodeDef, but I think that walks past G_ASSERT_ZEXT)

fhahn updated this revision to Diff 382243.Oct 26 2021, 2:54 AM

Address latest comments, thanks!

fhahn marked 2 inline comments as done.Oct 26 2021, 2:55 AM
fhahn added inline comments.
llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp
254

Great thanks!

256

yes, I merged them into a single if, thanks!

268

Any reason to not use getVRegDef here?

No reason I can think of. Updated!

305

Happy to split this up/pull it in somewhere else if that's better.

306

Thanks, looks like this can be dropped!

321–324

That makes things simpler, thanks! Did the same to get rid of ResNew below.

This revision is now accepted and ready to land.Oct 26 2021, 12:15 PM
This revision was automatically updated to reflect the committed changes.
fhahn marked 2 inline comments as done.