[PATCH] D33172: [InstCombine] Simpify inverted predicates in 'or'

Sanjay Patel via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon May 15 10:01:25 PDT 2017


spatel added a comment.

The problem may be more general than that. It's really about recognizing inverted compares, so let's take selects out of the equation (using div ops to thwart hoisting/sinking here, but that's just to produce a minimal IR example):

  define i32 @inverted_compares(i32 %a, i32 %b, i32 %c) {
  entry:
    %cmp = icmp slt i32 %a, %b
    br i1 %cmp, label %t1, label %f1
  
  t1:
    %div1 = sdiv i32 42, %c
    br label %endif1
  
  f1:
    %div2 = srem i32 43, %c
    br label %endif1
  
  endif1:
    %phi1 = phi i32 [ %div1, %t1 ], [ %div2, %f1 ]
    %cmpnot = icmp sge i32 %a, %b
    br i1 %cmpnot, label %t2, label %f2
  
  t2:
    %div3 = sdiv i32 44, %phi1
    br label %endif2
  
  f2:
    %div4 = srem i32 45, %phi1
    br label %endif2
  
  endif2:
    %phi2 = phi i32 [ %div3, %t2 ], [ %div4, %f2 ]
    %call = call i32 @bar(i32 %phi1, i32 %phi2)
  
    ret i32 %call
  }

Because of instcombine predicate canonicalization rules, we optimize this to one compare:

  define i32 @inverted_compares_optimized(i32 %a, i32 %b, i32 %c) {
  entry:
    %cmp = icmp slt i32 %a, %b
    br i1 %cmp, label %f2, label %t2
  
  t2:               
    %div2 = srem i32 43, %c
    %div3 = udiv i32 44, %div2
    br label %endif2
  
  f2:                               
    %div1 = sdiv i32 42, %c
    %div4 = srem i32 45, %div1
    br label %endif2
  
  endif2:                               
    %phi12 = phi i32 [ %div2, %t2 ], [ %div1, %f2 ]
    %phi2 = phi i32 [ %div3, %t2 ], [ %div4, %f2 ]
    %call = tail call i32 @bar(i32 %phi12, i32 %phi2)
    ret i32 %call
  }

But if the compare has an extra use, the instcombine doesn't fire, and this won't optimize at -O2:

  define i32 @inverted_compares_and_one(i32 %a, i32 %b, i32 %c) {
  entry:
    %cmp = icmp slt i32 %a, %b
    br i1 %cmp, label %t1, label %f1
  
  t1:
    %div1 = sdiv i32 42, %c
    br label %endif1
  
  f1:
    %div2 = srem i32 43, %c
    br label %endif1
  
  endif1:
    %phi1 = phi i32 [ %div1, %t1 ], [ %div2, %f1 ]
    %cmpnot = icmp sge i32 %a, %b
    br i1 %cmpnot, label %t2, label %f2
  
  t2:
    %div3 = sdiv i32 44, %phi1
    br label %endif2
  
  f2:
    %div4 = srem i32 45, %phi1
    br label %endif2
  
  endif2:
    %phi2 = phi i32 [ %div3, %t2 ], [ %div4, %f2 ]
    %call = call i32 @bar_extra_cmp_use(i32 %phi1, i32 %phi2, i1 %cmpnot)
    ret i32 %call
  }

We could have gotten this to:

  define i32 @inverted_compares_optimized(i32 %a, i32 %b, i32 %c) {
  entry:
    %cmp = icmp slt i32 %a, %b
    br i1 %cmp, label %f2, label %t2
  
  t2:               
    %div2 = srem i32 43, %c
    %div3 = udiv i32 44, %div2
    br label %endif2
  
  f2:                               
    %div1 = sdiv i32 42, %c
    %div4 = srem i32 45, %div1
    br label %endif2
  
  endif2:                               
    %phi12 = phi i32 [ %div2, %t2 ], [ %div1, %f2 ]
    %phi2 = phi i32 [ %div3, %t2 ], [ %div4, %f2 ]
    %cmpnot = icmp sge i32 %a, %b
    %call = call i32 @bar_extra_cmp_use(i32 %phi1, i32 %phi2, i1 %cmpnot)
    ret i32 %call
  }


https://reviews.llvm.org/D33172





More information about the llvm-commits mailing list