This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: C++ ICE with ntohs() and -mcpu=pentiumpro
- To: rguyom at mail dot dotcom dot fr
- Subject: Re: C++ ICE with ntohs() and -mcpu=pentiumpro
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Sun, 19 Mar 2000 11:53:17 -0800
- Cc: gcc-bugs at gcc dot gnu dot org, Richard Henderson <rth at twiddle dot net>, Jan Hubicka <jhub6202 at ss1000 dot ms dot mff dot cuni dot cz>
- Organization: CodeSourcery, LLC
- References: <20000319160509.A21156@pingoo.ifn.fr><20000319184935.A23013@pingoo.ifn.fr>
This change:
Thu Mar 16 17:03:10 MET 2000 Jan Hubicka <jh@suse.cz>
* i386.md (all HI and QI mode non-move patterns): Conditionize
by TARGET_[HQ]IMODE_MATH.
* i386.h (x86_himode_math, x86_qimode_math, x86_promote_hi_regs,
x86_promote_qi_regs): Declare.
(TARGET_HIMODE_MATH, TARGET_QIMODE_MATH, TARGET_PROMOTE_HI_REGS,
TARGET_PROMOTE_QI_REGS): New macros.
(PROMOTE_MODE): New macro.
* i386.c (x86_himode_math, x86_qimode_math, x86_promote_hi_regs,
x86_promote_qi_regs): New global variables.
is causing failure on this test-case:
typedef unsigned short u_short;
#define ntohs(x) \
__extension__ ({ register u_short __X = (x); \
__asm ("xchgb %h1, %b1" \
: "=q" (__X) \
: "0" (__X)); \
__X; })
u_short foo( u_short bar ) { return ntohs( bar ); }
when compiling in C++ with -mcpu=pentiumpro.
But, I don't think the problem really lies with your change,
directly. Here's what happens:
o The `asm' creates a temporary for the output with this code in
`stmt.c':
output_rtx[i] = assign_temp (type, 0, 0, 0);
TREE_VALUE (tail) = make_tree (type, output_rtx[i]);
Here, TYPE is `unsigned short', but assign_temp gives back an
SImode register, due to the PROMOTE_MODE change.
Then, make_tree creates an RTL_EXPR, whose RTL_EXPR_RTL is
the new SImode register.
o Then, in stabilize_reference, we build:
(INDIRECT_REF (SAVE_EXPR (ADDR_EXPR (RTL_EXPR REG:SI))))
We get to stabilize_reference from build_modify_expr from
c_expand_asm_operands; for some reason the C and C++ versions
of both of these functions are slightly different. In particular,
C's build_modify_expr doesn't call stabilize_reference. I don't
think that's the heart of the bug; if we called
stabilize_reference somewhere else the same bug would occur.
o The build_modify_expr call is supposed to copy the temporary
holding the output of the `asm' into the actual user-specified
storage -- in this case `__X'.
o When expanding the SAVE_EXPR we create a temporary to store the
address in. Then, we expand the ADDR_EXPR, which has type
`unsigned short *', so this code in expand_expr, case ADDR_EXPR:
/* If this object is in a register, it must be not
be BLKmode. */
tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
rtx memloc = assign_temp (inner_type, 1, 1, 1);
mark_temp_addr_taken (memloc);
creates an HImode temporary (so that we can take its address). In
assign_temp, PROMOTE_MODE doesn't fire when the last argument is 1,
which indicates not to promote the mode. It actually wouldn't fire
even if that weren't set, because the penultimate argument
indicates that the temporary needs to go in memory, and along that
path there doesn't appear to be any promotion anyhow.
Now, we try to:
emit_move_insn (memloc, op0);
to copy the SImode output of the RTL_EXPR into the HImode
temporary, and abort.
It seems to me that the correct change is to not promote the temporary
outputs of the asm statement. (That does indeed fix the problem.)
They're only going to live long enough to get copied elsewhere anyhow.
But, I'm no expert on this stuff, so I'd much appreciate your help,
Richard, if you've any to offer.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com