[PATCH] D75799: [JumpThreading] Don't create PHI nodes with "is.constant" values

Kazu Hirata via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Mar 29 01:34:09 PDT 2020


kazu added a comment.

It looks like the testcase can be reduced to the following.  You can check for no jump threading occurring:

  define void @foo(i32 %a, i32 %var) {
  entry:
    %cond1 = icmp ugt i32 %a, 24
    br i1 %cond1, label %bb_constant, label %bb_cond
  
  bb_constant:
    br label %bb_cond
  
  bb_cond:
    %phi = phi i32 [ 24, %bb_constant ], [ %var, %entry ]
    %sext = sext i32 %phi to i64
    %cond2 = icmp ugt i64 %sext, 24
    %is_constant = call i1 @llvm.is.constant.i64(i64 %sext)
    br i1 %cond2, label %bb_then, label %bb_else
  
  bb_then:
    unreachable
  
  bb_else:
    unreachable
  }
  
  ; Function Attrs: nounwind readnone willreturn
  declare i1 @llvm.is.constant.i64(i64) #0
  
  attributes #0 = { nounwind readnone willreturn }

That said, if I remove the sign extension like so, the edge `entry->bb_constant` gets threaded through `bb_cond` to `bb_else` even with your patch.  IIUC, your patch does not catch a case where a PHI node is directly used by `llvm.is_constant`:

  define void @bar(i32 %a, i64 %var) {
  entry:
    %cond1 = icmp ugt i32 %a, 24
    br i1 %cond1, label %bb_constant, label %bb_cond
  
  bb_constant:
    br label %bb_cond
  
  bb_cond:
    %sext = phi i64 [ 24, %bb_constant ], [ %var, %entry ]
    %cond2 = icmp ugt i64 %sext, 24
    %is_constant = call i1 @llvm.is.constant.i64(i64 %sext)
    br i1 %cond2, label %bb_then, label %bb_else
  
  bb_then:
    unreachable
  
  bb_else:
    unreachable
  }
  
  ; Function Attrs: nounwind readnone willreturn
  declare i1 @llvm.is.constant.i64(i64) #0
  
  attributes #0 = { nounwind readnone willreturn }

By the way, `MaybeThreadThroughTwoBasicBlocks` in `JumpThreading.cpp` can thread an edge through two successive basic blocks theses days.  You need to teach `MaybeThreadThroughTwoBasicBlocks` to look out for problematic `llvm.is_constant` also.

FWIW, we catch convergent calls in a somewhat sneaky interface. Specifically, `getJumpThreadDuplicationCost` returns `~0U` when it encounters an instruction that we cannot safely duplicate.  You could teach `getJumpThreadDuplicationCost` to return `~0U` on a problematic `llvm.is_constant`.  This way, you don't have to perform the same check in both `MaybeThreadThroughTwoBasicBlocks` and `TryThreadEdge`.

Now, the `convergent` attribute seems to me like a perfect fit for `llvm.is_constant` as far as I can tell from its description, but I am not sure what side effects it would have on the rest of the compiler.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D75799





More information about the llvm-commits mailing list