This is an archive of the discontinued LLVM Phabricator instance.

[RISCV] With Zbb, fold (sext_inreg (abs X)) -> (max X, (negw X))
ClosedPublic

Authored by craig.topper on Feb 25 2022, 3:48 PM.

Details

Summary

With Zbb, abs is expanded to (max X, neg) by default. If X has 33 or
more sign bits, we can expand it a little early using negw instead of
neg to save a sext_inreg. If X started as a 32 bit value, type
legalization would have inserted a sext before the abs so X having
33 sign bits should always be true.

Note: I've used ISD::FREEZE here since we increase the number of uses.
Our default expansion for ABS doesn't do that, but I think that's a bug.

We can't do this with custom type legalization because ISD::FREEZE
doesn't propagate sign bits so later DAG combine won't expand be
able to see optmize it.

Alives2 https://alive2.llvm.org/ce/z/Gx3RNe

Diff Detail

Event Timeline

craig.topper created this revision.Feb 25 2022, 3:48 PM
craig.topper requested review of this revision.Feb 25 2022, 3:48 PM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 25 2022, 3:48 PM
llvm/test/CodeGen/RISCV/rv64zbb.ll
976

If line 964 (i32 signext %x) takes effect, why can't we remove line 977 directly?

craig.topper added inline comments.Feb 28 2022, 8:44 AM
llvm/test/CodeGen/RISCV/rv64zbb.ll
976

The absolute value of a 32-bit value is a 33-bit number because 0xffffffff80000000 becomes 0x0000000080000000. The sign extend at the end will change it back to 0xffffffff80000000.

Herald added a project: Restricted Project. · View Herald TranscriptMar 1 2022, 6:44 PM
spatel added inline comments.Mar 3 2022, 5:39 AM
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
7637

Can the ComputeNumSignBits be an assert rather than part of the predicate?

7640–7644

If this will never be anything but a quirk of the i64 type, replace VT with MVT::i64 to make that clearer?

craig.topper added inline comments.Mar 3 2022, 8:09 AM
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
7637

The input is sign extended if the abs was promoted by type legalization, but I think it is possible to write (i64 (sext (i32 (trunc (i64 abs X)))) in the original IR and the input would not be sign extended.

spatel added inline comments.Mar 3 2022, 9:36 AM
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
7637

Maybe I'm not understanding the pattern - is it possible to write a negative test?
If we sext_inreg from i32, does this model the transform:
https://alive2.llvm.org/ce/z/j4RdVa ?

Expand the comment to better explain what is happening.

spatel added inline comments.Mar 3 2022, 1:12 PM
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
7637

I'm still not seeing it after reading the comment/example:
ashr X, 32 -> adds 32 signbits to at least 1 existing signbit
How can this be under 33?

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

craig.topper added inline comments.Mar 3 2022, 1:20 PM
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
7637

Your shift result isn't being used your src function returned %abs not %ashr https://alive2.llvm.org/ce/z/eRHZww

This is the transform I'm trying to do here

define i64 @src(i64 %x) {
  %abs = call i64 @llvm.abs.i64(i64 %x, i1 0)
  %shl = shl i64 %abs, 32
  %ashr = ashr i64 %shl, 32
  ret i64 %ashr
}

define i64 @tgt(i64 %x) {
  %f = freeze i64 %x
  %negx = sub i64 0, %f
  %shl = shl i64 %negx, 32
  %ashr = ashr i64 %shl, 32
  %max = call i64 @llvm.smax.i64(i64 %ashr, i64 %negx)
  ret i64 %max
}

It's only valid if %x has 33 sign bits.

craig.topper added inline comments.Mar 3 2022, 1:24 PM
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
7637

Oops that's not right. Give me a few minutes

craig.topper added inline comments.Mar 3 2022, 1:27 PM
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
7637

This is the transform I'm doing here

define i64 @src(i64 %x) {
  %abs = call i64 @llvm.abs.i64(i64 %x, i1 0)
  %shl = shl i64 %abs, 32
  %ashr = ashr i64 %shl, 32
  ret i64 %ashr
}

define i64 @tgt(i64 %x) {
  %f = freeze i64 %x
  %negx = sub i64 0, %f
  %shl = shl i64 %negx, 32
  %ashr = ashr i64 %shl, 32
  %max = call i64 @llvm.smax.i64(i64 %f, i64 %ashr)
  ret i64 %max
}

But it doesn't work if %x doesn't have 33 sign bits.

spatel accepted this revision.Mar 3 2022, 1:45 PM

LGTM

llvm/lib/Target/RISCV/RISCVISelLowering.cpp
7637

Thanks - now I see it. :)

This revision is now accepted and ready to land.Mar 3 2022, 1:45 PM
This revision was landed with ongoing or failed builds.Mar 3 2022, 3:42 PM
This revision was automatically updated to reflect the committed changes.