[PATCH] D147146: [InstCombine] Should postpone zero check folding if the compare argument is a call

Alexander via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 29 06:24:46 PDT 2023


alex-t added a comment.

Example:

  define i32 @zot(i32 noundef %arg) {
  bb:
    %inst = icmp eq i32 %arg, 0
    %inst1 = call i32 @llvm.cttz.i32(i32 %arg, i1 true)
    %inst2 = select i1 %inst, i32 -1, i32 %inst1
    %inst3 = add nsw i32 %inst2, 1
    ret i32 %inst3
  }
  
  define i32 @snork(i32 %arg, i32 noundef %arg1) {
  bb:
    %inst = xor i32 %arg1, -1
    %inst2 = call i32 @zot(i32 noundef %inst)
    %inst3 = icmp ne i32 %inst2, 0
    %inst4 = sub i32 %inst2, 1
    %inst5 = select i1 %inst3, i32 %inst4, i32 0
    ret i32 %inst5
  }

opt -S -passes=instcombine test.ll

  define i32 @zot(i32 noundef %arg) {
  bb:
    %inst = icmp eq i32 %arg, 0
    %inst1 = call i32 @llvm.cttz.i32(i32 %arg, i1 true), !range !0
    %inst1.op = add nuw nsw i32 %inst1, 1
    %inst3 = select i1 %inst, i32 0, i32 %inst1.op
    ret i32 %inst3
  }
  
  define i32 @snork(i32 %arg, i32 noundef %arg1) {
  bb:
    %inst = xor i32 %arg1, -1
    %inst2 = call i32 @zot(i32 noundef %inst)
    %inst5 = call i32 @llvm.usub.sat.i32(i32 %inst2, i32 1)
    ret i32 %inst5
  }

"opt -S -passes=module-inline" gets

  define i32 @snork(i32 %arg, i32 noundef %arg1) {
  bb:
    %inst = xor i32 %arg1, -1
    %inst.i = icmp eq i32 %inst, 0
    %inst1.i = call i32 @llvm.cttz.i32(i32 %inst, i1 true), !range !0
    %inst1.op.i = add nuw nsw i32 %inst1.i, 1
    %inst3.i = select i1 %inst.i, i32 0, i32 %inst1.op.i
    %inst5 = call i32 @llvm.usub.sat.i32(i32 %inst3.i, i32 1)
    ret i32 %inst5
  }

the next inst-combine cannot do much

  define i32 @snork(i32 %arg, i32 noundef %arg1) {
  bb:
    %inst = xor i32 %arg1, -1
    %inst.i = icmp eq i32 %arg1, -1
    %inst1.i = call i32 @llvm.cttz.i32(i32 %inst, i1 true), !range !0
    %inst1.op.i = add nuw nsw i32 %inst1.i, 1
    %inst3.i = select i1 %inst.i, i32 0, i32 %inst1.op.i
    %inst5 = call i32 @llvm.usub.sat.i32(i32 %inst3.i, i32 1)
    ret i32 %inst5
  }

The result before the change looks better:

  define i32 @snork(i32 %arg, i32 noundef %arg1) {
  bb:
    %inst = xor i32 %arg1, -1
    %inst.i = icmp eq i32 %arg1, -1
    %inst1.i = call i32 @llvm.cttz.i32(i32 %inst, i1 true), !range !0
    %inst5 = select i1 %inst.i, i32 0, i32 %inst1.i
    ret i32 %inst5
  }

Furthermore, we could see yet a worse difference if we track it down to the next inline pass which inlines ctlz stuff...


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

https://reviews.llvm.org/D147146



More information about the llvm-commits mailing list