What is going on is that in 'update_costs_from_allocno' we try to
identify the smallest mode using narrower_subreg_mode to then update the
costs.

The two modes involved here are E_DImode and E_VNx2QImode, cause these
are not ordered we ICE in 'paradoxical_subreg_p'.

Now I don't know if the strategy we want is:

- In 'update_costs_from_allocno' when modes are not ordered instead of
  calling 'narrower_subreg_mode' just keep the current one.

- Always select the cheapest mode in terms of cost.

The attached I'm testing implements the second.

  Andrea

>From 03da7bb5c7ad8ab6c25631de5ee1f7b70ea46229 Mon Sep 17 00:00:00 2001
From: Andrea Corallo <andrea.cora...@arm.com>
Date: Tue, 8 Dec 2020 23:17:26 +0100
Subject: [PATCH] Fix ICE in ira-color

2020-12-08  Andrea Corallo  <andrea.cora...@arm.com>

        * ira-color.c (update_costs_from_allocno): Pick the cheapest mode
        instead of the smaller one.
---
 gcc/ira-color.c | 34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/gcc/ira-color.c b/gcc/ira-color.c
index d3f8e23faff..13a3548018a 100644
--- a/gcc/ira-color.c
+++ b/gcc/ira-color.c
@@ -1400,19 +1400,29 @@ update_costs_from_allocno (ira_allocno_t allocno, int 
hard_regno,
              || ALLOCNO_ASSIGNED_P (another_allocno))
            continue;
 
-         /* If we have different modes use the smallest one.  It is
-            a sub-register move.  It is hard to predict what LRA
-            will reload (the pseudo or its sub-register) but LRA
-            will try to minimize the data movement.  Also for some
-            register classes bigger modes might be invalid,
-            e.g. DImode for AREG on x86.  For such cases the
-            register move cost will be maximal.  */
-         mode = narrower_subreg_mode (mode, ALLOCNO_MODE (cp->second));
+         /* If we have different modes use the cheapest one.  It is a
+            sub-register move.  It is hard to predict what LRA will
+            reload (the pseudo or its sub-register) but LRA will try
+            to minimize the data movement.  Also for some register
+            classes bigger modes might be invalid, e.g. DImode for
+            AREG on x86.  For such cases the register move cost will
+            be maximal.  */
+         machine_mode mode2 = ALLOCNO_MODE (cp->second);
          ira_init_register_move_cost_if_necessary (mode);
-         
-         cost = (cp->second == allocno
-                 ? ira_register_move_cost[mode][rclass][aclass]
-                 : ira_register_move_cost[mode][aclass][rclass]);
+         ira_init_register_move_cost_if_necessary (mode2);
+         int cost1, cost2;
+         if (cp->second == allocno)
+           {
+             cost1 = ira_register_move_cost[mode][rclass][aclass];
+             cost2 = ira_register_move_cost[mode2][rclass][aclass];
+           }
+         else
+           {
+             cost1 = ira_register_move_cost[mode][aclass][rclass];
+             cost2 = ira_register_move_cost[mode2][aclass][rclass];
+           }
+         cost = MIN (cost1, cost2);
+
          if (decr_p)
            cost = -cost;
 
-- 
2.20.1

Reply via email to