r254302 tried to clean up find_widening_optab_handler_and_mode
so that it really did only handle widening ops rather than
simple single-mode ones.  But this PR shows that I'd fluffed
the MODE_PARTIAL_INT handling.  It turns out that all four
combinations of:

  {MODE_INT,MODE_PARTIAL_INT}->{MODE_INT,MODE_PARTIAL_INT}

are possible, and GET_MODE_WIDER_MODE for a MODE_PARTIAL_INT
returns a MODE_INT (which makes sense in retrospect).

No test case since this is a build failure on affected targets.

Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu.
Also tested by Jozef on msp430-elf (thanks).  OK to install?

Richard


2018-02-20  Richard Sandiford  <richard.sandif...@linaro.org>

gcc/
        PR middle-end/84406
        * optabs-query.c (find_widening_optab_handler_and_mode): If from_mode
        is a scalar_int_mode, assert that to_mode is a scalar_int_mode with
        greater precision.  If to_mode is a MODE_PARTIAL_INT, stop the
        search at the associated MODE_INT.

Index: gcc/optabs-query.c
===================================================================
--- gcc/optabs-query.c  2018-01-13 18:01:51.236735252 +0000
+++ gcc/optabs-query.c  2018-02-20 17:16:11.783836883 +0000
@@ -473,9 +473,23 @@ find_widening_optab_handler_and_mode (op
                                      machine_mode from_mode,
                                      machine_mode *found_mode)
 {
-  gcc_checking_assert (GET_MODE_CLASS (from_mode) == GET_MODE_CLASS (to_mode));
-  gcc_checking_assert (from_mode < to_mode);
-  FOR_EACH_MODE (from_mode, from_mode, to_mode)
+  machine_mode limit_mode = to_mode;
+  if (is_a <scalar_int_mode> (from_mode))
+    {
+      gcc_checking_assert (is_a <scalar_int_mode> (to_mode)
+                          && known_lt (GET_MODE_PRECISION (from_mode),
+                                       GET_MODE_PRECISION (to_mode)));
+      /* The modes after FROM_MODE are all MODE_INT, so the only
+        MODE_PARTIAL_INT mode we consider is FROM_MODE itself.
+        If LIMIT_MODE is MODE_PARTIAL_INT, stop at the containing
+        MODE_INT.  */
+      if (GET_MODE_CLASS (limit_mode) == MODE_PARTIAL_INT)
+       limit_mode = GET_MODE_WIDER_MODE (limit_mode).require ();
+    }
+  else
+    gcc_checking_assert (GET_MODE_CLASS (from_mode) == GET_MODE_CLASS (to_mode)
+                        && from_mode < to_mode);
+  FOR_EACH_MODE (from_mode, from_mode, limit_mode)
     {
       enum insn_code handler = convert_optab_handler (op, to_mode, from_mode);
 

Reply via email to