[PATCH] D112276: [InstCombine] Fold `(c & ~(a | b)) | (b & ~(a | c))` to `~a & (b ^ c)`

Stanislav Mekhanoshin via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 25 10:28:52 PDT 2021


rampitec added a comment.

Let me give a little background on this. This is essentially ternary boolean logic similar to AVX512 instruction VPTERNLOG. I came across this function doing similar thing at a source level: https://forums.developer.nvidia.com/t/reverse-lut-for-lop3-lut/110651 as a simulation:

  uint32_t lop3_fast (uint32_t a, uint32_t b, uint32_t c, uint8_t ttbl)
  {
      uint32_t r = 0;
      if (ttbl & 0x01) r |= ~a & ~b & ~c;
      if (ttbl & 0x02) r |= ~a & ~b &  c;
      if (ttbl & 0x04) r |= ~a &  b & ~c;
      if (ttbl & 0x08) r |= ~a &  b &  c;
      if (ttbl & 0x10) r |=  a & ~b & ~c;
      if (ttbl & 0x20) r |=  a & ~b &  c;
      if (ttbl & 0x40) r |=  a &  b & ~c;
      if (ttbl & 0x80) r |=  a &  b &  c;
      return r;
  }

I cannot say there is a real driving factor to optimize it other than the fact I was shocked by the code produced by llvm optimizer. Here are couple of most patalogical cases:

1. case 15:

  %9 = or i32 %7, %6
  %10 = xor i32 %9, -1
  %11 = xor i32 %6, -1
  %12 = and i32 %7, %11
  %13 = xor i32 %8, -1
  %14 = and i32 %12, %13
  %15 = or i32 %14, %10
  %16 = and i32 %12, %8
  %17 = or i32 %15, %16

After simplification it is just `~a`.

2. case 255:

  %9 = or i32 %7, %6
  %10 = xor i32 %9, -1
  %11 = xor i32 %6, -1
  %12 = and i32 %7, %11
  %13 = xor i32 %8, -1
  %14 = and i32 %12, %13
  %15 = or i32 %14, %10
  %16 = and i32 %12, %8
  %17 = or i32 %15, %16
  %18 = xor i32 %7, -1
  %19 = and i32 %6, %18
  %20 = and i32 %19, %13
  %21 = or i32 %17, %20
  %22 = and i32 %19, %8
  %23 = or i32 %21, %22
  %24 = and i32 %7, %6
  %25 = and i32 %24, %13
  %26 = or i32 %23, %25
  %27 = and i32 %24, %8
  %28 = or i32 %26, %27

After simplification this is just `-1`.

Out of 256 possible functions calculated by this code most can use simplifications and can be done in ~3 instructions in average. Yet llvm produces a whole bloat of code.

My assumption was that shall be possible to optimize a few subexpressions here to simplify all of that. The assumption is based on the fact that these are just combinations of very similar patterns. In part that assumption is correct. For example D112108 <https://reviews.llvm.org/D112108> simplifies `case 4` from the above function, but also helped ~10 of other patterns. The next two patterns helped 16 and 19 other expressions respectively. Although they did not help all of these expressions completely.

I guess until all of that done I will not know how many more patterns are needed to handle it. Likely not 100, but certainly more than 10. I have to admit it converges slower than I hoped. That said I am not so sure the direction of pattern matching it here is right too so any thoughts are more than welcome.

I see a benefit of a logical solver as an alternative to pattern matching. Although the problem I see here is how to select a dag to solve? A longest dag consisting of logical operations does not seem to be correct answer because of a multiple use subexpressions, but limiting all subexpressions to a single use does not sound right either. This exercise showed that some tolerance to not having as single use for a subexpression is needed to tackle this. For example this case `(c & ~(a | b)) | (b & ~(a | c))` has 7 operations, simplified case `~a & (b ^ c)` has only 3. The naive approach is to think we may tolerate 4 multiply used values here, which also creates a problem of choice. I am just afraid a general logical solver will turn into an n-p complete solution because of this.

That said, patterns like this are linear even though big. I have no particular preference to put it into IC or AIC, but given the current definition anything O(N) goes into IC, and something more expensive into AIC as far as I understand.

To summarize I am somewhat unsure if that makes sense to continue pattern matching like this at all, or where shall it go if that makes sense.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D112276/new/

https://reviews.llvm.org/D112276



More information about the llvm-commits mailing list