https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79058

--- Comment #15 from Dominik Vogt <vogt at linux dot vnet.ibm.com> ---
There's some code to reload such paradoxical subregs in
lra-constraints.c:simplify_operand_subreg():

  /* Force a reload for a paradoxical subreg. For paradoxical subreg, 
     IRA allocates hardreg to the inner pseudo reg according to its mode 
     instead of the outermode, so the size of the hardreg may not be enough 
     to contain the outermode operand, in that case we may need to insert 
     reload for the reg. For the following two types of paradoxical subreg, 
     we need to insert reload: 
     1. If the op_type is OP_IN, and the hardreg could not be paired with 
        other hardreg to contain the outermode operand 
        (checked by in_hard_reg_set_p), we need to insert the reload. 
     2. If the op_type is OP_OUT or OP_INOUT. 

     Here is a paradoxical subreg example showing how the reload is generated: 

     (insn 5 4 7 2 (set (reg:TI 106 [ __comp ]) 
        (subreg:TI (reg:DI 107 [ __comp ]) 0)) {*movti_internal_rex64} 

     In IRA, reg107 is allocated to a DImode hardreg. We use x86-64 as example 
     here, if reg107 is assigned to hardreg R15, because R15 is the last 
     hardreg, compiler cannot find another hardreg to pair with R15 to 
     contain TImode data. So we insert a TImode reload reg180 for it. 
     After reload is inserted: 

     (insn 283 0 0 (set (subreg:DI (reg:TI 180 [orig:107 __comp ] [107]) 0) 
        (reg:DI 107 [ __comp ])) -1 
     (insn 5 4 7 2 (set (reg:TI 106 [ __comp ]) 
        (subreg:TI (reg:TI 180 [orig:107 __comp ] [107]) 0))
{*movti_internal_r\
ex64} 

     Two reload hard registers will be allocated to reg180 to save TImode data 
     in LRA_assign.  */ 
  else if (REG_P (reg) 
           && REGNO (reg) >= FIRST_PSEUDO_REGISTER 
           && (hard_regno = lra_get_regno_hard_regno (REGNO (reg))) >= 0 
           && (hard_regno_nregs[hard_regno][innermode] 
               < hard_regno_nregs[hard_regno][mode]) 
           && (regclass = lra_get_allocno_class (REGNO (reg))) 
           && (type != OP_IN
               || !in_hard_reg_set_p (reg_class_contents[regclass],
                                      mode, hard_regno)))
    { 

But on bigendian systems hard_regno is not the lowest register number, not the
highest number.  So, in_hard_reg_set_p checks whether r0 to r1 is good and
returns true, when the real range should have been r-1 to r0.

Does this patch fix the original problem?

diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -1685,8 +1685,14 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
               < hard_regno_nregs[hard_regno][mode])
           && (regclass = lra_get_allocno_class (REGNO (reg)))
           && (type != OP_IN
-              || !in_hard_reg_set_p (reg_class_contents[regclass],
-                                     mode, hard_regno)))
+              || (BYTES_BIG_ENDIAN
+                  && (hard_regno < hard_regno_nregs[hard_regno][mode] - 1))
+              || (!in_hard_reg_set_p
+                  (reg_class_contents[regclass], mode,
+                   (BYTES_BIG_ENDIAN ? (hard_regno
+                                        - hard_regno_nregs[hard_regno][mode]
+                                        + 1)
+                    : hard_regno)))))
     {
       /* The class will be defined later in curr_insn_transform.  */
       enum reg_class rclass

Reply via email to