This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Avoid LHS paradoxical subregs in make_extranction unless TRULY_NOOP_TRUNCATION
- From: Adam Nemet <anemet at caviumnetworks dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 1 Jul 2009 15:44:21 -0700
- Subject: [PATCH] Avoid LHS paradoxical subregs in make_extranction unless TRULY_NOOP_TRUNCATION
This is the combine counterpart of the expand changes to avoid:
(set (zero_extract:DI (subreg:DI (reg:SI A)) 3 29) ...)
patterns on !TRULY_NOOP_TRUNCATION(SI, DI) targets. This pattern has an
implicit truncation that is invalid if DI->SI truncation requires an actual
instruction.
The bug was uncovered by my next patch that transforms (and (truncate)) into
(truncate (and)). With that change for gcc.target/mips/ins-2.c we transform:
(set (reg/v:SI 195 [ s ])
(ior:SI (and:SI (reg/v:SI 195 [ s ])
(const_int 536870911 [0x1fffffff]))
(ashift:SI (truncate:SI (reg/v:DI 196 [ a+-4 ]))
(const_int 29 [0x1d]))))
into:
(set (zero_extract:DI (subreg:DI (reg/v:SI 195 [ s ]) 0)
(const_int 3 [0x3])
(const_int 29 [0x1d]))
(reg/v:DI 196 [ a+-4 ]))
So far we didn't do this because the RHS is not simplified leading to:
Trying 7, 8 -> 9:
Failed to match this instruction:
(set (zero_extract:DI (subreg:DI (reg/v:SI 195 [ s ]) 0)
(const_int 3 [0x3])
(const_int 29 [0x1d]))
(subreg:DI (and:SI (truncate:SI (reg/v:DI 196 [ a+-4 ]))
(const_int 7 [0x7])) 0))
Ultimately we want the above to be transformed into:
(set (zero_extract:SI (reg:SI A) 3 29) ...)
, which is valid on MIPS64r2. But one step at a time...
Boostrapped and regstested on mips64octeon-linux and regtested on
mipsisa64r2-elf.
OK to install?
Adam
* combine.c (make_extraction): Check TRULY_NOOP_TRUNCATION before
creating LHS paradoxical subregs. Fix surrounding returns to
use NULL_RTX rather than 0.
Index: gcc/combine.c
===================================================================
--- gcc.orig/combine.c 2009-06-30 12:06:41.000000000 -0700
+++ gcc/combine.c 2009-06-30 12:22:10.000000000 -0700
@@ -6692,18 +6692,25 @@ make_extraction (enum machine_mode mode,
inner = adjust_address_nv (inner, wanted_inner_mode, offset);
}
- /* If INNER is not memory, we can always get it into the proper mode. If we
- are changing its mode, POS must be a constant and smaller than the size
- of the new mode. */
+ /* If INNER is not memory, get it into the proper mode. If we are changing
+ its mode, POS must be a constant and smaller than the size of the new
+ mode. */
else if (!MEM_P (inner))
{
+ /* On the LHS, don't create paradoxical subregs implicitely truncating
+ the register unless TRULY_NOOP_TRUNCATION. */
+ if (in_dest
+ && !TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE (inner)),
+ GET_MODE_BITSIZE (wanted_inner_mode)))
+ return NULL_RTX;
+
if (GET_MODE (inner) != wanted_inner_mode
&& (pos_rtx != 0
|| orig_pos + len > GET_MODE_BITSIZE (wanted_inner_mode)))
- return 0;
+ return NULL_RTX;
if (orig_pos < 0)
- return 0;
+ return NULL_RTX;
inner = force_to_mode (inner, wanted_inner_mode,
pos_rtx