Article View: gnu.gcc.bug
Article #1039GCC 2.2.2 patch to improve quality of code for (expr&const)!=0
From: Paul Eggert
Date: Tue, 01 Sep 1992 23:10
Date: Tue, 01 Sep 1992 23:10
190 lines
7868 bytes
7868 bytes
The following patch uniformly improves the quality of the generated code for
for all programs that I have looked at on my machine (Sparc, SunOS 4.1.2);
this includes the entire GCC source code. For example, given the program
void f() { if (g() & 32768) h(); }
the patched GCC generates two fewer machine instructions by avoiding an
unnecessary shift and compare, as follows (diff --side-by-side output):
----- GCC 2.2.2 ----- ----- GCC 2.2.2 with patch -----
_f: _f:
save %sp,-112,%sp save %sp,-112,%sp
call _g,0 call _g,0
nop nop
sethi %hi(-32768),%o1 | sethi %hi(32768),%o1
and %o0,%o1,%o0 | andcc %o0,%o1,%g0
sll %o0,16,%o0 <
cmp %o0,0 <
be L2 be L2
nop nop
call _h,0 call _h,0
nop nop
L2: L2:
ret ret
restore restore
I'm fairly sure the patch does not introduce a compiler bug on any 2's
complement host, but I'm not sure whether it leads to better quality code on
all hosts. If this patch loses on some hosts, perhaps a configuration
variable is needed to include it conditionally.
Tue Sep 1 22:55:59 1992 Paul Eggert (eggert@twinsun.com)
* c-convert.c, cp-cvt.c (convert_to_integer): Prefer unsigned
arithmetic if the output type is unsigned and is no more precise than
the computation type. This avoids unnecessary sign extension.
===================================================================
RCS file: c-convert.c,v
retrieving revision 2.2
diff -c -r2.2 c-convert.c
*** c-convert.c 1992/04/21 18:00:03 2.2
--- c-convert.c 1992/09/01 22:55:59
***************
*** 232,242 ****
{
/* Don't do unsigned arithmetic where signed was wanted,
or vice versa.
! Exception: if either of the original operands were
unsigned then can safely do the work as unsigned.
And we may need to do it as unsigned
if we truncate to the original size. */
! typex = ((TREE_UNSIGNED (TREE_TYPE (expr))
|| TREE_UNSIGNED (TREE_TYPE (arg0))
|| TREE_UNSIGNED (TREE_TYPE (arg1)))
? unsigned_type (typex) : signed_type (typex));
--- 232,247 ----
{
/* Don't do unsigned arithmetic where signed was wanted,
or vice versa.
! Exception 1: if we will eventually truncate
! the result to unsigned, then do the work as unsigned;
! this can prevent unnecessary sign-extension.
! Exception 2: if either of the original operands were
unsigned then can safely do the work as unsigned.
And we may need to do it as unsigned
if we truncate to the original size. */
! typex = (((outprec <= TYPE_PRECISION (typex)
! && TREE_UNSIGNED (type))
! || TREE_UNSIGNED (TREE_TYPE (expr))
|| TREE_UNSIGNED (TREE_TYPE (arg0))
|| TREE_UNSIGNED (TREE_TYPE (arg1)))
? unsigned_type (typex) : signed_type (typex));
***************
*** 284,290 ****
{
/* Don't do unsigned arithmetic where signed was wanted,
or vice versa. */
! typex = (TREE_UNSIGNED (TREE_TYPE (expr))
? unsigned_type (typex) : signed_type (typex));
return convert (type,
build_unary_op (ex_form,
--- 289,297 ----
{
/* Don't do unsigned arithmetic where signed was wanted,
or vice versa. */
! typex = (((outprec <= TYPE_PRECISION (typex)
! && TREE_UNSIGNED (type))
! || TREE_UNSIGNED (TREE_TYPE (expr)))
? unsigned_type (typex) : signed_type (typex));
return convert (type,
build_unary_op (ex_form,
***************
*** 327,333 ****
{
/* Don't do unsigned arithmetic where signed was wanted,
or vice versa. */
! typex = (TREE_UNSIGNED (TREE_TYPE (expr))
? unsigned_type (typex) : signed_type (typex));
return convert (type,
fold (build (COND_EXPR, typex,
--- 334,342 ----
{
/* Don't do unsigned arithmetic where signed was wanted,
or vice versa. */
! typex = (((outprec <= TYPE_PRECISION (typex)
! && TREE_UNSIGNED (type))
! || TREE_UNSIGNED (TREE_TYPE (expr)))
? unsigned_type (typex) : signed_type (typex));
return convert (type,
fold (build (COND_EXPR, typex,
===================================================================
RCS file: cp-cvt.c,v
retrieving revision 2.2
diff -c -r2.2 cp-cvt.c
*** cp-cvt.c 1992/04/23 03:18:58 2.2
--- cp-cvt.c 1992/09/01 22:56:05
***************
*** 831,842 ****
{
/* Don't do unsigned arithmetic where signed was wanted,
or vice versa.
! Exception: if the original operands were unsigned
! then can safely do the work as unsigned.
And we may need to do it as unsigned
if we truncate to the original size. */
! typex = ((TREE_UNSIGNED (TREE_TYPE (expr))
! || TREE_UNSIGNED (TREE_TYPE (arg0)))
? unsigned_type (typex) : signed_type (typex));
return convert (type,
build_binary_op_nodefault (ex_form,
--- 831,848 ----
{
/* Don't do unsigned arithmetic where signed was wanted,
or vice versa.
! Exception 1: if we will eventually truncate
! the result, then do the work as unsigned;
! this can prevent unnecessary sign-extension.
! Exception 2: if either of the original operands were
! unsigned then can safely do the work as unsigned.
And we may need to do it as unsigned
if we truncate to the original size. */
! typex = (((outprec <= TYPE_PRECISION (typex)
! && TREE_UNSIGNED (type))
! || TREE_UNSIGNED (TREE_TYPE (expr))
! || TREE_UNSIGNED (TREE_TYPE (arg0))
! || TREE_UNSIGNED (TREE_TYPE (arg1)))
? unsigned_type (typex) : signed_type (typex));
return convert (type,
build_binary_op_nodefault (ex_form,
***************
*** 883,889 ****
{
/* Don't do unsigned arithmetic where signed was wanted,
or vice versa. */
! typex = (TREE_UNSIGNED (TREE_TYPE (expr))
? unsigned_type (typex) : signed_type (typex));
return convert (type,
build_unary_op (ex_form,
--- 889,897 ----
{
/* Don't do unsigned arithmetic where signed was wanted,
or vice versa. */
! typex = (((outprec <= TYPE_PRECISION (typex)
! && TREE_UNSIGNED (type))
! || TREE_UNSIGNED (TREE_TYPE (expr)))
? unsigned_type (typex) : signed_type (typex));
return convert (type,
build_unary_op (ex_form,
***************
*** 926,932 ****
{
/* Don't do unsigned arithmetic where signed was wanted,
or vice versa. */
! typex = (TREE_UNSIGNED (TREE_TYPE (expr))
? unsigned_type (typex) : signed_type (typex));
return convert (type,
fold (build (COND_EXPR, typex,
--- 934,942 ----
{
/* Don't do unsigned arithmetic where signed was wanted,
or vice versa. */
! typex = (((outprec <= TYPE_PRECISION (typex)
! && TREE_UNSIGNED (type))
! || TREE_UNSIGNED (TREE_TYPE (expr)))
? unsigned_type (typex) : signed_type (typex));
return convert (type,
fold (build (COND_EXPR, typex,
Technical Details
Message-ID:
<9209012310.AA22819@farside.twinsun.com>Path:
arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!twinsun.COM!eggertShow Full Headers
Complete Article Headers
Newsgroups: gnu.gcc.bug Path: arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!twinsun.COM!eggert From: eggert@twinsun.COM (Paul Eggert) Subject: GCC 2.2.2 patch to improve quality of code for (expr&const)!=0 Message-ID: <9209012310.AA22819@farside.twinsun.com> Sender: gnulists@ai.mit.edu Organization: GNUs Not Usenet Distribution: gnu Date: Tue, 1 Sep 1992 23:10:58 GMT Approved: bug-gcc@prep.ai.mit.edu Lines: 191