[PATCH] D70053: [Codegen] TargetLowering::prepareUREMEqFold(): `x u% C1 ==/!= C2` (PR35479)

Roman Lebedev via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 10 09:28:53 PST 2019


lebedev.ri created this revision.
lebedev.ri added reviewers: RKSimon, craig.topper, spatel.
lebedev.ri added a project: LLVM.
Herald added a subscriber: hiraditya.
lebedev.ri added a parent revision: D70051: [Codegen] TargetLowering::prepareUREMEqFold(): `x u% C1 ==/!= C2` with tautological C1 u<= C2 (PR35479).

The current lowering is:

  Name: (X % C1) == C2 -> X * C3 <= C4 || false
  Pre: (C2 == 0 || C1 u<= C2) && (C1 u>> countTrailingZeros(C1)) * C3 == 1
  %zz = and i8 C3, 0 ; trick alive into making C3 avaliable in precondition
  %o0 = urem i8 %x, C1
  %r = icmp eq i8 %o0, C2
    =>
  %zz = and i8 C3, 0 ; and silence it from complaining about said reg
  %C4 = -1 /u C1
  %n0 = mul i8 %x, C3
  %n1 = lshr i8 %n0, countTrailingZeros(C1) ; rotate right
  %n2 = shl i8 %n0, ((8-countTrailingZeros(C1)) %u 8) ; rotate right
  %n3 = or i8 %n1, %n2 ; rotate right
  %is_tautologically_false = icmp ule i8 C1, C2
  %C4_fixed = select i1 %is_tautologically_false, i8 -1, i8 %C4
  %res = icmp ule i8 %n3, %C4_fixed
  %r = xor i1 %res, %is_tautologically_false

https://rise4fun.com/Alive/2xC
https://rise4fun.com/Alive/jpb5

However, we can support non-tautological cases `C1 u> C2` too.
Said handling consists of two parts:

- `C2 u<= (-1 %u C1)`. It just works. We only have to change `(X % C1) == C2` into `((X - C2) % C1) == 0`

  Name: (X % C1) == C2 -> (X - C2) * C3 <= C4   iff C2 u<= (-1 %u C1)
  Pre: (C1 u>> countTrailingZeros(C1)) * C3 == 1 && C2 u<= (-1 %u C1)
  %zz = and i8 C3, 0 ; trick alive into making C3 avaliable in precondition
  %o0 = urem i8 %x, C1
  %r = icmp eq i8 %o0, C2
    =>
  %zz = and i8 C3, 0 ; and silence it from complaining about said reg
  %C4 = (-1 /u C1)
  %n0 = sub i8 %x, C2
  %n1 = mul i8 %n0, C3
  %n2 = lshr i8 %n1, countTrailingZeros(C1) ; rotate right
  %n3 = shl i8 %n1, ((8-countTrailingZeros(C1)) %u 8) ; rotate right
  %n4 = or i8 %n2, %n3 ; rotate right
  %is_tautologically_false = icmp ule i8 C1, C2
  %C4_fixed = select i1 %is_tautologically_false, i8 -1, i8 %C4
  %res = icmp ule i8 %n4, %C4_fixed
  %r = xor i1 %res, %is_tautologically_false

https://rise4fun.com/Alive/m4P
https://rise4fun.com/Alive/SKrx

- `C2 u> (-1 %u C1)`. We also have to change `(X % C1) == C2` into `((X - C2) % C1) == 0`, and we have to decrement C4:

  Name: (X % C1) == C2 -> (X - C2) * C3 <= C4   iff C2 u> (-1 %u C1)
  Pre: (C1 u>> countTrailingZeros(C1)) * C3 == 1 && C2 u> (-1 %u C1)
  %zz = and i8 C3, 0 ; trick alive into making C3 avaliable in precondition
  %o0 = urem i8 %x, C1
  %r = icmp eq i8 %o0, C2
    =>
  %zz = and i8 C3, 0 ; and silence it from complaining about said reg
  %C4 = (-1 /u C1)-1
  %n0 = sub i8 %x, C2
  %n1 = mul i8 %n0, C3
  %n2 = lshr i8 %n1, countTrailingZeros(C1) ; rotate right
  %n3 = shl i8 %n1, ((8-countTrailingZeros(C1)) %u 8) ; rotate right
  %n4 = or i8 %n2, %n3 ; rotate right
  %is_tautologically_false = icmp ule i8 C1, C2
  %C4_fixed = select i1 %is_tautologically_false, i8 -1, i8 %C4
  %res = icmp ule i8 %n4, %C4_fixed
  %r = xor i1 %res, %is_tautologically_false

https://rise4fun.com/Alive/d40
https://rise4fun.com/Alive/8cF

I believe this concludes `x u% C1 ==/!= C2` lowering.
In fact, clang is may now be better in this regard than gcc:
as it can be seen from `@t32_6_4` test, we do lower `x % 6 == 4`
via this pattern, while gcc does not: https://godbolt.org/z/XNU2z9
And all the general alive proofs say this is legal.
And manual checking agrees: https://rise4fun.com/Alive/WA2

Fixes PR35479 <https://bugs.llvm.org/show_bug.cgi?id=35479>.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D70053

Files:
  llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
  llvm/test/CodeGen/AArch64/urem-seteq-nonzero.ll
  llvm/test/CodeGen/AArch64/urem-seteq-vec-nonzero.ll
  llvm/test/CodeGen/X86/urem-seteq-nonzero.ll
  llvm/test/CodeGen/X86/urem-seteq-vec-nonzero.ll

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D70053.228610.patch
Type: text/x-patch
Size: 47977 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191110/fe6eec13/attachment-0001.bin>


More information about the llvm-commits mailing list