This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

optimization/6261: Has this combiner pass bug been fixed?



>Number:         6261
>Category:       optimization
>Synopsis:       Has this combiner pass bug been fixed?
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Apr 11 11:36:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Ted Merrill, ArrayComm, Inc.
>Release:        gcc 3.04
>Organization:
>Environment:
gcc 3.04 conf.g for ARM/thumb with -mthumb running on solaris
>Description:
The problem effects certain types of bit shift/mask
operations, and caused incorrect results from 
newlib math library.
Evidentally if affects targets other than ARM/thumb.
Richard Earnshaw very helpfully provided me a patch
that fixes this problem.
This is just to document this, and ensure that it gets
into 3.1 at least... 
-Ted Merrill
>How-To-Repeat:

>Fix:
See patch in attachment.
We've seen no problems since applying the patch.
>Release-Note:
>Audit-Trail:
>Unformatted:
----gnatsweb-attachment----
Content-Type: text/plain; name="attach.txt"
Content-Disposition: inline; filename="attach.txt"

::::::::::::::
mail1.txt
::::::::::::::
>From ted@arraycomm.com Thu Apr 11 11:25:32 2002
Date: Tue, 26 Feb 2002 19:05:58 -0800 (PST)
From: Ted Merrill <ted@arraycomm.com>
To: Richard.Earnshaw@arm.com
Cc: gcc-bugs@gcc.gnu.org, ted@arraycomm.com, rearnsha@arm.com
Subject: gcc 3.0.4 thumb floating pt bug

Richard,

Following i describe what i believe to be a bug in the arm/thumb
code generation of the latest gcc, and also of gcc since at least 3.0.0.

We've been bedeviled for sometime by e.g. pow(10.0,0.2) returning 0.0
and by other occasional floating point bugs.
I just upgraded to newlib-1.10.0 and gcc-3.0.4, both of which are for
the moment reasonably current, and the problem is still there.
(Target is arm, running in thumb mode; optimization flag is -O).
After long tracing i finally narrowed this down to the following
compiler bug which can be summarized as:

(int j=0x3fe542a5)
newlib-1.10.0/newlib/libm/math/e_pow.c line 273:
if ((j&0x7fffffff) >= 0x4090cc00)
{
    ... under flow code...
}

The underflow code incorrectly executes because the generated assembly
code looks like:

(r5 is j == 0x3fe542a5)
lsl r3,r5,#1        (sets r5 to 0x7fca854a)
ldr r4,(pc-relative location containing 0x812197ff which is 2*0x4090cc00-1)
cmp r3,r4           (sets N=1,Z=0,C=0,V=1)
blt (past overflow code)    

The blt instruction branches only if N!=V which is not the case here,
thus the underflow code executes (which should not be the case).
The correct instruction to use would have been BLS (with appropriate
fiddling of the constant).
The blt would make sense if r3 and r4 were really signed integers.
Although blt would have been appropriate for signed integers,
the optimization clearly(?) recognizes that positive quantities are being
compared (otherwise the optimization could not be done) and 
the comparison must be treated as unsigned.
(I assume the point of the optimization was to avoid loading the
constant 0x7fffffff... a good thing to avoid).

Attached is the .c and .s files of a simple test case.

Thanks for your (otherwise) excellent work.
If you have time to produce a patch in the next week or so i will
probably have time to test it.
In any event, i'd appreciate an ack that you got this message.

Thanks

-Ted Merrill
ArrayComm, Inc.
ted@arraycomm.com




    [ Part 2, "bug1.c"  Text/PLAIN (Name: "bug1.c")  4 lines. ]
    [ Unable to print this part. ]


    [ Part 3, "bug1.s"  Text/PLAIN (Name: "bug1.c.o.s")  100 lines. ]
    [ Unable to print this part. ]

::::::::::::::
bug1.c
::::::::::::::
int bug1(int j)
{
    if ( (j&0x7fffffff) >= 0x4090cc00 )
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

int bug1test(void)
{
    int j = 0x3fe542a5;
    return bug1(j);
}
::::::::::::::
bug1.s
::::::::::::::
@ Generated by gcc 3.0 for ARM/elf
	.file	"bug1.c.o.i"
	.code	16
	.section	.debug_abbrev
.Ldebug_abbrev0:
	.section			.text
.Ltext0:
	.section	.debug_info
.Ldebug_info0:
	.section	.debug_line
.Ldebug_line0:
	.text
	.align	2
	.global	bug1
	.thumb_func
	.type	bug1,function
bug1:
.LFB1:
.LM1:
	push	{r7, lr}
	mov	r7, sp
.LM2:
	lsl	r0, r0, #1
	ldr	r3, .L4
	cmp	r0, r3
	blt	.L2
.LM3:
	mov	r0, #1
	b	.L1
.L2:
.LM4:
	mov	r0, #0
.LM5:
.L1:
	mov	sp, r7
	pop	{r7, pc}
.L5:
	.align	2
.L4:
	.word	-2128504833
.LFE1:
.Lfe1:
	.size	bug1,.Lfe1-bug1
	.align	2
	.global	bug1test
	.thumb_func
	.type	bug1test,function
bug1test:
.LFB2:
.LM6:
	push	{r7, lr}
.LBB2:
	mov	r7, sp
.LM7:
	ldr	r0, .L7
	bl	bug1
.LBE2:
.LM8:
	mov	sp, r7
	pop	{r7, pc}
.L8:
	.align	2
.L7:
	.word	1071989413
.LFE2:
.Lfe2:
	.size	bug1test,.Lfe2-bug1test
	.section			.text
.Letext0:
	.section	.debug_line
	.4byte	.LELT0-.LSLT0
.LSLT0:
	.2byte	0x2
	.4byte	.LELTP0-.LASLTP0
.LASLTP0:
	.byte	0x4
	.byte	0x1
	.byte	0xf6
	.byte	0xf5
	.byte	0xa
	.byte	0x0
	.byte	0x1
	.byte	0x1
	.byte	0x1
	.byte	0x1
	.byte	0x0
	.byte	0x0
	.byte	0x0
	.byte	0x1
	.ascii	"/s/home/ted/_wdsl/gccbug"
	.byte	0
	.byte	0x0
	.ascii	"o/lib.thumb/bug1.c.o.i\000"
	.byte	0x1
	.byte	0x0
	.byte	0x0
	.ascii	"bug1.c\000"
	.byte	0x1
	.byte	0x0
	.byte	0x0
	.byte	0x0
.LELTP0:
	.byte	0x0
	.byte	0x5
	.byte	0x2
	.4byte	.LM1
	.byte	0x4
	.byte	0x2
	.byte	0x15
	.byte	0x0
	.byte	0x5
	.byte	0x2
	.4byte	.LM2
	.byte	0x15
	.byte	0x0
	.byte	0x5
	.byte	0x2
	.4byte	.LM3
	.byte	0x16
	.byte	0x0
	.byte	0x5
	.byte	0x2
	.4byte	.LM4
	.byte	0x18
	.byte	0x0
	.byte	0x5
	.byte	0x2
	.4byte	.LM5
	.byte	0x16
	.byte	0x0
	.byte	0x5
	.byte	0x2
	.4byte	.LM6
	.byte	0x17
	.byte	0x0
	.byte	0x5
	.byte	0x2
	.4byte	.LM7
	.byte	0x16
	.byte	0x0
	.byte	0x5
	.byte	0x2
	.4byte	.LM8
	.byte	0x15
	.byte	0x0
	.byte	0x5
	.byte	0x2
	.4byte	.Letext0
	.byte	0x0
	.byte	0x1
	.byte	0x1
.LELT0:
	.section	.debug_info
	.4byte	0xa5
	.2byte	0x2
	.4byte	.Ldebug_abbrev0
	.byte	0x4
	.byte	0x1
	.4byte	.Ldebug_line0
	.4byte	.Letext0
	.4byte	.Ltext0
	.ascii	"/s/home/ted/_wdsl/gccbug/o/lib.thumb/bug1.c.o.i\000"
	.ascii	"GNU C 3.0\000"
	.byte	0x1
	.byte	0x2
	.4byte	0x7b
	.byte	0x1
	.ascii	"bug1\000"
	.byte	0x2
	.byte	0x2
	.byte	0x1
	.4byte	0x7b
	.4byte	.LFB1
	.4byte	.LFE1
	.byte	0x1
	.byte	0x57
	.byte	0x3
	.ascii	"j\000"
	.byte	0x2
	.byte	0x1
	.4byte	0x7b
	.byte	0x1
	.byte	0x50
	.byte	0x0
	.byte	0x4
	.ascii	"int\000"
	.byte	0x4
	.byte	0x5
	.byte	0x5
	.byte	0x1
	.ascii	"bug1test\000"
	.byte	0x2
	.byte	0xe
	.byte	0x1
	.4byte	0x7b
	.4byte	.LFB2
	.4byte	.LFE2
	.byte	0x1
	.byte	0x57
	.byte	0x6
	.ascii	"j\000"
	.byte	0x2
	.byte	0xf
	.4byte	0x7b
	.byte	0x0
	.byte	0x0
	.section	.debug_abbrev
	.byte	0x1
	.byte	0x11
	.byte	0x1
	.byte	0x10
	.byte	0x6
	.byte	0x12
	.byte	0x1
	.byte	0x11
	.byte	0x1
	.byte	0x3
	.byte	0x8
	.byte	0x25
	.byte	0x8
	.byte	0x13
	.byte	0xb
	.byte	0x0
	.byte	0x0
	.byte	0x2
	.byte	0x2e
	.byte	0x1
	.byte	0x1
	.byte	0x13
	.byte	0x3f
	.byte	0xc
	.byte	0x3
	.byte	0x8
	.byte	0x3a
	.byte	0xb
	.byte	0x3b
	.byte	0xb
	.byte	0x27
	.byte	0xc
	.byte	0x49
	.byte	0x13
	.byte	0x11
	.byte	0x1
	.byte	0x12
	.byte	0x1
	.byte	0x40
	.byte	0xa
	.byte	0x0
	.byte	0x0
	.byte	0x3
	.byte	0x5
	.byte	0x0
	.byte	0x3
	.byte	0x8
	.byte	0x3a
	.byte	0xb
	.byte	0x3b
	.byte	0xb
	.byte	0x49
	.byte	0x13
	.byte	0x2
	.byte	0xa
	.byte	0x0
	.byte	0x0
	.byte	0x4
	.byte	0x24
	.byte	0x0
	.byte	0x3
	.byte	0x8
	.byte	0xb
	.byte	0xb
	.byte	0x3e
	.byte	0xb
	.byte	0x0
	.byte	0x0
	.byte	0x5
	.byte	0x2e
	.byte	0x1
	.byte	0x3f
	.byte	0xc
	.byte	0x3
	.byte	0x8
	.byte	0x3a
	.byte	0xb
	.byte	0x3b
	.byte	0xb
	.byte	0x27
	.byte	0xc
	.byte	0x49
	.byte	0x13
	.byte	0x11
	.byte	0x1
	.byte	0x12
	.byte	0x1
	.byte	0x40
	.byte	0xa
	.byte	0x0
	.byte	0x0
	.byte	0x6
	.byte	0x34
	.byte	0x0
	.byte	0x3
	.byte	0x8
	.byte	0x3a
	.byte	0xb
	.byte	0x3b
	.byte	0xb
	.byte	0x49
	.byte	0x13
	.byte	0x0
	.byte	0x0
	.byte	0x0
	.section	.debug_pubnames
	.4byte	0x24
	.2byte	0x2
	.4byte	.Ldebug_info0
	.4byte	0xa9
	.4byte	0x53
	.ascii	"bug1\000"
	.4byte	0x82
	.ascii	"bug1test\000"
	.4byte	0x0
	.section	.debug_aranges
	.4byte	0x1c
	.2byte	0x2
	.4byte	.Ldebug_info0
	.byte	0x4
	.byte	0x0
	.2byte	0x0
	.2byte	0x0
	.4byte	.Ltext0
	.4byte	.Letext0-.Ltext0
	.4byte	0x0
	.4byte	0x0
	.data
::::::::::::::
mail2.txt
::::::::::::::
>From rearnsha@arm.com Thu Apr 11 11:17:31 2002
Date: Wed, 27 Feb 2002 10:59:23 +0000
From: Richard Earnshaw <rearnsha@arm.com>
Reply-To: Richard.Earnshaw@arm.com
To: Ted Merrill <ted@arraycomm.com>
Cc: Richard.Earnshaw@arm.com, gcc-bugs@gcc.gnu.org, rearnsha@arm.com
Subject: Re: gcc 3.0.4 thumb floating pt bug 

Ted,

This is a generic bug in the combiner pass.

Can you please try this patch.

R.

2002-02-27  Richard Earnshaw  <rearnsha@arm.com>

	* combine.c (simplify_comparision): If simplifying a logical-shift 
	right and compare with constant to eliminate the shift, make the
	comparison unsigned.



    [ Part 2, "gcc-lsrcmp.patch"  Text/X-PATCH (Name: "gcc-lsrcmp.patch")  ]
    [ 21 lines. ]
    [ Unable to print this part. ]

::::::::::::::
gcc-lsrcmp.patch
::::::::::::::
Index: combine.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/combine.c,v
retrieving revision 1.267
diff -p -r1.267 combine.c
*** combine.c	2002/02/20 23:15:00	1.267
--- combine.c	2002/02/27 10:55:40
*************** simplify_comparison (code, pop0, pop1)
*** 10885,10890 ****
--- 10885,10895 ----
  		  || (floor_log2 (const_op) + INTVAL (XEXP (op0, 1))
  		      < mode_width)))
  	    {
+ 	      /* If the shift was logical, then we must make the condition
+ 		 unsigned.  */
+ 	      if (GET_CODE (op0) == LSHIFTRT)
+ 		code = unsigned_condition (code);
+ 
  	      const_op <<= INTVAL (XEXP (op0, 1));
  	      op1 = GEN_INT (const_op);
  	      op0 = XEXP (op0, 0);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]