diff mbox

Fix mode mismatch in expand_parity

Message ID 5681349.DiU8tKv8N4@polaris
State New
Headers show

Commit Message

Eric Botcazou Oct. 15, 2016, 6:46 p.m. UTC
expand_parity attempts to generate popcount operations in wider modes and do a 
logical AND afterward, but it overlooks the mode of "target" and just do:

 	      if (temp != 0)
 		temp = expand_binop (wider_mode, and_optab, temp, const1_rtx,
 				     target, true, OPTAB_DIRECT);

and this ICEs if the mode of "target" is not wider_mode, as for the attached 
testcase compiled for Niagara-2 at -Os.

Tested on x86_64-suse-linux and SPARC/Solaris, applied on mainline as obvious.


2016-10-15  Eric Botcazou  <ebotcazou@adacore.com>

	* optabs.c (expand_parity): Fix mode mismatch, add final conversion
	and keep looping on failure.


2016-10-15  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc.target/sparc/popc-2.c: New test.
diff mbox

Patch

Index: optabs.c
===================================================================
--- optabs.c	(revision 241147)
+++ optabs.c	(working copy)
@@ -2382,18 +2382,26 @@  expand_parity (machine_mode mode, rtx op
 
 	      last = get_last_insn ();
 
-	      if (target == 0)
-		target = gen_reg_rtx (mode);
+	      if (target == 0 || GET_MODE (target) != wider_mode)
+		target = gen_reg_rtx (wider_mode);
+
 	      xop0 = widen_operand (op0, wider_mode, mode, true, false);
 	      temp = expand_unop (wider_mode, popcount_optab, xop0, NULL_RTX,
 				  true);
 	      if (temp != 0)
 		temp = expand_binop (wider_mode, and_optab, temp, const1_rtx,
 				     target, true, OPTAB_DIRECT);
-	      if (temp == 0)
-		delete_insns_since (last);
 
-	      return temp;
+	      if (temp)
+		{
+		  if (mclass != MODE_INT
+		      || !TRULY_NOOP_TRUNCATION_MODES_P (mode, wider_mode))
+		    return convert_to_mode (mode, temp, 0);
+		  else
+		    return gen_lowpart (mode, temp);
+		}
+	      else
+		delete_insns_since (last);
 	    }
 	}
     }