Index: gcc/genmatch.c
===================================================================
--- gcc/genmatch.c	(revision 217284)
+++ gcc/genmatch.c	(working copy)
@@ -110,6 +110,18 @@
 #if GCC_VERSION >= 4001
 __attribute__((format (printf, 2, 3)))
 #endif
+fatal_at (source_location loc, const char *msg, ...)
+{
+  va_list ap;
+  va_start (ap, msg);
+  error_cb (NULL, CPP_DL_FATAL, 0, loc, 0, msg, &ap);
+  va_end (ap);
+}
+
+static void
+#if GCC_VERSION >= 4001
+__attribute__((format (printf, 2, 3)))
+#endif
 warning_at (const cpp_token *tk, const char *msg, ...)
 {
   va_list ap;
@@ -549,11 +561,11 @@
   simplify (operand *match_, source_location match_location_,
 	    struct operand *result_, source_location result_location_,
 	    vec<if_or_with> ifexpr_vec_, vec<vec<user_id *> > for_vec_,
-	    cid_map_t *capture_ids_)
+	    cid_map_t *capture_ids_, vec<user_id *> oper_lists_ = vNULL)
       : match (match_), match_location (match_location_),
       result (result_), result_location (result_location_),
       ifexpr_vec (ifexpr_vec_), for_vec (for_vec_),
-      capture_ids (capture_ids_), capture_max (capture_ids_->elements () - 1) {}
+      capture_ids (capture_ids_), capture_max (capture_ids_->elements () - 1), oper_lists (oper_lists_) {}
 
   /* The expression that is matched against the GENERIC or GIMPLE IL.  */
   operand *match;
@@ -572,6 +584,8 @@
   /* A map of capture identifiers to indexes.  */
   cid_map_t *capture_ids;
   int capture_max;
+  /* collected operator-list used in expression */
+  vec<user_id *> oper_lists;
 };
 
 /* Debugging routines for dumping the AST.  */
@@ -721,7 +735,7 @@
     {
       simplify *ns = new simplify (matchers[i], s->match_location,
 				   s->result, s->result_location, s->ifexpr_vec,
-				   s->for_vec, s->capture_ids);
+				   s->for_vec, s->capture_ids, s->oper_lists);
       simplifiers.safe_push (ns);
     }
 }
@@ -837,7 +851,7 @@
     {
       simplify *ns = new simplify (matchers[i], s->match_location,
 				   s->result, s->result_location, s->ifexpr_vec,
-				   s->for_vec, s->capture_ids);
+				   s->for_vec, s->capture_ids, s->oper_lists);
       simplifiers.safe_push (ns);
     }
 }
@@ -934,6 +948,38 @@
     simplifiers.safe_push (worklist[i]);
 }
 
+static void
+lower_operator_list (simplify *s, vec<simplify *>& simplifiers)
+{
+  vec<user_id *> oper_lists = s->oper_lists;
+  if (oper_lists == vNULL)
+    {
+      simplifiers.safe_push (s);
+      return;
+    } 
+
+  unsigned min = oper_lists[0]->substitutes.length ();
+  for (unsigned i = 1; i < oper_lists.length (); ++i)
+    if (min > oper_lists[i]->substitutes.length ())
+      min = oper_lists[i]->substitutes.length ();
+
+  for (unsigned i = 0; i < oper_lists.length (); ++i)
+    if (oper_lists[i]->substitutes.length () % min != 0)
+      fatal_at (s->match_location, "All user-defined identifiers must have a multiple number "
+				   "of operator substittions of the smallest number of substitutions");
+
+  vec< vec<user_id *> > for_vec = vNULL;
+  for_vec.safe_push (oper_lists);
+
+  simplify ns (s->match, s->match_location,
+	       s->result, s->result_location,
+	       s->ifexpr_vec, for_vec,
+	       s->capture_ids);
+
+  lower_for (&ns, simplifiers);
+}
+
+
 /* Lower the AST for everything in SIMPLIFIERS.  */
 
 static void
@@ -947,14 +993,15 @@
   for (unsigned i = 0; i < out_simplifiers0.length (); ++i)
     lower_commutative (out_simplifiers0[i], out_simplifiers1);
 
+  auto_vec<simplify *> out_simplifiers2;
+  for (unsigned i = 0;  i < out_simplifiers1.length (); ++i)
+    lower_operator_list (out_simplifiers1[i], out_simplifiers2);
+
   simplifiers.truncate (0);
-  for (unsigned i = 0; i < out_simplifiers1.length (); ++i)
-    lower_for (out_simplifiers1[i], simplifiers);
+  for (unsigned i = 0; i < out_simplifiers2.length (); ++i)
+    lower_for (out_simplifiers2[i], simplifiers);
 }
 
-
-
-
 /* The decision tree built for generating GIMPLE and GENERIC pattern
    matching code.  It represents the 'match' expression of all
    simplifies and has those as its leafs.  */
@@ -2498,10 +2545,13 @@
   void parse_if (source_location);
   void parse_predicates (source_location);
   void parse_operator_list (source_location);
+  
+  bool parsing_for_p () { return active_fors.length () != 0; }
 
   cpp_reader *r;
   vec<if_or_with> active_ifs;
   vec<vec<user_id *> > active_fors;
+  vec<user_id *> oper_lists;
 
   cid_map_t *capture_ids;
 
@@ -2669,8 +2719,11 @@
 
   user_id *p = dyn_cast<user_id *> (op);
   if (p && p->is_oper_list)
-    fatal_at (id_tok, "operator-list not allowed in expression");
-
+    {
+      if (parsing_for_p ()) 
+	fatal_at (id_tok, "operator-list not allowed in expression enclosed in 'for'");
+      oper_lists.safe_push (p);
+    }
   return op;
 }
 
@@ -2807,8 +2860,13 @@
 
       /* If this is possibly a user-defined identifier mark it used.  */
       if (token->type == CPP_NAME)
-	get_operator ((const char *)CPP_HASHNODE
-		        (token->val.node.node)->ident.str);
+	{
+	  id_base *idb = get_operator ((const char *)CPP_HASHNODE
+				      (token->val.node.node)->ident.str);
+	  user_id *p;
+	  if (idb && (p = dyn_cast<user_id *> (idb)) && p->is_oper_list)
+	    oper_lists.safe_push (p);
+	}
 
       /* Record the token.  */
       code.safe_push (*token);
@@ -2893,6 +2951,8 @@
 {
   /* Reset the capture map.  */
   capture_ids = new cid_map_t;
+  /* Reset oper_lists */
+  oper_lists = vNULL;
 
   const cpp_token *loc = peek ();
   parsing_match_operand = true;
@@ -2915,7 +2975,7 @@
       simplifiers.safe_push
 	(new simplify (match, match_location, result, token->src_loc,
 		       active_ifs.copy (), active_fors.copy (),
-		       capture_ids));
+		       capture_ids, oper_lists.copy ()));
       return;
     }
 
@@ -2941,7 +3001,7 @@
 		  simplifiers.safe_push
 		      (new simplify (match, match_location, result,
 				     paren_loc, active_ifs.copy (),
-				     active_fors.copy (), capture_ids));
+				     active_fors.copy (), capture_ids, oper_lists.copy ()));
 		}
 	    }
 	  else if (peek_ident ("with"))
@@ -2960,7 +3020,7 @@
 	      simplifiers.safe_push
 		  (new simplify (match, match_location, op,
 				 token->src_loc, active_ifs.copy (),
-				 active_fors.copy (), capture_ids));
+				 active_fors.copy (), capture_ids, oper_lists.copy ()));
 	      eat_token (CPP_CLOSE_PAREN);
 	      /* A "default" result closes the enclosing scope.  */
 	      if (active_ifs.length () > active_ifs_len)
@@ -2992,7 +3052,7 @@
 	      (new simplify (match, match_location,
 			     matcher ? result : parse_op (),
 			     token->src_loc, active_ifs.copy (),
-			     active_fors.copy (), capture_ids));
+			     active_fors.copy (), capture_ids, oper_lists.copy ()));
 	  /* A "default" result closes the enclosing scope.  */
 	  if (active_ifs.length () > active_ifs_len)
 	    {
@@ -3286,6 +3346,7 @@
   active_ifs = vNULL;
   active_fors = vNULL;
   simplifiers = vNULL;
+  oper_lists = vNULL;
   user_predicates = vNULL;
   parsing_match_operand = false;
 
Index: gcc/match-builtin.pd
===================================================================
--- gcc/match-builtin.pd	(revision 217284)
+++ gcc/match-builtin.pd	(working copy)
@@ -147,8 +147,6 @@
       dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); }
     (POW @0 { build_real (type, dconstroot); }))))
  /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5).  */
- (for SQRT (BUILT_IN_SQRTF BUILT_IN_SQRT BUILT_IN_SQRTL)
-      POW (BUILT_IN_POWF BUILT_IN_POW BUILT_IN_POWL)
   (simplify
-   (SQRT (POW @0 @1))
-   (POW (abs @0) (mult @1 { build_real (TREE_TYPE (@1), dconsthalf); })))))
+   (SQRTs (POWs @0 @1))
+   (POWs (abs @0) (mult @1 { build_real (TREE_TYPE (@1), dconsthalf); }))))
