From: Vladimir Makarov <vmaka...@redhat.com>
Date: Fri, 4 Sep 2015 10:00:54 -0400

> LRA porting frequently needs changing in constraints.md, <target>.c,
> and <target>.md files.

I did make such changes, trust me :-)

First obstacle was that, unlike reload, LRA is very strict about
register constraints.  If a constraint doesn't evaluate to a
register class, LRA refuses to consider it a register.

So we had this ugly thing:

(define_constraint "U"
 "Pseudo-register or hard even-numbered integer register"
 (and (match_test "TARGET_ARCH32")
      (match_code "reg")
      (ior (match_test "REGNO (op) < FIRST_PSEUDO_REGISTER")
           (not (match_test "reload_in_progress && reg_renumber [REGNO (op)] < 
0")))
      (match_test "register_ok_for_ldd (op)")))

A few years ago I tried the simple thing, changing this to a plain
GENERAL_REGS register constraint and hoping that HARD_REGNO_OK would
properly enforce the even register number requirement.  Back then it
didn't work but now it appears to work properly.

I've included the full patch I am working with below in case you are
curious.

> I don't think we should add a new LRA code calling process_address
> before adding insns for further processing.  LRA just needs to get
> operands from insns to make them valid.  So again I'd try to make insn
> recognizable for LRA first and only if it does not work then think
> about other solutions in case when such change creates other problems
> (it is hard for me to predict LRA behaviour definitely just reading
> source files and not knowing sparc port well).

If LRA is prepared to do a blind emit_move_insn() on an arbitrary MEM,
before it even validates the displacements in such a MEM as needing
reloads or not, it has to do something to accomodate this situation.

If LRA had not done the special SUBREG processing on this insn, it
indeed would have fixed up the invalid displacement using a reload.

Anyways, here is the patch I am working with.

diff --git a/gcc/config/sparc/constraints.md b/gcc/config/sparc/constraints.md
index e12efa1..7a18879 100644
--- a/gcc/config/sparc/constraints.md
+++ b/gcc/config/sparc/constraints.md
@@ -44,6 +44,8 @@
 (define_register_constraint "h" "(TARGET_V9 && TARGET_V8PLUS ? I64_REGS : 
NO_REGS)"
  "64-bit global or out register in V8+ mode")
 
+(define_register_constraint "U" "(TARGET_ARCH32 ? GENERAL_REGS : NO_REGS)")
+
 ;; Floating-point constant constraints
 
 (define_constraint "G"
@@ -135,51 +137,6 @@
       (match_code "mem")
       (match_test "memory_ok_for_ldd (op)")))
 
-;; This awkward register constraint is necessary because it is not
-;; possible to express the "must be even numbered register" condition
-;; using register classes.  The problem is that membership in a
-;; register class requires that all registers of a multi-regno
-;; register be included in the set.  It is add_to_hard_reg_set
-;; and in_hard_reg_set_p which populate and test regsets with these
-;; semantics.
-;;
-;; So this means that we would have to put both the even and odd
-;; register into the register class, which would not restrict things
-;; at all.
-;;
-;; Using a combination of GENERAL_REGS and HARD_REGNO_MODE_OK is not a
-;; full solution either.  In fact, even though IRA uses the macro
-;; HARD_REGNO_MODE_OK to calculate which registers are prohibited from
-;; use in certain modes, it still can allocate an odd hard register
-;; for DImode values.  This is due to how IRA populates the table
-;; ira_useful_class_mode_regs[][].  It suffers from the same problem
-;; as using a register class to describe this restriction.  Namely, it
-;; sets both the odd and even part of an even register pair in the
-;; regset.  Therefore IRA can and will allocate odd registers for
-;; DImode values on 32-bit.
-;;
-;; There are legitimate cases where DImode values can end up in odd
-;; hard registers, the most notable example is argument passing.
-;;
-;; What saves us is reload and the DImode splitters.  Both are
-;; necessary.  The odd register splitters cannot match if, for
-;; example, we have a non-offsetable MEM.  Reload will notice this
-;; case and reload the address into a single hard register.
-;;
-;; The real downfall of this awkward register constraint is that it does
-;; not evaluate to a true register class like a bonafide use of
-;; define_register_constraint would.  This currently means that we cannot
-;; use LRA on Sparc, since the constraint processing of LRA really depends
-;; upon whether an extra constraint is for registers or not.  It uses
-;; reg_class_for_constraint, and checks it against NO_REGS.
-(define_constraint "U"
- "Pseudo-register or hard even-numbered integer register"
- (and (match_test "TARGET_ARCH32")
-      (match_code "reg")
-      (ior (match_test "REGNO (op) < FIRST_PSEUDO_REGISTER")
-          (not (match_test "reload_in_progress && reg_renumber [REGNO (op)] < 
0")))
-      (match_test "register_ok_for_ldd (op)")))
-
 ;; Equivalent to 'T' but available in 64-bit mode
 (define_memory_constraint "W"
  "Memory reference for 'e' constraint floating-point register"
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index ed8a166..2223998 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -808,6 +808,9 @@ char sparc_hard_reg_printed[8];
 #undef TARGET_CAN_ELIMINATE
 #define TARGET_CAN_ELIMINATE sparc_can_eliminate
 
+#undef TARGET_LRA_P
+#define TARGET_LRA_P hook_bool_void_true
+
 #undef  TARGET_PREFERRED_RELOAD_CLASS
 #define TARGET_PREFERRED_RELOAD_CLASS sparc_preferred_reload_class
 
@@ -1746,7 +1749,7 @@ sparc_expand_move (machine_mode mode, rtx *operands)
       if (register_or_zero_operand (operands[1], mode))
        return false;
 
-      if (!reload_in_progress)
+      if (! lra_in_progress)
        {
          operands[0] = validize_mem (operands[0]);
          operands[1] = force_reg (mode, operands[1]);
@@ -1790,7 +1793,7 @@ sparc_expand_move (machine_mode mode, rtx *operands)
        {
          operands[1]
            = sparc_legitimize_pic_address (operands[1],
-                                           reload_in_progress
+                                           lra_in_progress
                                            ? operands[0] : NULL_RTX);
          return false;
        }
@@ -1827,7 +1830,7 @@ sparc_expand_move (machine_mode mode, rtx *operands)
        return false;
 
       operands[1] = force_const_mem (mode, operands[1]);
-      if (!reload_in_progress)
+      if (! lra_in_progress)
        operands[1] = validize_mem (operands[1]);
       return false;
     }
@@ -3757,11 +3760,13 @@ check_pic (int i)
     {
     case 1:
       op = recog_data.operand[i];
-      gcc_assert (GET_CODE (op) != SYMBOL_REF
-                 && (GET_CODE (op) != CONST
-                     || (GET_CODE (XEXP (op, 0)) == MINUS
-                         && XEXP (XEXP (op, 0), 0) == sparc_got ()
-                         && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST)));
+      if (GET_CODE (op) != SYMBOL_REF
+         && (GET_CODE (op) != CONST
+             || (GET_CODE (XEXP (op, 0)) == MINUS
+                 && XEXP (XEXP (op, 0), 0) == sparc_got ()
+                 && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST)))
+       return 1;
+      return 0;
     case 2:
     default:
       return 1;
@@ -3975,6 +3980,10 @@ sparc_legitimate_address_p (machine_mode mode, rtx addr, 
bool strict)
         than the alignment (8) may cause the LO_SUM to overflow.  */
       if (mode == TFmode && TARGET_ARCH32)
        return 0;
+
+      /* When PIC, we should never see LO_SUM references to symbols.  */
+      if (flag_pic && GET_CODE (imm1) == SYMBOL_REF)
+       return 0;
     }
   else if (GET_CODE (addr) == CONST_INT && SMALL_INT (addr))
     return 1;
@@ -4706,19 +4715,21 @@ enum sparc_mode_class {
 #define DF_MODES (SF_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
 
 /* Modes for quad-float and smaller quantities.  */
-#define TF_MODES (DF_MODES | (1 << (int) TF_MODE))
+#define TF_MODES (T_MODES)
 
 /* Modes for quad-float pairs and smaller quantities.  */
-#define OF_MODES (TF_MODES | (1 << (int) OF_MODE))
+#define OF_MODES (O_MODES)
 
 /* Modes for double-float only quantities.  */
 #define DF_MODES_NO_S ((1 << (int) D_MODE) | (1 << (int) DF_MODE))
 
 /* Modes for quad-float and double-float only quantities.  */
-#define TF_MODES_NO_S (DF_MODES_NO_S | (1 << (int) TF_MODE))
+#define TF_MODES_NO_S \
+  (DF_MODES_NO_S | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
 
 /* Modes for quad-float pairs and double-float only quantities.  */
-#define OF_MODES_NO_S (TF_MODES_NO_S | (1 << (int) OF_MODE))
+#define OF_MODES_NO_S \
+  (TF_MODES_NO_S | (1 << (int) O_MODE) | (1 << (int) OF_MODE))
 
 /* Modes for condition codes.  */
 #define CC_MODES (1 << (int) CC_MODE)
@@ -11188,7 +11199,7 @@ sparc_register_move_cost (machine_mode mode 
ATTRIBUTE_UNUSED,
          || sparc_cpu == PROCESSOR_NIAGARA2
          || sparc_cpu == PROCESSOR_NIAGARA3
          || sparc_cpu == PROCESSOR_NIAGARA4)
-       return 12;
+       return 8;
 
       return 6;
     }

Reply via email to