[PATCH] D78430: [InstSimplify] fold and/or of compares with equality to min/max constant

Sanjay Patel via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Apr 18 09:41:39 PDT 2020


spatel created this revision.
spatel added reviewers: lebedev.ri, nikic, nlopes, regehr, aqjune.
Herald added subscribers: hiraditya, mcrosier.

I found 12 (6 if we compress the DeMorganized forms) patterns for logic-of-compares with a min/max constant while looking at PR45510:
https://bugs.llvm.org/show_bug.cgi?id=45510

The variations on those forms multiply the test cases by 8 (unsigned/signed, swapped compare operands, commuted logic operands).
We had partial logic to deal with these for the unsigned min (zero) case, but missed everything else.

I drafted an alternate implementation that uses ConstantRange instead of predicate+constant matching. It's slightly less code, but it requires many more code comments to follow the implied logic, so I think it's not worth the effort. I don't expect there's any noticeable compile-time impact for either form.

Here's an abuse of Alive2 to show the 12 basic signed variants of the patterns in 1 function:
http://volta.cs.utah.edu:8080/z/5Vpiyg

  declare void @use(i1, i1, i1, i1, i1, i1, i1, i1, i1, i1, i1, i1)
  define void @src(i8 %x, i8 %y)  {
    %m1 = icmp eq i8 %x, 127
    %c1 = icmp slt i8 %x, %y
    %r1 = and i1 %m1, %c1   ; (X == MAX) && (X < Y) --> false
  
    %m2 = icmp ne i8 %x, 127
    %c2 = icmp sge i8 %x, %y
    %r2 = or i1 %m2, %c2    ; (X != MAX) || (X >= Y) --> true
  
    %m3 = icmp eq i8 %x, -128
    %c3 = icmp sgt i8 %x, %y
    %r3 = and i1 %m3, %c3   ; (X == MIN) && (X > Y) --> false
  
    %m4 = icmp ne i8 %x, -128
    %c4 = icmp sle i8 %x, %y
    %r4 = or i1 %m4, %c4    ; (X != MIN) || (X <= Y) --> true
  
    %m5 = icmp eq i8 %x, 127
    %c5 = icmp sge i8 %x, %y
    %r5 = and i1 %m5, %c5   ; (X == MAX) && (X >= Y) --> X == MAX
   
    %m6 = icmp ne i8 %x, 127
    %c6 = icmp slt i8 %x, %y
    %r6 = or i1 %m6, %c6   ; (X != MAX) || (X < Y) --> X != MAX
  
    %m7 = icmp eq i8 %x, -128
    %c7 = icmp sle i8 %x, %y
    %r7 = and i1 %m7, %c7   ; (X == MIN) && (X <= Y) --> X == MIN
  
    %m8 = icmp ne i8 %x, -128
    %c8 = icmp sgt i8 %x, %y
    %r8 = or i1 %m8, %c8   ; (X != MIN) || (X > Y) --> X != MIN
  
    %m9 = icmp ne i8 %x, 127
    %c9 = icmp slt i8 %x, %y
    %r9 = and i1 %m9, %c9    ; (X != MAX) && (X < Y) --> X < Y
   
    %m10 = icmp eq i8 %x, 127
    %c10 = icmp sge i8 %x, %y
    %r10 = or i1 %m10, %c10    ; (X == MAX) || (X >= Y) --> X >= Y
  
    %m11 = icmp ne i8 %x, -128
    %c11 = icmp sgt i8 %x, %y
    %r11 = and i1 %m11, %c11    ; (X != MIN) && (X > Y) --> X > Y
  
    %m12 = icmp eq i8 %x, -128
    %c12 = icmp sle i8 %x, %y
    %r12 = or i1 %m12, %c12    ; (X == MIN) || (X <= Y) --> X <= Y
  
    call void @use(i1 %r1, i1 %r2, i1 %r3, i1 %r4, i1 %r5, i1 %r6, i1 %r7, i1 %r8, i1 %r9, i1 %r10, i1 %r11, i1 %r12)
    ret void
  }
  
  define void @tgt(i8 %x, i8 %y)  {
    %m5 = icmp eq i8 %x, 127
    %m6 = icmp ne i8 %x, 127
    %m7 = icmp eq i8 %x, -128
    %m8 = icmp ne i8 %x, -128
    %c9 = icmp slt i8 %x, %y
    %c10 = icmp sge i8 %x, %y
    %c11 = icmp sgt i8 %x, %y
    %c12 = icmp sle i8 %x, %y
    call void @use(i1 0, i1 1, i1 0, i1 1, i1 %m5, i1 %m6, i1 %m7, i1 %m8, i1 %c9, i1 %c10, i1 %c11, i1 %c12)
    ret void
  }


https://reviews.llvm.org/D78430

Files:
  llvm/lib/Analysis/InstructionSimplify.cpp
  llvm/test/Transforms/InstSimplify/and-or-icmp-min-max.ll

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D78430.258528.patch
Type: text/x-patch
Size: 36484 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200418/5b2fcfac/attachment.bin>


More information about the llvm-commits mailing list