validate subregs, part 6

Richard Henderson rth@redhat.com
Wed Dec 1 19:14:00 GMT 2004


On Wed, Dec 01, 2004 at 06:22:03PM +0000, Joern RENNECKE wrote:
> optabs.c:expand_unop tries to expand the SFmode negate, and finds
> an DImode xor operation.  It wants to generate an SFmode subreg
> of the SImode lowpart of a DImode register - which is perfectly fine
> for sh64 - but this fails because of your new check.

Try this.


r~


Index: optabs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.c,v
retrieving revision 1.250
diff -u -p -r1.250 optabs.c
--- optabs.c	24 Nov 2004 18:50:20 -0000	1.250
+++ optabs.c	1 Dec 2004 19:11:55 -0000
@@ -2131,6 +2131,26 @@ expand_parity (enum machine_mode mode, r
   return 0;
 }
 
+/* Extract the OMODE lowpart from VAL, which has IMODE.  Under certain 
+   conditions, VAL may already be a SUBREG against which we cannot generate
+   a further SUBREG.  In this case, we expect forcing the value into a
+   register will work around the situation.  */
+
+static rtx
+lowpart_subreg_maybe_copy (enum machine_mode omode, rtx val,
+			   enum machine_mode imode)
+{
+  rtx ret;
+  ret = lowpart_subreg (omode, val, imode);
+  if (ret == NULL)
+    {
+      val = force_reg (imode, val);
+      ret = lowpart_subreg (omode, val, imode);
+      gcc_assert (reg != NULL);
+    }
+  return ret;
+}
+
 /* Generate code to perform an operation specified by UNOPTAB
    on operand OP0, with result having machine-mode MODE.
 
@@ -2322,7 +2342,8 @@ expand_unop (enum machine_mode mode, opt
 	      rtx insn;
 	      if (target == 0)
 		target = gen_reg_rtx (mode);
-	      insn = emit_move_insn (target, gen_lowpart (mode, temp));
+	      temp = lowpart_subreg_maybe_copy (mode, temp, imode);
+	      insn = emit_move_insn (target, temp);
 	      set_unique_reg_note (insn, REG_EQUAL,
 				   gen_rtx_fmt_e (NEG, mode,
 						  copy_rtx (op0)));
@@ -2513,7 +2534,8 @@ expand_abs_nojump (enum machine_mode mod
 	      rtx insn;
 	      if (target == 0)
 		target = gen_reg_rtx (mode);
-	      insn = emit_move_insn (target, gen_lowpart (mode, temp));
+	      temp = lowpart_subreg_maybe_copy (mode, temp, imode);
+	      insn = emit_move_insn (target, temp);
 	      set_unique_reg_note (insn, REG_EQUAL,
 				   gen_rtx_fmt_e (ABS, mode,
 						  copy_rtx (op0)));



More information about the Gcc-patches mailing list