Bug 18089 - [4.0 regression] Valgrind errors in real.c
Summary: [4.0 regression] Valgrind errors in real.c
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.0.0
: P2 normal
Target Milestone: 4.0.0
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2004-10-20 20:00 UTC by Daniel Jacobowitz
Modified: 2005-01-30 23:02 UTC (History)
4 users (show)

See Also:
Host: i686-pc-linux-gnu
Target:
Build:
Known to work: 3.4.3
Known to fail: 4.0.0
Last reconfirmed: 2005-01-07 15:07:18


Attachments
Testcase. (180 bytes, text/plain)
2004-10-20 20:01 UTC, Daniel Jacobowitz
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel Jacobowitz 2004-10-20 20:00:11 UTC
During an --enable-checking=valgrind (and the normal checks) bootstrap, stage2
gives warnings compiling ggc-common.c.  The first one is:
==29462== Conditional jump or move depends on uninitialised value(s)
==29462==    at 0x853CB22: do_fix_trunc (real.c:963)

963           if (REAL_EXP (r) <= 0)

(gdb) bt
#0  0x0853cb22 in do_fix_trunc (r=0x52bfd9cc, a=0x52bfd9b4) at
/home/drow/src/gcc/gcc/real.c:963
#1  0x0853e1be in real_trunc (r=0x52bfd9b4, mode=VOIDmode, x=0x7) at
/home/drow/src/gcc/gcc/real.c:4610
#2  0x0825fcaf in fold_convert_const (code=FIX_TRUNC_EXPR, type=0x1bb93488,
arg1=0x1c194a80)
    at /home/drow/src/gcc/gcc/fold-const.c:1754
#3  0x080f9a0b in evaluate_stmt (stmt=Variable "stmt" is not available.
) at /home/drow/src/gcc/gcc/tree-ssa-ccp.c:853
#4  0x080fa0a8 in ccp_visit_stmt (stmt=0x1c191f54, taken_edge_p=0x7,
output_p=0x4000007)
    at /home/drow/src/gcc/gcc/tree-ssa-ccp.c:1065
#5  0x08146f48 in simulate_stmt (stmt=0x1c191f54) at
/home/drow/src/gcc/gcc/tree-ssa-propagate.c:306
#6  0x081474f0 in ssa_propagate (visit_stmt=0x4000007, visit_phi=0x4000007)
    at /home/drow/src/gcc/gcc/tree-ssa-propagate.c:429
#7  0x080fa77c in execute_ssa_ccp () at /home/drow/src/gcc/gcc/tree-ssa-ccp.c:1207

The code being compiled is the check of min_expand.  It looks like stage1 has
miscompiled stage2, because do_fix_trunc starts by copying *r to *a, but at this
read of *r r->uexp is still undefined.  That's just a guess.

Compiler is: GNU C version 4.0.0 20041012 (it took three days and a bit to do
the valgrind bootstrap).
Comment 1 Daniel Jacobowitz 2004-10-20 20:01:17 UTC
Created attachment 7389 [details]
Testcase.

valgrind --db-attach=yes gcc/stage2/cc1 -fpreprocessed ggc-common2.i -quiet -O1
-o ggc-common.s
Comment 2 Andrew Pinski 2004-10-20 20:18:06 UTC
          REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);


Comment 3 Steven Bosscher 2004-12-19 15:08:24 UTC
Any news about this one? 
 
Comment 4 Volker Reichelt 2005-01-07 15:07:18 UTC
I just stumbled over this one, too.
Even shorter testcase: valgrind --tool=memcheck cc1 -quiet vg.c

==================================
int foo() { return 1.0 + 1.1; }
==================================
Comment 5 Volker Reichelt 2005-01-08 21:06:25 UTC
Roger, the problem appears with your patch for PR17151:
http://gcc.gnu.org/ml/gcc-cvs/2004-09/msg01231.html

It looks like this causes a miscompilation of the stage2 compiler.
Comment 6 Volker Reichelt 2005-01-10 09:33:44 UTC
Just another data point:
Reverting the patch on current mainline makes the problem disappear.
Comment 7 Jakub Jelinek 2005-01-14 18:35:00 UTC
Are you sure this is not just a bug in valgrind?
I have verified that with current CVS I get
ERROR SUMMARY: 37 errors from 21 contexts (suppressed: 12 from 1)
while if I rebuild stage1's combine.o with Roger's patch backed out, link new
stage1 cc1, then rebuild stage2's real.o with the new stage1 cc1 and link new
stage2 cc1, I get
ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 12 from 1)

I did a binary search on real.s and e.g. one of the valgrind errors is triggered
by following change in real.s:
@@ -6453,8 +6453,8 @@ round_for_format:
        .p2align 2,,3
 .L997:
        movl    (%ebp), %eax
+       subl    $-2147483648, %eax
        shrl    $5, %eax
-       xorl    $67108864, %eax
        subl    $67108864, %eax
        cmpl    %eax, 32(%esp)
        jge     .L979

With the xorl there are no errors, with subl there is one error.
But I don't see any functional difference between these two.
If I replace 28 occurences of these subl $0x80000000, %eax before >> 5 to
xorl $0x4000000, %eax after >> 5 (I left out encoders/decoders of non-ieee
formats), valgrind stops reporting any errors.

So to me this looks like valgrind not handling subl $0x80000000, %eax
instruction correctly.

Do you agree?

I used valgrind 2.2.0.
Comment 8 Jakub Jelinek 2005-01-14 20:20:42 UTC
BTW, if I replace all
       subl    $-2147483648, %eax
instructions in real.s by:
       xorl    $-2147483648, %eax
(note that all such instructions are followed either by shrl, or addl, so
any differences in %eflags are ignored), it shuts valgrind up as well.

Comment 9 Jakub Jelinek 2005-01-14 20:36:37 UTC
To prove this is a valgrind bug and not GCC bug, I wrote a small self-contained
testcase on which valgrind complains:
#define EXP_BITS (32 - 5)
struct real_value
{
  unsigned int cl : 2;
  unsigned int sign : 1;
  unsigned int signalling : 1;
  unsigned int canonical : 1;
  unsigned int uexp : EXP_BITS;
  unsigned long sig[4];
};

#if defined __i386__ && defined USE_ASM
#define REAL_EXP(REAL) \
  ({ int ret; \
     __asm ("movl (%%eax),%%eax; subl $0x80000000,%%eax; shrl $5, %%eax; subl
$0x4000000,%%eax" \
            : "=a" (ret) : "a" (REAL), "m" (*(REAL))); \
     ret; })
#else
#define REAL_EXP(REAL) \
  ((int)((REAL)->uexp ^ (unsigned int)(1 << (EXP_BITS - 1))) \
   - (1 << (EXP_BITS - 1)))
#endif

#if __GNUC__ >= 3
#define __noinline __attribute ((noinline))
#else
#define __noinline
#endif

int dummy;

void __noinline
bar (void)
{
  ++dummy;
}

void __noinline
foo (struct real_value *r)
{
  if (REAL_EXP (r) <= 5)
    bar ();
}

int
main (void)
{
  struct real_value r;
  r.uexp = 0x21;
  foo (&r);
  return 0;
}

Both with -DUSE_ASM and without CVS GCC generates the same assembly and in both
cases valgrind --tool=memcheck /tmp/test fails with:
==31022== Conditional jump or move depends on uninitialised value(s)
==31022==    at 0x8048368: foo (test.c:41)
==31022==    by 0x80483A4: main (test.c:50)
Comment 10 Andrew Pinski 2005-01-14 21:45:53 UTC
So closing as invalid, please report this to valgrind then.
Comment 11 Volker Reichelt 2005-01-30 23:02:29 UTC
Just for reference, this is now tracked in
http://bugs.kde.org/show_bug.cgi?id=97042