[LLVMbugs] [Bug 22227] New: Incorrect result with -O: Possibly inlining and variable reuse issue

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Wed Jan 14 06:08:25 PST 2015


http://llvm.org/bugs/show_bug.cgi?id=22227

            Bug ID: 22227
           Summary: Incorrect result with -O: Possibly inlining and
                    variable reuse issue
           Product: clang
           Version: 3.5
          Hardware: PC
                OS: MacOS X
            Status: NEW
          Severity: normal
          Priority: P
         Component: -New Bugs
          Assignee: unassignedclangbugs at nondot.org
          Reporter: lilbill39 at gmail.com
                CC: llvmbugs at cs.uiuc.edu
    Classification: Unclassified

Created attachment 13687
  --> http://llvm.org/bugs/attachment.cgi?id=13687&action=edit
repro_bad.c/repro_bad.ll show incorrect behavior repro_good.c/repro_good.ll
show correct behavior

The attached program returns different results when compiled with clang with -O
and without -O. This is reproducible using clang 3.5 on Mac OSX 10.9 and was
also seen with 3.4 on Mac.

Reductions using bugpoint and delta were not successful. Valgrind came back
clean on the example compiled with -O -g. I'm happy to try other reduction
steps. From what I saw, seemingly innocuous changes to the code cause the issue
to go away.

To reproduce unzip attachment and:

  clang -O repro_bad.c -o repro_opt
  ./repro_opt

  clang repro_bad.c -o repro_no_opt
  ./repro_no_opt

Notice the difference in the result, the second is the expected result. Search
for "README" in repro_bad.c to find important parts outlined below.

The example is large so I'll describe the structure and what seems to be
happening. The relevant structure is:

void c1_c_linsolve (...) {
creal_T c1_tau[4];
/* No reference to c1_tau */
...
c1_f_xgeqp3(...,c1_tau,...);
}

void c1_f_xgeqp3(...,creal_T c1_tau[4],...) {
<Set elements/fields of c1_tau to 0.0>
for (k = 0; k < 4; ++k) {
  <print value of c1_tau>
  if (p) {
    t = c1_j_zlarfg(...);
    c1_tau[k] = t;
  } else {
    t2 = c1_i_zlarfg(...);
    c1_tau[k] = t2;
  }
  <print value of c1_tau>
}

Each iteration writes one element of c1_tau.

With optimizations on, the values of every element of c1_tau can change between
the two <print value of c1_tau> as is shown in the runtime output.

See the stdout output like:

==========Iteration: 2===========
c1_tau = 
+1.000000 + -0.554875i
+0.000000 + 0.000000i
+0.000000 + 0.000000i
+0.000000 + 0.000000i

Calling zlarfg

c1_tau = 
+0.598883 + 0.419382i
+1.136470 + -0.512310i
+0.527357 + 1.281762i
+0.631325 + 0.417253i

Adding a single printf to main causes the optimized output to be correct (see
last "README" comment). Compile repro_good.c to see this:

  clang -O repro_good.c -o repro_good
  ./repro_good

Attached are IR dumps (repro_good.ll, repro_bad.ll) for repro_good.c and
repro_bad.c both compiled with -O. The main difference seems to be:

< ; ModuleID = 'repro_good.c'
---
> ; ModuleID = 'repro_bad.c'
6154,6175c6159,6165
< c1_c_linsolve.exit.loopexit:                      ; preds =
%.loopexit.i4.i265
<   br label %c1_c_linsolve.exit
< 
< c1_c_linsolve.exit:                               ; preds =
%c1_c_linsolve.exit.loopexit, %.thread.preheader.i.i238, %.preheader.i1.i258
<   call void @llvm.lifetime.end(i64 64, i8* %12) #2
<   call void @llvm.lifetime.end(i64 60, i8* %10) #2
<   call void @llvm.lifetime.end(i64 64, i8* %868) #2
<   call void @llvm.lifetime.end(i64 960, i8* %869) #2
<   call void @llvm.lifetime.end(i64 64, i8* %892) #2
<   call void @llvm.lifetime.end(i64 60, i8* %8) #2
<   call void @llvm.lifetime.end(i64 960, i8* %867) #2
<   call void @llvm.lifetime.end(i64 32, i8* %6)
<   %puts = tail call i32 @puts(i8* getelementptr inbounds ([9 x i8]* @str, i64
0, i64 0))
<   br label %2998
< 
< ; <label>:2998                                    ; preds = %2998,
%c1_c_linsolve.exit
<   %indvars.iv = phi i64 [ 0, %c1_c_linsolve.exit ], [ %indvars.iv.next, %2998
]
<   %2999 = getelementptr inbounds [15 x %struct.creal_T]* %C, i64 0, i64
%indvars.iv, i32 0
<   %3000 = load double* %2999, align 16, !tbaa !18
<   %3001 = getelementptr inbounds [15 x %struct.creal_T]* %C, i64 0, i64
%indvars.iv, i32 1
<   %3002 = load double* %3001, align 8, !tbaa !20
<   %3003 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([11 x
i8]* @.str1, i64 0, i64 0), double %3000, double %3002) #2
---
> c1_c_linsolve.exit:                               ; preds = %c1_c_linsolve.exit.preheader, %c1_c_linsolve.exit
>   %indvars.iv = phi i64 [ %indvars.iv.next, %c1_c_linsolve.exit ], [ 0, %c1_c_linsolve.exit.preheader ]
>   %2998 = getelementptr inbounds [15 x %struct.creal_T]* %C, i64 0, i64 %indvars.iv, i32 0
>   %2999 = load double* %2998, align 16, !tbaa !18
>   %3000 = getelementptr inbounds [15 x %struct.creal_T]* %C, i64 0, i64 %indvars.iv, i32 1
>   %3001 = load double* %3000, align 8, !tbaa !20
>   %3002 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([11 x i8]* @.str, i64 0, i64 0), double %2999, double %3001) #2

-- 
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/20150114/a9e31d68/attachment.html>


More information about the llvm-bugs mailing list