[llvm-dev] Bug in pass 'ipsccp' on function attribute 'argmemonly'?

Fangqing Du via llvm-dev llvm-dev at lists.llvm.org
Fri Jul 10 19:04:41 PDT 2020


Hi all,

Let's see an example (from Alexandre Isoard) first:
****************************************************************************************
; RUN: opt -ipsccp -deadargelim -licm -O2 -S < %s

@g = internal global i32 0

; Function Attrs: argmemonly
define internal void @foo(i32* nonnull dereferenceable(4) %arg, i32 %val) #0
 {
entry:
  store i32 %val, i32* %arg
  ret void
}

define i32 @bar(i32 %n) {
entry:
  store i32 1, i32* @g
  br label %loop

loop:                                              ; preds = %bb1, %bb
  %i = phi i32 [ %i.inc, %loop ], [ 0, %entry ]
  %g.val = load i32, i32* @g
  %g.inc = add nuw i32 %g.val, 1
  tail call void @foo(i32* @g, i32 %g.inc)
  %i.inc = add nuw i32 %i, 1
  %cond = icmp eq i32 %i.inc, %n
  br i1 %cond, label %exit, label %loop

exit:                                              ; preds = %bb1
  ret i32 %g.val
}

declare void @llvm.assume(i1)

attributes #0 = { argmemonly }
****************************************************************************************
With opt cmd '-ipsccp -deadargelim -licm -O2', function @bar will return
constant value 1, instead of correct value %n. This is crazy, right?
Let's see what happens here.
Due to pass 'ipsccp' replaced the argument of function '@foo' with global
variable '@g', but keeps attr 'argmemonly' there, so pass 'licm' will hoist
the load of '@g' before the loop (as the value of @g isn't changed, but it
is changed), and will cause function return wrong constant value '1',
instead of '%n' (the correct value) , like following:
****************************************************************************************

; Function Attrs: nofree norecurse nounwind writeonly
define i32 @bar(i32 %n) local_unnamed_addr #0 {
entry:
  ret i32 1
}

attributes #0 = { nofree norecurse nounwind writeonly }
****************************************************************************************


And if remove the 'argmemonly' attribute, function @bar will return the
correct value:
****************************************************************************************

; Function Attrs: nofree norecurse nounwind
define i32 @bar(i32 %n) local_unnamed_addr #0 {
entry:
  ret i32 %n
}
****************************************************************************************


So if function attribute 'argmemonly' on function @foo is correct, then
there's a bug in pass 'ipsccp'. When it replaces the function local value
with global variable, then it shoud remember to remove this function
attribute.

Thanks,
Fangqing
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200710/71e12c6e/attachment.html>


More information about the llvm-dev mailing list