diff mbox series

Fix find_widening_optab_handler_and_mode assertion (PR 84406)

Message ID 871shfshpz.fsf@linaro.org
State New
Headers show
Series Fix find_widening_optab_handler_and_mode assertion (PR 84406) | expand

Commit Message

Richard Sandiford Feb. 20, 2018, 5:18 p.m. UTC
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.sandiford@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.
diff mbox series

Patch

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);