This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Sign-extend CONST_INTs within their modes


On Mar 18, 2001, Geoff Keating <geoffk@geoffk.org> wrote:

> Alexandre Oliva <aoliva@redhat.com> writes:
>> A while ago, I proposed a patch that would auto-detect the need for
>> 64-bits HOST_WIDE_INTs, and it ended up rejected because some targets
>> broke with a wider-than-32-bits HOST_WIDE_INT because GCC wouldn't
>> sign-extend CONST_INTs as it should.

>> I've come up with a patch to detect occurrences of non-sign-extended
>> CONST_INTs, and fixed all errors it detected on a port I'm working on,
>> in which I enabled 64-bit HOST_WIDE_INTs.  There are certainly more
>> bugs lurking around, in chunks of code not exercised by this port, but
>> I'd like to install the fixes I've found so far, and maybe the test to
>> detect invalid values too (it's the changes in recog.c).

>> This has only been tested with the new port.  I intend to test it on
>> alpha and probably a few alpha-x-??? crosses.  Suggestions?

> I believe the original trouble was on PA, if you could try a build
> there, that would be good.

It bootstrapped fine on alpha.  For a x86 bootstrap, I had to tweak
the argument mode promotion rules in integrate.c.  For a sparc
bootstrap, I had to tweak expand_binop so as to handle widening
conversions properly.  For a pa bootstrap, I had to fix
expand_end_case() so as to convert minval and range to the appropriate
modes.  Then, for a alpha-x-ppc `make all-target', I needed a couple
of tweaks in the rs6000 configuration files.

>> Ok to install the codegen fixes?  What about the recog changes?

> The codegen fixes (other than the varasm.c change) are all OK, put
> them in if the compiler survives a bootstrap & test on alpha.  The
> varasm.c change can go in if it also survives an x86 bootstrap & test
> and a PA bootstrap & test, I figure if it works on those three natives
> it's probably no worse than the current situation.  The recog change
> is OK (if the others go in) but I'd like to see it controlled by
> another flag than RTL_CHECKING, as RTL_CHECKING is very expensive and
> these tests are not (perhaps --enable-checking=misc?), and be prepared
> to disable it if problems are reported that you can't quickly fix.

Here's the updated patch.  Ok to install?

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* recog.c (general_operand, immediate_operand,
	nonmemory_operand): Require CONST_INTs to be sign-extended
	values for their modes.
	* combine.c (try_combine): Avoid generating a new set in i2
	that changes the expected mode of a CONST_INT.
	* expmed.c (store_bit_field): Truncate CONST_INTs.
	(expand_mult_highpart, expand_divmod): Likewise.
	* expr.c (convert_modes, store_field): Likewise.
	* integrate.c (expand_inline_function): Use promote_mode() to
	determine whether to convert_modes() an argument as signed
	or unsigned.
	* optabs.c (expand_binop): Get CONST_INT operands
	sign-extended for their appropriate modes.
	* stmt.c (emit_case_nodes): Convert node values to the
	appropriate mode.
	(expand_end_case): Convert minval and range to the appropriate
	mode.
	* unroll.c (loop_iterations): Truncate abs_diff to the mode of
	the iteration variable.
	* varasm.c (immed_double_const): Don't require words to be
	narrower than host wide ints to properly sign-extend
	CONST_INTs.

Index: gcc/recog.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/recog.c,v
retrieving revision 1.93
diff -u -p -r1.93 recog.c
--- gcc/recog.c 2001/03/22 18:48:31 1.93
+++ gcc/recog.c 2001/03/30 07:58:10
@@ -1052,6 +1052,12 @@ general_operand (op, mode)
       && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
     return 0;
 
+#ifdef ENABLE_CHECKING
+  if (GET_CODE (op) == CONST_INT
+      && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
+    abort ();
+#endif
+
   if (CONSTANT_P (op))
     return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode
 	     || mode == VOIDmode)
@@ -1235,6 +1241,12 @@ immediate_operand (op, mode)
       && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
     return 0;
 
+#ifdef ENABLE_CHECKING
+  if (GET_CODE (op) == CONST_INT
+      && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
+    abort ();
+#endif
+
   /* Accept CONSTANT_P_RTX, since it will be gone by CSE1 and
      result in 0/1.  It seems a safe assumption that this is
      in range for everyone.  */
@@ -1305,6 +1317,12 @@ nonmemory_operand (op, mode)
 	  && GET_MODE_CLASS (mode) != MODE_INT
 	  && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
 	return 0;
+
+#ifdef ENABLE_CHECKING
+      if (GET_CODE (op) == CONST_INT
+	  && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
+	abort ();
+#endif
 
       return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode
 	      || mode == VOIDmode)
Index: gcc/combine.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/combine.c,v
retrieving revision 1.195
diff -u -p -r1.195 combine.c
--- gcc/combine.c 2001/03/28 05:40:43 1.195
+++ gcc/combine.c 2001/03/30 07:58:15
@@ -2249,17 +2249,30 @@ try_combine (i3, i2, i1, new_direct_jump
 	     be written as a ZERO_EXTEND.  */
 	  if (split_code == SUBREG && GET_CODE (SUBREG_REG (*split)) == MEM)
 	    SUBST (*split, gen_rtx_ZERO_EXTEND  (split_mode,
-						 XEXP (*split, 0)));
+					    XEXP (*split, 0)));
 #endif
 
-	  newi2pat = gen_rtx_SET (VOIDmode, newdest, *split);
-	  SUBST (*split, newdest);
-	  i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
-
 	  /* If the split point was a MULT and we didn't have one before,
 	     don't use one now.  */
-	  if (i2_code_number >= 0 && ! (split_code == MULT && ! have_mult))
+	  if (! (split_code == MULT && ! have_mult))
 	    insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
+	  else
+	    insn_code_number = -1;
+
+	  /* We want to test newi2pat only if the combination for i3
+	     would have worked.  This prevents us from generating i2
+	     as a set from a CONST_INT to a register in the wrong
+	     mode, in case i3 is a comparison in a certain mode whose
+	     result is in a different mode.  */
+	  if (insn_code_number >= 0)
+	    {
+	      newi2pat = gen_rtx_SET (VOIDmode, newdest, *split);
+	      SUBST (*split, newdest);
+	      i2_code_number = recog_for_combine (&newi2pat, i2,
+						  &new_i2_notes);
+	    }
+	  else
+	    i2_code_number = -1;
 	}
     }
 
Index: gcc/expmed.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/expmed.c,v
retrieving revision 1.77
diff -u -p -r1.77 expmed.c
--- gcc/expmed.c 2001/03/22 18:48:28 1.77
+++ gcc/expmed.c 2001/03/30 07:58:16
@@ -587,6 +587,8 @@ store_bit_field (str_rtx, bitsize, bitnu
 	      else
 		value1 = gen_lowpart (maxmode, value1);
 	    }
+	  else if (GET_CODE (value) == CONST_INT)
+	    value1 = GEN_INT (trunc_int_for_mode (INTVAL (value), maxmode));
 	  else if (!CONSTANT_P (value))
 	    /* Parse phase is supposed to make VALUE's data type
 	       match that of the component reference, which is a type
@@ -2780,7 +2782,7 @@ expand_mult_highpart (mode, op0, cnst1, 
   if (size > HOST_BITS_PER_WIDE_INT)
     abort ();
 
-  op1 = GEN_INT (cnst1);
+  op1 = GEN_INT (trunc_int_for_mode (cnst1, mode));
 
   if (GET_MODE_BITSIZE (wider_mode) <= HOST_BITS_PER_INT)
     wide_op1 = op1;
@@ -3267,7 +3269,7 @@ expand_divmod (rem_flag, code, mode, op0
 		if (rem_flag && d < 0)
 		  {
 		    d = abs_d;
-		    op1 = GEN_INT (abs_d);
+		    op1 = GEN_INT (trunc_int_for_mode (abs_d, compute_mode));
 		  }
 
 		if (d == 1)
@@ -3297,7 +3299,8 @@ expand_divmod (rem_flag, code, mode, op0
 			t1 = copy_to_mode_reg (compute_mode, op0);
 			do_cmp_and_jump (t1, const0_rtx, GE,
 					 compute_mode, label);
-			expand_inc (t1, GEN_INT (abs_d - 1));
+			expand_inc (t1, GEN_INT (trunc_int_for_mode
+						 (abs_d - 1, compute_mode)));
 			emit_label (label);
 			quotient = expand_shift (RSHIFT_EXPR, compute_mode, t1,
 						 build_int_2 (lgup, 0),
@@ -3334,7 +3337,10 @@ expand_divmod (rem_flag, code, mode, op0
 			  		       REG_EQUAL,
 					       gen_rtx_DIV (compute_mode,
 							    op0,
-							    GEN_INT (abs_d)));
+							    GEN_INT
+							    (trunc_int_for_mode
+							     (abs_d,
+							      compute_mode))));
 
 			quotient = expand_unop (compute_mode, neg_optab,
 						quotient, quotient, 0);
@@ -3833,8 +3839,10 @@ expand_divmod (rem_flag, code, mode, op0
 	    ml = invert_mod2n (d >> pre_shift, size);
 	    t1 = expand_shift (RSHIFT_EXPR, compute_mode, op0,
 			       build_int_2 (pre_shift, 0), NULL_RTX, unsignedp);
-	    quotient = expand_mult (compute_mode, t1, GEN_INT (ml), NULL_RTX,
-			      	    0);
+	    quotient = expand_mult (compute_mode, t1,
+				    GEN_INT (trunc_int_for_mode
+					     (ml, compute_mode)),
+				    NULL_RTX, 0);
 
 	    insn = get_last_insn ();
 	    set_unique_reg_note (insn,
Index: gcc/expr.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/expr.c,v
retrieving revision 1.307
diff -u -p -r1.307 expr.c
--- gcc/expr.c 2001/03/28 11:03:51 1.307
+++ gcc/expr.c 2001/03/30 07:58:18
@@ -1360,7 +1360,7 @@ convert_modes (mode, oldmode, x, unsigne
 	      && (val & ((HOST_WIDE_INT) 1 << (width - 1))))
 	    val |= (HOST_WIDE_INT) (-1) << width;
 
-	  return GEN_INT (val);
+	  return GEN_INT (trunc_int_for_mode (val, mode));
 	}
 
       return gen_lowpart (mode, x);
@@ -5268,7 +5268,13 @@ store_field (target, bitsize, bitpos, mo
 	      enum machine_mode tmode;
 
 	      if (unsignedp)
-		return expand_and (temp, GEN_INT (width_mask), NULL_RTX);
+		return expand_and (temp,
+				   GEN_INT
+				   (trunc_int_for_mode
+				    (width_mask,
+				     GET_MODE (temp) == VOIDmode
+				     ? value_mode
+				     : GET_MODE (temp))), NULL_RTX);
 	      tmode = GET_MODE (temp);
 	      if (tmode == VOIDmode)
 		tmode = value_mode;
Index: gcc/integrate.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/integrate.c,v
retrieving revision 1.137
diff -u -p -r1.137 integrate.c
--- gcc/integrate.c 2001/03/28 11:03:54 1.137
+++ gcc/integrate.c 2001/03/30 07:58:19
@@ -702,13 +702,24 @@ expand_inline_function (fndecl, parms, t
       else if (GET_CODE (loc) != MEM)
 	{
 	  if (GET_MODE (loc) != TYPE_MODE (TREE_TYPE (arg)))
-	    /* The mode if LOC and ARG can differ if LOC was a variable
-	       that had its mode promoted via PROMOTED_MODE.  */
-	    arg_vals[i] = convert_modes (GET_MODE (loc),
-					 TYPE_MODE (TREE_TYPE (arg)),
-					 expand_expr (arg, NULL_RTX, mode,
-						      EXPAND_SUM),
-					 TREE_UNSIGNED (TREE_TYPE (formal)));
+	    {
+	      int unsignedp = TREE_UNSIGNED (TREE_TYPE (formal));
+	      enum machine_mode pmode = TYPE_MODE (TREE_TYPE (formal));
+
+	      pmode = promote_mode (TREE_TYPE (formal), pmode,
+				    &unsignedp, 0);
+
+	      if (GET_MODE (loc) != pmode)
+		abort ();
+
+	      /* The mode if LOC and ARG can differ if LOC was a variable
+		 that had its mode promoted via PROMOTED_MODE.  */
+	      arg_vals[i] = convert_modes (pmode,
+					   TYPE_MODE (TREE_TYPE (arg)),
+					   expand_expr (arg, NULL_RTX, mode,
+							EXPAND_SUM),
+					   unsignedp);
+	    }
 	  else
 	    arg_vals[i] = expand_expr (arg, NULL_RTX, mode, EXPAND_SUM);
 	}
Index: gcc/optabs.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/optabs.c,v
retrieving revision 1.91
diff -u -p -r1.91 optabs.c
--- gcc/optabs.c 2001/03/28 11:03:56 1.91
+++ gcc/optabs.c 2001/03/30 07:58:19
@@ -723,17 +723,25 @@ expand_binop (mode, binoptab, op0, op1, 
 	}
 
       /* In case the insn wants input operands in modes different from
-	 the result, convert the operands.  */
+	 the result, convert the operands.  It would seem that we
+	 don't need to convert CONST_INTs, but we do, so that they're
+	 a properly sign-extended for their modes.  */
 
-      if (GET_MODE (op0) != VOIDmode
-	  && GET_MODE (op0) != mode0
+      if (GET_MODE (op0) != mode0
 	  && mode0 != VOIDmode)
-	xop0 = convert_to_mode (mode0, xop0, unsignedp);
+	xop0 = convert_modes (mode0,
+			      GET_MODE (op0) != VOIDmode
+			      ? GET_MODE (op0)
+			      : mode0,
+			      xop0, unsignedp);
 
-      if (GET_MODE (xop1) != VOIDmode
-	  && GET_MODE (xop1) != mode1
+      if (GET_MODE (xop1) != mode1
 	  && mode1 != VOIDmode)
-	xop1 = convert_to_mode (mode1, xop1, unsignedp);
+	xop1 = convert_modes (mode1,
+			      GET_MODE (op1) != VOIDmode
+			      ? GET_MODE (op1)
+			      : mode1,
+			      xop1, unsignedp);
 
       /* Now, if insn's predicates don't allow our operands, put them into
 	 pseudo regs.  */
@@ -4295,7 +4303,9 @@ expand_fix (to, from, unsignedp)
 				 NULL_RTX, 0, OPTAB_LIB_WIDEN);
 	  expand_fix (to, target, 0);
 	  target = expand_binop (GET_MODE (to), xor_optab, to,
-				 GEN_INT ((HOST_WIDE_INT) 1 << (bitsize - 1)),
+				 GEN_INT (trunc_int_for_mode
+					  ((HOST_WIDE_INT) 1 << (bitsize - 1),
+					   GET_MODE (to))),
 				 to, 1, OPTAB_LIB_WIDEN);
 
 	  if (target != to)
Index: gcc/stmt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/stmt.c,v
retrieving revision 1.190
diff -u -p -r1.190 stmt.c
--- gcc/stmt.c 2001/03/28 11:03:58 1.190
+++ gcc/stmt.c 2001/03/30 08:12:44
@@ -1,6 +1,6 @@
 /* Expands front end tree to back end RTL for GNU C-Compiler
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000 Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -5474,6 +5474,8 @@ expand_end_case (orig_index)
 	      op1 = expand_expr (minval, NULL_RTX, VOIDmode, 0);
 
 	      op_mode = insn_data[(int) CODE_FOR_casesi].operand[1].mode;
+	      op1 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (minval)),
+				   op1, TREE_UNSIGNED (TREE_TYPE (minval)));
 	      if (! (*insn_data[(int) CODE_FOR_casesi].operand[1].predicate)
 		  (op1, op_mode))
 		op1 = copy_to_mode_reg (op_mode, op1);
@@ -5481,6 +5483,8 @@ expand_end_case (orig_index)
 	      op2 = expand_expr (range, NULL_RTX, VOIDmode, 0);
 
 	      op_mode = insn_data[(int) CODE_FOR_casesi].operand[2].mode;
+	      op2 = convert_modes (op_mode, TYPE_MODE (TREE_TYPE (range)),
+				   op2, TREE_UNSIGNED (TREE_TYPE (range)));
 	      if (! (*insn_data[(int) CODE_FOR_casesi].operand[2].predicate)
 		  (op2, op_mode))
 		op2 = copy_to_mode_reg (op_mode, op2);
@@ -5503,7 +5507,11 @@ expand_end_case (orig_index)
 	      do_pending_stack_adjust ();
 
 	      do_tablejump (index, TYPE_MODE (index_type),
-			    expand_expr (range, NULL_RTX, VOIDmode, 0),
+			    convert_modes (TYPE_MODE (index_type),
+					   TYPE_MODE (TREE_TYPE (range)),
+					   expand_expr (range, NULL_RTX,
+							VOIDmode, 0),
+					   TREE_UNSIGNED (TREE_TYPE (range))),
 			    table_label, default_label);
 	      win = 1;
 	    }
@@ -6027,6 +6035,7 @@ emit_case_nodes (index, node, default_la
   /* If INDEX has an unsigned type, we must make unsigned branches.  */
   int unsignedp = TREE_UNSIGNED (index_type);
   enum machine_mode mode = GET_MODE (index);
+  enum machine_mode imode = TYPE_MODE (index_type);
 
   /* See if our parents have already tested everything for us.
      If they have, emit an unconditional jump for this node.  */
@@ -6038,7 +6047,11 @@ emit_case_nodes (index, node, default_la
       /* Node is single valued.  First see if the index expression matches
 	 this node and then check our children, if any.  */
 
-      do_jump_if_equal (index, expand_expr (node->low, NULL_RTX, VOIDmode, 0),
+      do_jump_if_equal (index,
+			convert_modes (mode, imode,
+				       expand_expr (node->low, NULL_RTX,
+						    VOIDmode, 0),
+				       unsignedp),
 			label_rtx (node->code_label), unsignedp);
 
       if (node->right != 0 && node->left != 0)
@@ -6052,8 +6065,11 @@ emit_case_nodes (index, node, default_la
 	  if (node_is_bounded (node->right, index_type))
 	    {
 	      emit_cmp_and_jump_insns (index,
-				       expand_expr (node->high, NULL_RTX,
-						    VOIDmode, 0),
+				       convert_modes
+				       (mode, imode,
+					expand_expr (node->high, NULL_RTX,
+						     VOIDmode, 0),
+					unsignedp),
 				       GT, NULL_RTX, mode, unsignedp, 0,
 				       label_rtx (node->right->code_label));
 	      emit_case_nodes (index, node->left, default_label, index_type);
@@ -6062,8 +6078,11 @@ emit_case_nodes (index, node, default_la
 	  else if (node_is_bounded (node->left, index_type))
 	    {
 	      emit_cmp_and_jump_insns (index,
-				       expand_expr (node->high, NULL_RTX,
-						    VOIDmode, 0),
+				       convert_modes
+				       (mode, imode,
+					expand_expr (node->high, NULL_RTX,
+						     VOIDmode, 0),
+					unsignedp),
 				       LT, NULL_RTX, mode, unsignedp, 0,
 				       label_rtx (node->left->code_label));
 	      emit_case_nodes (index, node->right, default_label, index_type);
@@ -6078,8 +6097,11 @@ emit_case_nodes (index, node, default_la
 
 	      /* See if the value is on the right.  */
 	      emit_cmp_and_jump_insns (index,
-				       expand_expr (node->high, NULL_RTX,
-						    VOIDmode, 0),
+				       convert_modes
+				       (mode, imode,
+					expand_expr (node->high, NULL_RTX,
+						     VOIDmode, 0),
+					unsignedp),
 				       GT, NULL_RTX, mode, unsignedp, 0,
 				       label_rtx (test_label));
 
@@ -6110,8 +6132,11 @@ emit_case_nodes (index, node, default_la
 	      if (!node_has_low_bound (node, index_type))
 		{
 		  emit_cmp_and_jump_insns (index,
-					   expand_expr (node->high, NULL_RTX,
-							VOIDmode, 0),
+					   convert_modes
+					   (mode, imode,
+					    expand_expr (node->high, NULL_RTX,
+							 VOIDmode, 0),
+					    unsignedp),
 					   LT, NULL_RTX, mode, unsignedp, 0,
 					   default_label);
 		}
@@ -6123,8 +6148,11 @@ emit_case_nodes (index, node, default_la
 	       since we haven't ruled out the numbers less than
 	       this node's value.  So handle node->right explicitly.  */
 	    do_jump_if_equal (index,
-			      expand_expr (node->right->low, NULL_RTX,
-					   VOIDmode, 0),
+			      convert_modes
+			      (mode, imode,
+			       expand_expr (node->right->low, NULL_RTX,
+					    VOIDmode, 0),
+			       unsignedp),
 			      label_rtx (node->right->code_label), unsignedp);
 	}
 
@@ -6150,9 +6178,12 @@ emit_case_nodes (index, node, default_la
 	    {
 	      if (!node_has_high_bound (node, index_type))
 		{
-		  emit_cmp_and_jump_insns (index, expand_expr (node->high,
-							       NULL_RTX,
-							       VOIDmode, 0),
+		  emit_cmp_and_jump_insns (index,
+					   convert_modes
+					   (mode, imode,
+					    expand_expr (node->high, NULL_RTX,
+							 VOIDmode, 0),
+					    unsignedp),
 					   GT, NULL_RTX, mode, unsignedp, 0,
 					   default_label);
 		}
@@ -6164,8 +6195,11 @@ emit_case_nodes (index, node, default_la
 	       since we haven't ruled out the numbers less than
 	       this node's value.  So handle node->left explicitly.  */
 	    do_jump_if_equal (index,
-			      expand_expr (node->left->low, NULL_RTX,
-					   VOIDmode, 0),
+			      convert_modes
+			      (mode, imode,
+			       expand_expr (node->left->low, NULL_RTX,
+					    VOIDmode, 0),
+			       unsignedp),
 			      label_rtx (node->left->code_label), unsignedp);
 	}
     }
@@ -6187,8 +6221,12 @@ emit_case_nodes (index, node, default_la
 	  if (node_is_bounded (node->right, index_type))
 	    /* Right hand node is fully bounded so we can eliminate any
 	       testing and branch directly to the target code.  */
-	    emit_cmp_and_jump_insns (index, expand_expr (node->high, NULL_RTX,
-							 VOIDmode, 0),
+	    emit_cmp_and_jump_insns (index,
+				     convert_modes
+				     (mode, imode,
+				      expand_expr (node->high, NULL_RTX,
+						   VOIDmode, 0),
+				      unsignedp),
 				     GT, NULL_RTX, mode, unsignedp, 0,
 				     label_rtx (node->right->code_label));
 	  else
@@ -6198,16 +6236,23 @@ emit_case_nodes (index, node, default_la
 
 	      test_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
 	      emit_cmp_and_jump_insns (index,
-				       expand_expr (node->high, NULL_RTX,
-						    VOIDmode, 0),
+				       convert_modes
+				       (mode, imode,
+					expand_expr (node->high, NULL_RTX,
+						     VOIDmode, 0),
+					unsignedp),
 				       GT, NULL_RTX, mode, unsignedp, 0,
 				       label_rtx (test_label));
 	    }
 
 	  /* Value belongs to this node or to the left-hand subtree.  */
 
-	  emit_cmp_and_jump_insns (index, expand_expr (node->low, NULL_RTX,
-						       VOIDmode, 0),
+	  emit_cmp_and_jump_insns (index,
+				   convert_modes
+				   (mode, imode,
+				    expand_expr (node->low, NULL_RTX,
+						 VOIDmode, 0),
+				    unsignedp),
 				   GE, NULL_RTX, mode, unsignedp, 0,
 				   label_rtx (node->code_label));
 
@@ -6234,16 +6279,23 @@ emit_case_nodes (index, node, default_la
 	  if (!node_has_low_bound (node, index_type))
 	    {
 	      emit_cmp_and_jump_insns (index,
-				       expand_expr (node->low, NULL_RTX,
-						    VOIDmode, 0),
+				       convert_modes
+				       (mode, imode,
+					expand_expr (node->low, NULL_RTX,
+						     VOIDmode, 0),
+					unsignedp),
 				       LT, NULL_RTX, mode, unsignedp, 0,
 				       default_label);
 	    }
 
 	  /* Value belongs to this node or to the right-hand subtree.  */
 
-	  emit_cmp_and_jump_insns (index, expand_expr (node->high, NULL_RTX,
-						       VOIDmode, 0),
+	  emit_cmp_and_jump_insns (index,
+				   convert_modes
+				   (mode, imode,
+				    expand_expr (node->high, NULL_RTX,
+						 VOIDmode, 0),
+				    unsignedp),
 				   LE, NULL_RTX, mode, unsignedp, 0,
 				   label_rtx (node->code_label));
 
@@ -6257,8 +6309,11 @@ emit_case_nodes (index, node, default_la
 	  if (!node_has_high_bound (node, index_type))
 	    {
 	      emit_cmp_and_jump_insns (index,
-				       expand_expr (node->high, NULL_RTX,
-						    VOIDmode, 0),
+				       convert_modes
+				       (mode, imode,
+					expand_expr (node->high, NULL_RTX,
+						     VOIDmode, 0),
+					unsignedp),
 				       GT, NULL_RTX, mode, unsignedp, 0,
 				       default_label);
 	    }
@@ -6266,8 +6321,11 @@ emit_case_nodes (index, node, default_la
 	  /* Value belongs to this node or to the left-hand subtree.  */
 
 	  emit_cmp_and_jump_insns (index,
-				   expand_expr (node->low, NULL_RTX,
-						VOIDmode, 0),
+				   convert_modes
+				   (mode, imode,
+				    expand_expr (node->low, NULL_RTX,
+						 VOIDmode, 0),
+				    unsignedp),
 				   GE, NULL_RTX, mode, unsignedp, 0,
 				   label_rtx (node->code_label));
 
@@ -6283,8 +6341,11 @@ emit_case_nodes (index, node, default_la
 	  if (!node_has_high_bound (node, index_type))
 	    {
 	      emit_cmp_and_jump_insns (index,
-				       expand_expr (node->high, NULL_RTX,
-						    VOIDmode, 0),
+				       convert_modes
+				       (mode, imode,
+					expand_expr (node->high, NULL_RTX,
+						     VOIDmode, 0),
+					unsignedp),
 				       GT, NULL_RTX, mode, unsignedp, 0,
 				       default_label);
 	    }
@@ -6292,8 +6353,11 @@ emit_case_nodes (index, node, default_la
 	  if (!node_has_low_bound (node, index_type))
 	    {
 	      emit_cmp_and_jump_insns (index,
-				       expand_expr (node->low, NULL_RTX,
-						    VOIDmode, 0),
+				       convert_modes
+				       (mode, imode,
+					expand_expr (node->low, NULL_RTX,
+						     VOIDmode, 0),
+					unsignedp),
 				       LT, NULL_RTX, mode, unsignedp, 0,
 				       default_label);
 	    }
Index: gcc/unroll.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/unroll.c,v
retrieving revision 1.125
diff -u -p -r1.125 unroll.c
--- gcc/unroll.c 2001/01/25 09:28:55 1.125
+++ gcc/unroll.c 2001/03/30 07:58:21
@@ -3962,6 +3962,8 @@ loop_iterations (loop)
   else
     abort ();
 
+  abs_diff = trunc_int_for_mode (abs_diff, GET_MODE (iteration_var));
+
   /* For NE tests, make sure that the iteration variable won't miss
      the final value.  If abs_diff mod abs_incr is not zero, then the
      iteration variable will overflow before the loop exits, and we
Index: gcc/varasm.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/varasm.c,v
retrieving revision 1.170
diff -u -p -r1.170 varasm.c
--- gcc/varasm.c 2001/03/23 22:00:40 1.170
+++ gcc/varasm.c 2001/03/30 07:58:22
@@ -1984,7 +1984,7 @@ immed_double_const (i0, i1, mode)
 	 represented as a 64 bit value -1, and not as 0x00000000ffffffff.
 	 The later confuses the sparc backend.  */
 
-      if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT && BITS_PER_WORD == width
+      if (width < HOST_BITS_PER_WIDE_INT
 	  && (i0 & ((HOST_WIDE_INT) 1 << (width - 1))))
 	i0 |= ((HOST_WIDE_INT) (-1) << width);
 
Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* config/rs6000/rs6000.c (logical_operand): CONST_INTs are
	already sign-extended.
	(rs6000_emit_move): Don't special-case HOST_BITS_PER_WIDE_INT != 32.
	(rs6000_emit_prologue): Make register iterator signed.
	(rs6000_emit_epilogue): Likewise.
	* config/rs6000/rs6000.md (addsi3, adddi3): Sign-extend high
	and low.
	(movsf split, movdf split): Sign-extend CONST_INTs.
	(movdi splits): Likewise.

Index: gcc/config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.172
diff -u -p -r1.172 rs6000.c
--- gcc/config/rs6000/rs6000.c 2001/03/28 11:19:20 1.172
+++ gcc/config/rs6000/rs6000.c 2001/03/30 13:39:15
@@ -965,7 +965,7 @@ add_operand (op, mode)
 {
   return (reg_or_short_operand (op, mode)
 	  || (GET_CODE (op) == CONST_INT
-	      && CONST_OK_FOR_LETTER_P (INTVAL(op), 'L')));
+	      && CONST_OK_FOR_LETTER_P (INTVAL (op), 'L')));
 }
 
 /* Return 1 if OP is a constant but not a valid add_operand.  */
@@ -977,7 +977,7 @@ non_add_cint_operand (op, mode)
 {
   return (GET_CODE (op) == CONST_INT
 	  && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x8000) >= 0x10000
-	  && ! CONST_OK_FOR_LETTER_P (INTVAL(op), 'L'));
+	  && ! CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
 }
 
 /* Return 1 if the operand is a non-special register or a constant that
@@ -995,13 +995,7 @@ logical_operand (op, mode)
     return 1;
 
   if (GET_CODE (op) == CONST_INT)
-    {
-      opl = INTVAL (op) & GET_MODE_MASK (mode);
-      if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
-	oph = 0;
-      else
-	oph = INTVAL (op) >> (HOST_BITS_PER_WIDE_INT - 1);
-    }
+    opl = INTVAL (op);
   else if (GET_CODE (op) == CONST_DOUBLE)
     {
       if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
@@ -1009,13 +1003,21 @@ logical_operand (op, mode)
 
       opl = CONST_DOUBLE_LOW (op);
       oph = CONST_DOUBLE_HIGH (op);
+
+      if (oph != ((unsigned HOST_WIDE_INT)0
+		  - ((opl & ((unsigned HOST_WIDE_INT)1
+			     << (HOST_BITS_PER_WIDE_INT - 1))) != 0)))
+	return 0;
     }
   else
     return 0;
+
+  /* This must really be SImode, not MODE.  */
+  if (opl != trunc_int_for_mode (opl, SImode))
+    return 0;
 
-  return (oph == 0
-	  && ((opl & ~ (unsigned HOST_WIDE_INT) 0xffff) == 0
-	      || (opl & ~ (unsigned HOST_WIDE_INT) 0xffff0000) == 0));
+  return ((opl & 0xffff) == 0
+	  || (opl & ~ (unsigned HOST_WIDE_INT) 0xffff) == 0);
 }
 
 /* Return 1 if C is a constant that is not a logical operand (as
@@ -1688,8 +1690,7 @@ rs6000_emit_move (dest, source, mode)
 	}
       else if (mode == Pmode
 	       && CONSTANT_P (operands[1])
- 	       && (((HOST_BITS_PER_WIDE_INT != 32 
- 		     || GET_CODE (operands[1]) != CONST_INT)
+ 	       && ((GET_CODE (operands[1]) != CONST_INT
  		    && ! easy_fp_constant (operands[1], mode))
  		   || (GET_CODE (operands[0]) == REG
  		       && FP_REGNO_P (REGNO (operands[0]))))
@@ -5762,7 +5763,7 @@ rs6000_emit_prologue ()
      easiest way to get the frame unwind information emitted.  */
   if (current_function_calls_eh_return)
     {
-      unsigned int i, regno;
+      int i, regno;
       for (i = 0; ; ++i)
 	{
 	  rtx addr, reg, mem;
@@ -6006,7 +6007,7 @@ rs6000_emit_epilogue (sibcall)
   /* Load exception handler data registers, if needed.  */
   if (current_function_calls_eh_return)
     {
-      unsigned int i, regno;
+      int i, regno;
       for (i = 0; ; ++i)
 	{
 	  rtx addr, mem;
Index: gcc/config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.111
diff -u -p -r1.111 rs6000.md
--- gcc/config/rs6000/rs6000.md 2001/03/28 12:22:48 1.111
+++ gcc/config/rs6000/rs6000.md 2001/03/30 13:39:19
@@ -1426,7 +1426,10 @@
       HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
 
       if (low & 0x8000)
-        high += 0x10000, low |= ((HOST_WIDE_INT) -1) << 16;
+	{
+	  high = trunc_int_for_mode (high + 0x10000, SImode);
+	  low = trunc_int_for_mode (low, HImode);
+	}
 
       /* The ordering here is important for the prolog expander.
 	 When space is allocated from the stack, adding 'low' first may
@@ -1529,7 +1532,10 @@
   HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
 
   if (low & 0x8000)
-    high += 0x10000, low |= ((HOST_WIDE_INT) -1) << 16;
+    {
+      high = trunc_int_for_mode (high + 0x10000, SImode);
+      low = trunc_int_for_mode (low, HImode);
+    }
 
   operands[3] = GEN_INT (high);
   operands[4] = GEN_INT (low);
@@ -5759,7 +5765,10 @@
 	HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
 
 	if (low & 0x8000)
-	  high += 0x10000, low |= ((HOST_WIDE_INT) -1) << 16;
+	  {
+	    high = trunc_int_for_mode (high + 0x10000, SImode);
+	    low = trunc_int_for_mode (low, HImode);
+	  }
 
 	emit_insn (gen_adddi3 (tmp, operands[1], GEN_INT (high)));
 	emit_insn (gen_adddi3 (operands[0], tmp, GEN_INT (low)));
@@ -5858,7 +5867,10 @@
   HOST_WIDE_INT high = INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff);
 
   if (low & 0x8000)
-    high+=0x10000, low |= ((HOST_WIDE_INT) -1) << 16;
+    {
+      high = trunc_int_for_mode (high + 0x10000, SImode);
+      low = trunc_int_for_mode (low, HImode);
+    }
 
   operands[3] = GEN_INT (high);
   operands[4] = GEN_INT (low);
@@ -7573,7 +7585,7 @@
   else
     operands[2] = gen_lowpart (SImode, operands[0]);
 
-  operands[3] = GEN_INT(l);
+  operands[3] = GEN_INT (trunc_int_for_mode (l, SImode));
 }")
 
 (define_insn "*movsf_hardfloat"
@@ -7663,8 +7675,8 @@
 
   operands[2] = operand_subword (operands[0], endian, 0, DFmode);
   operands[3] = operand_subword (operands[0], 1 - endian, 0, DFmode);
-  operands[4] = GEN_INT (l[endian]);
-  operands[5] = GEN_INT (l[1 - endian]);
+  operands[4] = GEN_INT (trunc_int_for_mode (l[endian], SImode));
+  operands[5] = GEN_INT (trunc_int_for_mode (l[1 - endian], SImode));
 }")
 
 (define_split
@@ -8009,7 +8021,7 @@
 		(match_dup 3)))]
   "
 {
-  operands[2] = GEN_INT (INTVAL (operands[1]) & 0xffff0000);
+  operands[2] = GEN_INT (INTVAL (operands[1]) & (~ (HOST_WIDE_INT) 0xffff));
   operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff);
 }")
 
@@ -8029,7 +8041,7 @@
 		(match_dup 3)))]
   "
 {
-  operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[1]) & 0xffff0000);
+  operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[1]) & (~ (HOST_WIDE_INT) 0xffff));
   operands[3] = GEN_INT (CONST_DOUBLE_LOW (operands[1]) & 0xffff);
 }")
 
@@ -8050,7 +8062,7 @@
 		(match_dup 3)))]
   "
 {
-  operands[2] = GEN_INT (INTVAL (operands[1]) & 0xffff0000);
+  operands[2] = GEN_INT (INTVAL (operands[1]) & (~ (HOST_WIDE_INT) 0xffff));
   operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff);
 }")
 

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                  aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist    *Please* write to mailing lists, not to me

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]