[llvm-bugs] [Bug 51766] New: loop-bound-split miscompile (resulted in unconditional ubsan overflow reported in a test case)

via llvm-bugs llvm-bugs at lists.llvm.org
Mon Sep 6 02:22:07 PDT 2021


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

            Bug ID: 51766
           Summary: loop-bound-split miscompile (resulted in unconditional
                    ubsan overflow reported in a test case)
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Loop Optimizer
          Assignee: unassignedbugs at nondot.org
          Reporter: bjorn.a.pettersson at ericsson.com
                CC: jingu.kang at arm.com, llvm-bugs at lists.llvm.org

Here is a reduced test case based on running some tests involving
loop-bound-split pass and having ubsan enabled.

;------------------------------------------------------------------------
; RUN: opt < %s -S -passes='loop-bound-split'

define i16 @main(i16 %qqq) {
entry:
  br label %for.body

for.body:
  %t0 = phi i16 [ 0, %entry ], [ %t8, %cont19 ]
  %t1 = shl nuw nsw i16 %t0, 1
  %t2 = add i16 %t1, %qqq
  %.not9 = icmp ult i16 %t2, %qqq
  br i1 %.not9, label %handler.pointer_overflow, label %cont15.critedge

handler.pointer_overflow:
  call void @__ubsan_handle_pointer_overflow()
  br label %cont19

cont15.critedge:
  br label %cont19

cont19:
  %t8 = add nuw nsw i16 %t0, 1
  %exitcond.not = icmp eq i16 %t8, 3
  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body

for.cond.cleanup:
  ret i16 0
}

declare dso_local void @__ubsan_handle_pointer_overflow()
;-------------------------------------------------------------------------


First iteration in the for.body we have %t0=0, which gives %t1=0, which gives
%t2=%qqq, which gives %.not9=false. So we should not jump to
%handler.pointer.overflow. And if %qqq for example it 100 we will bail out from
the loop before any unsigned wrap-around when calculating %t2.

However, loop-bound-split pass is transforming the IR above into this (which
has an unconditional branch from for.body to %handler.pointer_overflow):

;--------------------------------------------------------------------------

define i16 @main(i16 %qqq) {
entry:
  br label %entry.split

entry.split:                                      ; preds = %entry
  %new.bound = call i16 @llvm.umin.i16(i16 %qqq, i16 2)
  br label %for.body

for.body:                                         ; preds = %cont19,
%entry.split
  %t0 = phi i16 [ 0, %entry.split ], [ %t8, %cont19 ]
  %t1 = shl nuw nsw i16 %t0, 1
  %t2 = add i16 %t1, %qqq
  %.not9 = icmp ult i16 %t2, %qqq
  br i1 true, label %handler.pointer_overflow, label %cont15.critedge

handler.pointer_overflow:                         ; preds = %for.body
  call void @__ubsan_handle_pointer_overflow()
  br label %cont19

cont15.critedge:                                  ; preds = %for.body
  br label %cont19

cont19:                                           ; preds = %cont15.critedge,
%handler.pointer_overflow
  %t8 = add nuw nsw i16 %t0, 1
  %exitcond.not = icmp eq i16 %t8, %new.bound
  br i1 %exitcond.not, label %entry.split.split, label %for.body

entry.split.split:                                ; preds = %cont19
  %t8.lcssa = phi i16 [ %t8, %cont19 ]
  %0 = icmp ne i16 %t8.lcssa, 3
  br i1 %0, label %for.body.split.preheader, label %for.cond.cleanup

for.body.split.preheader:                         ; preds = %entry.split.split
  br label %for.body.split

for.body.split:                                   ; preds =
%for.body.split.preheader, %cont19.split
  %t0.split = phi i16 [ %t8.split, %cont19.split ], [ %new.bound,
%for.body.split.preheader ]
  %t1.split = shl nuw nsw i16 %t0.split, 1
  %t2.split = add i16 %t1.split, %qqq
  %.not9.split = icmp ult i16 %t2.split, %qqq
  br i1 false, label %handler.pointer_overflow.split, label
%cont15.critedge.split

cont15.critedge.split:                            ; preds = %for.body.split
  br label %cont19.split

handler.pointer_overflow.split:                   ; preds = %for.body.split
  call void @__ubsan_handle_pointer_overflow()
  br label %cont19.split

cont19.split:                                     ; preds =
%handler.pointer_overflow.split, %cont15.critedge.split
  %t8.split = add nuw nsw i16 %t0.split, 1
  %exitcond.not.split = icmp eq i16 %t8.split, 3
  br i1 %exitcond.not.split, label %for.cond.cleanup.loopexit, label
%for.body.split

for.cond.cleanup.loopexit:                        ; preds = %cont19.split
  br label %for.cond.cleanup

for.cond.cleanup:                                 ; preds =
%for.cond.cleanup.loopexit, %entry.split.split
  ret i16 0
}

declare dso_local void @__ubsan_handle_pointer_overflow()

; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
declare i16 @llvm.umin.i16(i16, i16) #0

attributes #0 = { nofree nosync nounwind readnone speculatable willreturn }

;--------------------------------------------------------------------------

-- 
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/20210906/e8eed3ce/attachment-0001.html>


More information about the llvm-bugs mailing list