[llvm-dev] Dereferenceable load semantics & LICM

Piotr Padlewski via llvm-dev llvm-dev at lists.llvm.org
Fri Mar 31 09:07:21 PDT 2017


Hi all,
I have a question about dereferenceable metadata on load instruction. I
have a patch (https://reviews.llvm.org/D31539) for LICM that hoists loads
with !invariant.group.
The motivation example is devirtualization:

struct A {
   virtual void foo();
};
int bar();
void indirect(A &a) {
  while(bar())
       a.foo();
}

With -O2 -fstrict-vtable-pointers we get:

define void @hoist(%struct.A* dereferenceable(8)) {
entry:
  %call1 = tail call i32 @bar()
  %tobool2 = icmp eq i32 %call1, 0
  br i1 %tobool2, label %while.end, label %while.body.lr.ph

while.body.lr.ph:                                 ; preds = %entry
  %b = bitcast %struct.A* %0 to void (%struct.A*)***

  br label %while.body

while.body:                                       ; preds = %
while.body.lr.ph, %while.body
  %vtable = load void (%struct.A*)**, void (%struct.A*)*** %b, align 8,
!invariant.group !0
  %1 = load void (%struct.A*)*, void (%struct.A*)** %vtable, align 8,
!invariant.load !0
  tail call void %1(%struct.A* %0)
  %call = tail call i32 @bar()
  %tobool = icmp eq i32 %call, 0
  br i1 %tobool, label %while.end.loopexit, label %while.body

while.end.loopexit:                               ; preds = %while.body
  br label %while.end

while.end:                                        ; preds =
%while.end.loopexit, %entry
  ret void
}



We know that the load of vptr and virtual function will not change in this
loop, which is indicated by !invariant.group.
Hoisting invariant.group load is legal because %b is dereferenceable, but
hoisting next load is illegal by LICM because it can't prove that %vtable
is dereferenceable.
But if I add dereferenceable metadata on vtable load like

%vtable = load void (%struct.A*)**, void (%struct.A*)*** %b, align 8,
!invariant.group !0, !dereferenceable !1
!1 = !{i64 8}

Then it doesn't help either, because LICM drops !dereferencealbe metadata
when hoisting (and adding it would be invalid, because we don't know if it
is also dereferenceable in hoisted block).

On the other hand, after performing my LICM of !invariant.group load, GVN
hoists the second load and I am not sure why it is legal then.

Any ideas?

Piotr
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170331/f2c01bef/attachment.html>


More information about the llvm-dev mailing list