--- gcc/cgraph.h.jj	2013-11-01 17:11:42.000000000 +0100
+++ gcc/cgraph.h	2013-11-01 17:24:59.472995514 +0100
@@ -250,10 +250,12 @@ struct GTY(()) cgraph_clone_info
   bitmap combined_args_to_skip;
 };
 
-enum linear_stride_type {
-  LINEAR_STRIDE_NO,
-  LINEAR_STRIDE_YES_CONSTANT,
-  LINEAR_STRIDE_YES_VARIABLE
+enum simd_clone_arg_type
+{
+  SIMD_CLONE_ARG_TYPE_VECTOR,
+  SIMD_CLONE_ARG_TYPE_UNIFORM,
+  SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP,
+  SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP
 };
 
 /* Function arguments in the original function of a SIMD clone.
@@ -282,28 +284,17 @@ struct GTY(()) simd_clone_arg {
   tree simd_array;
 
   /* A SIMD clone's argument can be either linear (constant or
-     variable), uniform, or vector.  If the argument is neither linear
-     or uniform, the default is vector.  */
+     variable), uniform, or vector.  */
+  enum simd_clone_arg_type arg_type;
 
-  /* If the linear stride is a constant, `linear_stride' is
-     LINEAR_STRIDE_YES_CONSTANT, and `linear_stride_num' holds
-     the numeric stride.
-
-     If the linear stride is variable, `linear_stride' is
-     LINEAR_STRIDE_YES_VARIABLE, and `linear_stride_num' contains
-     the function argument containing the stride (as an index into the
-     function arguments starting at 0).
-
-     Otherwise, `linear_stride' is LINEAR_STRIDE_NO and
-     `linear_stride_num' is unused.  */
-  enum linear_stride_type linear_stride;
-  unsigned HOST_WIDE_INT linear_stride_num;
+  /* For arg_type SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP this is
+     the constant linear step, if arg_type is
+     SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP, this is index of
+     the uniform argument holding the step, otherwise 0.  */
+  HOST_WIDE_INT linear_step;
 
   /* Variable alignment if available, otherwise 0.  */
   unsigned int alignment;
-
-  /* True if variable is uniform.  */
-  unsigned int uniform : 1;
 };
 
 /* Specific data for a SIMD function clone.  */
--- gcc/omp-low.c.jj	2013-11-01 17:11:42.000000000 +0100
+++ gcc/omp-low.c	2013-11-01 17:41:26.635904034 +0100
@@ -10561,8 +10561,8 @@ static struct simd_clone *
 simd_clone_struct_alloc (int nargs)
 {
   struct simd_clone *clone_info;
-  int len = sizeof (struct simd_clone)
-    + nargs * sizeof (struct simd_clone_arg);
+  size_t len = (sizeof (struct simd_clone)
+		+ nargs * sizeof (struct simd_clone_arg));
   clone_info = ggc_alloc_cleared_simd_clone_stat (len PASS_MEM_STAT);
   return clone_info;
 }
@@ -10572,8 +10572,8 @@ simd_clone_struct_alloc (int nargs)
 static inline void
 simd_clone_struct_copy (struct simd_clone *to, struct simd_clone *from)
 {
-  memcpy (to, from, sizeof (struct simd_clone)
-	  + from->nargs * sizeof (struct simd_clone_arg));
+  memcpy (to, from, (sizeof (struct simd_clone)
+		     + from->nargs * sizeof (struct simd_clone_arg)));
 }
 
 /* Given a simd clone in NEW_NODE, extract the simd specific
@@ -10637,31 +10637,27 @@ simd_clone_clauses_extract (struct cgrap
 	    int argno = TREE_INT_CST_LOW (decl);
 	    if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
 	      {
-		clone_info->args[argno].linear_stride
-		  = LINEAR_STRIDE_YES_VARIABLE;
-		clone_info->args[argno].linear_stride_num
-		  = TREE_INT_CST_LOW (step);
-		gcc_assert (!TREE_INT_CST_HIGH (step));
+		clone_info->args[argno].arg_type
+		  = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
+		clone_info->args[argno].linear_step
+		  = tree_low_cst (step, 0);
+		gcc_assert (clone_info->args[argno].linear_step >= 0
+			    && clone_info->args[argno].linear_step < n);
 	      }
 	    else
 	      {
-		if (TREE_INT_CST_HIGH (step))
-		  {
-		    /* It looks like this can't really happen, since the
-		       front-ends generally issue:
-
-		       warning: integer constant is too large for its type.
-
-		       But let's assume somehow we got past all that.  */
-		    warning_at (DECL_SOURCE_LOCATION (decl), 0,
-				"ignoring large linear step");
-		  }
+		if (!host_integerp (step, 0))
+		  warning_at (OMP_CLAUSE_LOCATION (t), 0,
+			      "ignoring large linear step");
+		else if (integer_zerop (step))
+		  warning_at (OMP_CLAUSE_LOCATION (t), 0,
+			      "ignoring zero linear step");
 		else
 		  {
-		    clone_info->args[argno].linear_stride
-		      = LINEAR_STRIDE_YES_CONSTANT;
-		    clone_info->args[argno].linear_stride_num
-		      = TREE_INT_CST_LOW (step);
+		    clone_info->args[argno].arg_type
+		      = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
+		    clone_info->args[argno].linear_step
+		      = tree_low_cst (step, 0);
 		  }
 	      }
 	    break;
@@ -10670,7 +10666,8 @@ simd_clone_clauses_extract (struct cgrap
 	  {
 	    tree decl = OMP_CLAUSE_DECL (t);
 	    int argno = tree_low_cst (decl, 1);
-	    clone_info->args[argno].uniform = 1;
+	    clone_info->args[argno].arg_type
+	      = SIMD_CLONE_ARG_TYPE_UNIFORM;
 	    break;
 	  }
 	case OMP_CLAUSE_ALIGNED:
@@ -10731,14 +10728,12 @@ simd_clone_compute_base_data_type (struc
     {
       argno_map map (fndecl);
       for (unsigned int i = 0; i < new_node->simdclone->nargs; ++i)
-	{
-	  struct simd_clone_arg arg = new_node->simdclone->args[i];
-	  if (!arg.uniform && arg.linear_stride == LINEAR_STRIDE_NO)
-	    {
-	      type = TREE_TYPE (map[i]);
-	      break;
-	    }
-	}
+	if (new_node->simdclone->args[i].arg_type
+	    == SIMD_CLONE_ARG_TYPE_VECTOR)
+	  {
+	    type = TREE_TYPE (map[i]);
+	    break;
+	  }
     }
 
   /* c) If the characteristic data type determined by a) or b) above
@@ -10824,20 +10819,25 @@ simd_clone_mangle (struct cgraph_node *o
     {
       struct simd_clone_arg arg = new_node->simdclone->args[n];
 
-      if (arg.uniform)
+      if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
 	pp_character (&pp, 'u');
-      else if (arg.linear_stride == LINEAR_STRIDE_YES_CONSTANT)
+      else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
 	{
-	  gcc_assert (arg.linear_stride_num != 0);
+	  gcc_assert (arg.linear_step != 0);
 	  pp_character (&pp, 'l');
-	  if (arg.linear_stride_num > 1)
-	    pp_unsigned_wide_integer (&pp,
-				      arg.linear_stride_num);
+	  if (arg.linear_step > 0)
+	    pp_unsigned_wide_integer (&pp, arg.linear_step);
+	  else
+	    {
+	      pp_character (&pp, 'n');
+	      pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
+					      arg.linear_step));
+	    }
 	}
-      else if (arg.linear_stride == LINEAR_STRIDE_YES_VARIABLE)
+      else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
 	{
 	  pp_character (&pp, 's');
-	  pp_unsigned_wide_integer (&pp, arg.linear_stride_num);
+	  pp_unsigned_wide_integer (&pp, arg.linear_step);
 	}
       else
 	pp_character (&pp, 'v');
@@ -10975,8 +10975,7 @@ simd_clone_adjust_argument_types (struct
 
       node->simdclone->args[i].orig_arg = parm;
 
-      if (node->simdclone->args[i].uniform
-	  || node->simdclone->args[i].linear_stride != LINEAR_STRIDE_NO)
+      if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
 	{
 	  /* No adjustment necessary for scalar arguments.  */
 	  adj.copy_param = 1;
