[PATCH] D123473: [LICM] Only create load in pre-header when promoting load.

Nuno Lopes via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed May 4 10:53:17 PDT 2022


nlopes added a comment.

In D123473#3485355 <https://reviews.llvm.org/D123473#3485355>, @nlopes wrote:

> In D123473#3484702 <https://reviews.llvm.org/D123473#3484702>, @reames wrote:
>
>> I don't think we actually want to do that.  Instead, I think we're making a mistake by considering the load to be immediate UB as opposed to simply returning poison in this case.
>
> You've a point. My concern is that it's surprising to have LLVM introducing a load in a function that's not supposed to do any load. I was thinking about I/O, but those accesses should be volatile. For kernel code it may not be ok, but probably they also use volatile to prevent the compiler messing around instead of relying on `writeonly`

I run LLVM's test suite under Alive2 and found no issues with the load-is-poison semantics for writeonly & argmemonly functions.

Giving it a second thought, I agree with you. These attributes are not there to prevent optimizations, but to enable them. The compiler can do whatever it wants as long as it respects the memory model. The kernel may have a different idea about how the memory model looks like, but for now we don't support such special casing like gcc does (or used to).

So I think we can change it. It's generally better to keep UB usage as low as possible, and yield poison whenever possible. So I favor the change.

As for this patch, it optimizes the case where the loop & store are guaranteed to execute, so no load is needed. This is independent of writeonly.
See this example:

  define void @test(i8 %var, ptr %ptr) {
  entry:
    br label %for.cond
  
  for.cond:
    %i = phi i64 [ 0, %entry ], [ %add, %cond.end ]
    %cmp = icmp ult i64 %i, 2
    br i1 %cmp, label %for.body39, label %for.end
  
  for.body39:
    %div = sdiv i8 %var, 3
    %cmp2 = icmp slt i8 %div, 0
    br i1 %cmp2, label %cond.true, label %cond.false
  
  cond.true:
    br label %cond.end
  
  cond.false:
    br label %cond.end
  
  cond.end:
    %merge = phi i8 [ %div, %cond.true ], [ 0, %cond.false ]
    store i8 %merge, ptr %ptr, align 1
    %add = add i64 %i, 4
    br label %for.cond
  
  for.end:
    ret void
  }

LICM currently produces a load that is replaced with poison with this patch:

  define void @test(i8 %var, ptr %ptr) {
  entry:
    %div = sdiv i8 %var, 3
    %cmp2 = icmp slt i8 %div, 0
    %ptr.promoted = load i8, ptr %ptr, align 1
    br label %for.cond
  ...


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D123473



More information about the llvm-commits mailing list