[llvm-bugs] [Bug 51670] New: LoopUnroll: runtime check introduces branch on poison if fn call doesn't return

via llvm-bugs llvm-bugs at lists.llvm.org
Mon Aug 30 03:35:57 PDT 2021


https://bugs.llvm.org/show_bug.cgi?id=51670

            Bug ID: 51670
           Summary: LoopUnroll: runtime check introduces branch on poison
                    if fn call doesn't return
           Product: libraries
           Version: trunk
          Hardware: All
                OS: All
            Status: NEW
          Keywords: miscompilation
          Severity: normal
          Priority: P
         Component: Loop Optimizer
          Assignee: unassignedbugs at nondot.org
          Reporter: nunoplopes at sapo.pt
                CC: atrick at apple.com, haicheng at codeaurora.org,
                    llvm-bugs at lists.llvm.org, meheff at google.com,
                    nikita.ppv at gmail.com, zhaoshiz at quicinc.com

Test: Transforms/LoopUnroll/loop-remarks.ll

In the test below, @baz may not return. In that case, the source function will
not branch on the possibly poison %exitcond (poison if %n poison).
The target function always branches on %n regardless of whether @baz returns or
not.
The fix is to freeze %n if the code doesn't provably reach the branch.


define i32 @runtime(i32 %n) {
%entry:
  br label %for.body

%for.body:
  %s.06 = phi i32 [ 0, %entry ], [ %add1, %for.body ]
  %i.05 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
  %add = add nsw i32 %i.05, 4
  %call = call i32 @baz(i32 %add)
  %add1 = add nsw i32 %call, %s.06
  %inc = add nsw i32 %i.05, 1
  %exitcond = icmp eq i32 %inc, %n
  br i1 %exitcond, label %for.end, label %for.body

%for.end:
  ret i32 %add1
}
=>
define i32 @runtime(i32 %n) {
%entry:
  %0 = add i32 %n, 4294967295
  %xtraiter = and i32 %n, 3
  %1 = icmp ult i32 %0, 3
  br i1 %1, label %for.end.unr-lcssa, label %entry.new

%entry.new:
  %unroll_iter = sub i32 %n, %xtraiter
  br label %for.body

%for.body:
  %s.06 = phi i32 [ 0, %entry.new ], [ %add1.3, %for.body ]
  %i.05 = phi i32 [ 0, %entry.new ], [ %inc.3, %for.body ]
  %niter = phi i32 [ %unroll_iter, %entry.new ], [ %niter.nsub.3, %for.body ]
  %add = add nsw i32 %i.05, 4
  %call = call i32 @baz(i32 %add)
  %add1 = add nsw i32 %call, %s.06
  %inc = add nsw nuw i32 %i.05, 1
  %niter.nsub = sub i32 %niter, 1
  %add.1 = add nsw i32 %inc, 4
  %call.1 = call i32 @baz(i32 %add.1)
  %add1.1 = add nsw i32 %call.1, %add1
  %inc.1 = add nsw nuw i32 %inc, 1
  %niter.nsub.1 = sub i32 %niter.nsub, 1
  %add.2 = add nsw i32 %inc.1, 4
  %call.2 = call i32 @baz(i32 %add.2)
  %add1.2 = add nsw i32 %call.2, %add1.1
  %inc.2 = add nsw nuw i32 %inc.1, 1
  %niter.nsub.2 = sub i32 %niter.nsub.1, 1
  %add.3 = add nsw i32 %inc.2, 4
  %call.3 = call i32 @baz(i32 %add.3)
  %add1.3 = add nsw i32 %call.3, %add1.2
  %inc.3 = add nsw i32 %inc.2, 1
  %niter.nsub.3 = sub i32 %niter.nsub.2, 1
  %niter.ncmp.3 = icmp eq i32 %niter.nsub.3, 0
  br i1 %niter.ncmp.3, label %for.end.unr-lcssa.loopexit, label %for.body

%for.end.unr-lcssa.loopexit:
  %add1.lcssa.ph.ph = phi i32 [ %add1.3, %for.body ]
  %s.06.unr.ph = phi i32 [ %add1.3, %for.body ]
  %i.05.unr.ph = phi i32 [ %inc.3, %for.body ]
  br label %for.end.unr-lcssa

%for.end.unr-lcssa:
  %add1.lcssa.ph = phi i32 [ undef, %entry ], [ %add1.lcssa.ph.ph,
%for.end.unr-lcssa.loopexit ]
  %s.06.unr = phi i32 [ 0, %entry ], [ %s.06.unr.ph,
%for.end.unr-lcssa.loopexit ]
  %i.05.unr = phi i32 [ 0, %entry ], [ %i.05.unr.ph,
%for.end.unr-lcssa.loopexit ]
  %lcmp.mod = icmp ne i32 %xtraiter, 0
  br i1 %lcmp.mod, label %for.body.epil.preheader, label %for.end

%for.body.epil.preheader:
  br label %for.body.epil

%for.body.epil:
  %add.epil = add nsw i32 %i.05.unr, 4
  %call.epil = call i32 @baz(i32 %add.epil)
  %add1.epil = add nsw i32 %call.epil, %s.06.unr
  %inc.epil = add nsw i32 %i.05.unr, 1
  %epil.iter.sub = sub i32 %xtraiter, 1
  %epil.iter.cmp = icmp ne i32 %epil.iter.sub, 0
  br i1 %epil.iter.cmp, label %for.body.epil.1, label %for.end.epilog-lcssa

%for.body.epil.1:
  %add.epil.1 = add nsw i32 %inc.epil, 4
  %call.epil.1 = call i32 @baz(i32 %add.epil.1)
  %add1.epil.1 = add nsw i32 %call.epil.1, %add1.epil
  %inc.epil.1 = add nsw i32 %inc.epil, 1
  %epil.iter.sub.1 = sub i32 %epil.iter.sub, 1
  %epil.iter.cmp.1 = icmp ne i32 %epil.iter.sub.1, 0
  br i1 %epil.iter.cmp.1, label %for.body.epil.2, label %for.end.epilog-lcssa

%for.body.epil.2:
  %add.epil.2 = add nsw i32 %inc.epil.1, 4
  %call.epil.2 = call i32 @baz(i32 %add.epil.2)
  %add1.epil.2 = add nsw i32 %call.epil.2, %add1.epil.1
  br label %for.end.epilog-lcssa

%for.end.epilog-lcssa:
  %add1.lcssa.ph1 = phi i32 [ %add1.epil, %for.body.epil ], [ %add1.epil.1,
%for.body.epil.1 ], [ %add1.epil.2, %for.body.epil.2 ]
  br label %for.end

%for.end:
  %add1.lcssa = phi i32 [ %add1.lcssa.ph, %for.end.unr-lcssa ], [
%add1.lcssa.ph1, %for.end.epilog-lcssa ]
  ret i32 %add1.lcssa
}
Transformation doesn't verify!
ERROR: Source is more defined than target

Example:
i32 %n = poison

Source:
i32 %s.06 = #x00000000 (0)
i32 %i.05 = #x00000000 (0)
i32 %add = #x00000004 (4)
i32 %call = poison
i32 %add1 = poison
i32 %inc = #x00000001 (1)
i1 %exitcond = poison

Target:
i32 %0 = poison
i32 %xtraiter = poison
i1 %1 = poison

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20210830/31db83fe/attachment.html>


More information about the llvm-bugs mailing list