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]

Re: C++ ICE with ntohs() and -mcpu=pentiumpro



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

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