[i386] : FixPR47744; [x32] ICE: in reload_cse_simplify_operands, at postreload.c:403 [was: Re: PATCH [5/n] X32: Supprot 32bit address]

Message ID CAFULd4bbWHs27DQM0qy1zxP7Lcq_ocb5DfwsPxQkGn91fhHPTg@mail.gmail.com
State New
Headers show

Commit Message

Uros Bizjak July 18, 2011, 5:50 p.m.

This alternative patch fixes the problem in ix86_decompose_address,
uncovered by x32 branch. Since x32 branch generates lots of SImode
subreg of DImode values to handle Pmode vs. ptr_mode restrictions, a
latent bug in x86_decompose_address allowed addresses in the (invalid,
see SImode subreg of DImode operation) form of:

(insn 108 106 186 3 (set (reg:SI 40 r11 [207])
        (plus:SI (plus:SI (mult:SI (reg:SI 1 dx [205])
                    (const_int 8 [0x8]))
                (subreg:SI (plus:DI (reg/f:DI 7 sp)
                        (const_int 208 [0xd0])) 0))
            (const_int -160 [0xffffffffffffff60]))) m.i:3 251 {*lea_1_x32}

this form later choked reload to ICE with "error: insn does not
satisfy its constraints:" in reload_cse_simplify_operands, at

Invalid RTX in this example was created by reload trying to eliminate
frame pointer register to RSP+offset.

The solution is to prevent subregs of DImode operations in PLUS
address sequences. We can still allow hard registers, since we are
sure that combine won't touch them and reload won't try to eliminate
them to some reg+offset. Effectively, instead of above RTX, gcc
generates more correct sequence that correctly handles SI and DImodes:

(insn 185 87 89 3 (set (reg:DI 0 ax)
        (plus:DI (reg/f:DI 7 sp)
            (const_int 200 [0xc8]))) pr47744.c:5 248 {*lea_1}

(insn 89 185 90 3 (set (reg:SI 40 r11 [177])
        (plus:SI (plus:SI (mult:SI (reg:SI 40 r11 [175])
                    (const_int 8 [0x8]))
                (reg:SI 0 ax))
            (const_int -160 [0xffffffffffffff60]))) pr47744.c:5 286

So, there is no need for some special lea_* patterns. In addition,
this simple patch removes huge amount of "problematic" kludges from
current x32 branch.

Also, the patch prevents invalid address RTXes for current x86 targets
(32 and 64 bit). There is in fact no protection for i.e. SImode subreg
of HImode operation to combine into invalid address RTX. On a related
note, SImode subreg of a DImode hard register is OK also for 32bit
targets, reload will choose the lower SImode register of a DImode

Oh, and BTW: patched gcc bootstrapped faster for me on x86_64 SNB for
default configure and make -j 8:


real    28m40.314s
user    154m2.612s
sys    8m16.934s



real    27m8.057s
user    142m42.522s
sys    7m41.875s

(see PR for details).

2011-07-18  Uros Bizjak  <ubizjak@gmail.com>

	PR target/47744
	* config/i386/i386.c (ix86_decompose_address): Allow only subregs
	of DImode hard registers in PLUS address chains.

Patch was bootstrapped on x86_64-pc-linux-gnu {,-m32}. H.J. tested it
on x32 target, where the patch fixed all reported failures.

Patch was committed to mainline SVN.



Index: config/i386/i386.c
--- config/i386/i386.c	(revision 176386)
+++ config/i386/i386.c	(working copy)
@@ -11149,8 +11149,13 @@  ix86_decompose_address (rtx addr, struct
 		return 0;
-	    case REG:
 	    case SUBREG:
+	      /* Allow only subregs of DImode hard regs in PLUS chains.  */
+	      if (!register_no_elim_operand (SUBREG_REG (op), DImode))
+		return 0;
+	      /* FALLTHRU */
+	    case REG:
 	      if (!base)
 		base = op;
 	      else if (!index)