diff mbox

[match-and-simplify] Add predicate expressions

Message ID alpine.LSU.2.11.1409231253140.20733@zhemvz.fhfr.qr
State New
Headers show

Commit Message

Richard Biener Sept. 23, 2014, 11:02 a.m. UTC
As promised this allows you to define custom predicate expressions
(or operators), like one modeled after 
tree-ssa-forwprop.c:lookup_logical_inverted_value:

(match logical_inverted_value
 (bit_not truth_valued_p@0)
 (logical_inverted_value @0))
(match logical_inverted_value
 (eq @0 integer_zerop)
 (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))
  (logical_inverted_value @0)))
(match logical_inverted_value
 (ne truth_valued_p@0 integer_onep)
 (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))
  (logical_inverted_value @0)))
(match logical_inverted_value
 (bit_xor truth_valued_p@0 integer_onep)
 (logical_inverted_value @0))

which you can use as (logical_inverted_value <op>) anywhere in
expressions you want to match, like for example

/* X & !X -> 0.  */
(simplify
 (bit_and @0 (logical_inverted_value @0))
 { build_zero_cst (type); })

you can continue matching on the result, thus write
(logical_inverted_value (plus @0 INTEGER_CST)) (doesn't make
much sense for this example though).  The result of
logical_inverted_value is then matched against the expression.

I noticed that parsing of 'for' and outer 'if's is broken with
respect to all (match ...)es.  The patch is big enough already,
I'll try to fix that as followup ('if' is easy, 'for' is more
interesting).

As usage example I've taken the forwprop simplify_bitwise_binary_1
code.

Note that code-generation using predicate expressions is worse
than if you manually inline-expand all cases (and the generator
doesn't yet inline-expand here - but it could, at least in theory).

You can now write pattern-based IL matching for, say, vectorizer
pattern detection and use it via the generated APIs that follows

bool gimple_logical_inverted_value (tree t, tree *res_ops, tree 
(*valueize)(tree) = NULL);

where res_ops[0] will contain the matched operands of the
operation.

Bootstrap and regtest in progress.

Richard.

2014-09-23  Richard Biener  <rguenther@suse.de>

	* genmatch.c (struct predicate_id): Add nargs member.
	(struct simplify): Remove name member.
	(lower_commutative): Adjust.
	(lower_opt_convert): Likewise.
	(dt_node::gen_gimple_kids): Generate code for predicate
	expressions.
	(dt_node::gen_generic_kids): Likewise.
	(dt_simplify::gen): Likewise.
	(write_predicate_prototype): New function.
	(write_predicate): Adjust.
	(parse_simplify): Be less forgiving about errors, handle
	predicate expression definitions.
	(parse_pattern): Adjust.
	(main): Output prototypes for all predicates first.
	* match-bitwise.pd (X & !X -> 0, X | !X and X ^ !X -> 1):
	Implement using predicate expressions, more closely matching
	code in tree-ssa-forwprop.c.
diff mbox

Patch

Index: gcc/genmatch.c
===================================================================
--- gcc/genmatch.c	(revision 215499)
+++ gcc/genmatch.c	(working copy)
@@ -193,8 +193,9 @@  struct simplify;
 struct predicate_id : public id_base
 {
   predicate_id (const char *id_)
-    : id_base (id_base::PREDICATE, id_), matchers (vNULL) {}
+    : id_base (id_base::PREDICATE, id_), matchers (vNULL), nargs(-1) {}
   vec<simplify *> matchers;
+  int nargs;
 };
 
 template<>
@@ -433,14 +434,12 @@  struct if_or_with {
 };
 
 struct simplify {
-  simplify (const char *name_,
-	    operand *match_, source_location match_location_,
+  simplify (operand *match_, source_location match_location_,
 	    struct operand *result_, source_location result_location_, vec<if_or_with> ifexpr_vec_ = vNULL)
-      : name (name_), match (match_), match_location (match_location_),
+      : match (match_), match_location (match_location_),
       result (result_), result_location (result_location_),
       ifexpr_vec (ifexpr_vec_) {}
 
-  const char *name;
   operand *match; 
   source_location match_location;
   struct operand *result;
@@ -682,7 +681,7 @@  lower_commutative (simplify *s, vec<simp
   vec<operand *> matchers = commutate (s->match);
   for (unsigned i = 0; i < matchers.length (); ++i)
     {
-      simplify *ns = new simplify (s->name, matchers[i], s->match_location,
+      simplify *ns = new simplify (matchers[i], s->match_location,
 				   s->result, s->result_location, s->ifexpr_vec);
       simplifiers.safe_push (ns);
     }
@@ -810,7 +809,7 @@  lower_opt_convert (simplify *s, vec<simp
   vec<operand *> matchers = lower_opt_convert (s->match);
   for (unsigned i = 0; i < matchers.length (); ++i)
     {
-      simplify *ns = new simplify (s->name, matchers[i], s->match_location,
+      simplify *ns = new simplify (matchers[i], s->match_location,
 				   s->result, s->result_location, s->ifexpr_vec);
       simplifiers.safe_push (ns);
     }
@@ -1512,10 +1511,11 @@  dt_operand::gen_generic_expr (FILE *f, c
 void
 dt_node::gen_gimple_kids (FILE *f)
 {
-  vec<dt_operand *> gimple_exprs = vNULL;
-  vec<dt_operand *> generic_exprs = vNULL;
-  vec<dt_operand *> fns = vNULL;
-  vec<dt_node *> others = vNULL;
+  auto_vec<dt_operand *> gimple_exprs;
+  auto_vec<dt_operand *> generic_exprs;
+  auto_vec<dt_operand *> fns;
+  auto_vec<dt_operand *> preds;
+  auto_vec<dt_node *> others;
   dt_node *true_operand = NULL;
   for (unsigned i = 0; i < kids.length (); ++i)
     {
@@ -1527,6 +1527,8 @@  dt_node::gen_gimple_kids (FILE *f)
 		generic_exprs.safe_push (op);
 	      else if (e->operation->op->kind == id_base::FN)
 		fns.safe_push (op);
+	      else if (e->operation->op->kind == id_base::PREDICATE)
+		preds.safe_push (op);
 	      else
 		gimple_exprs.safe_push (op);
 	    }
@@ -1638,6 +1640,25 @@  dt_node::gen_gimple_kids (FILE *f)
     fprintf (f, "default:;\n"
 	     "}\n");
 
+  for (unsigned i = 0; i < preds.length (); ++i)
+    {
+      expr *e = as_a <expr *> (preds[i]->op);
+      predicate_id *p = as_a <predicate_id *> (e->operation->op);
+      preds[i]->get_name (kid_opname);
+      fprintf (f, "tree %s_pops[%d];\n", kid_opname, p->nargs);
+      fprintf (f, "if (gimple_%s (%s, %s_pops, valueize))\n", p->id,
+	       kid_opname, kid_opname);
+      fprintf (f, "{\n");
+      for (int j = 0; j < p->nargs; ++j)
+	{
+	  char child_opname[20];
+	  preds[i]->gen_opname (child_opname, j);
+	  fprintf (f, "tree %s = %s_pops[%d];\n", child_opname, kid_opname, j);
+	}
+      preds[i]->gen_gimple_kids (f);
+      fprintf (f, "}\n");
+    }
+
   for (unsigned i = 0; i < others.length (); ++i)
     others[i]->gen_gimple (f);
 
@@ -1721,6 +1742,10 @@  dt_operand::gen_generic (FILE *f)
 void
 dt_node::gen_generic_kids (FILE *f)
 {
+  auto_vec<dt_operand *> generic_exprs;
+  auto_vec<dt_operand *> fns;
+  auto_vec<dt_operand *> preds;
+
   bool any = false;
   for (unsigned j = 0; j < kids.length (); ++j)
     {
@@ -1729,7 +1754,23 @@  dt_node::gen_generic_kids (FILE *f)
 	{
 	  dt_operand *kid = static_cast<dt_operand *>(node);
 	  if (kid->op->type == operand::OP_EXPR)
-	    any = true;
+	    {
+	      expr *e = as_a <expr *> (kid->op);
+	      if (e->operation->op->kind == id_base::CODE)
+		{
+		  generic_exprs.safe_push (kid);
+		  any = true;
+		}
+	      else if (e->operation->op->kind == id_base::FN)
+		{
+		  fns.safe_push (kid);
+		  any = true;
+		}
+	      else if (e->operation->op->kind == id_base::PREDICATE)
+		preds.safe_push (kid);
+	      else
+		gcc_unreachable ();
+	    }
 	}
     }
 
@@ -1739,17 +1780,11 @@  dt_node::gen_generic_kids (FILE *f)
       static_cast <dt_operand *>(kids[0])->get_name (opname); 
       fprintf (f, "switch (TREE_CODE (%s))\n"
 	       "{\n", opname);
-      for (unsigned j = 0; j < kids.length (); ++j)
+      for (unsigned j = 0; j < generic_exprs.length (); ++j)
 	{
-	  dt_node *node = kids[j];
-	  if (node->type != DT_OPERAND)
-	    continue;
-	  dt_operand *kid = static_cast<dt_operand *>(node);
-	  if (kid->op->type != operand::OP_EXPR)
-	    continue;
-	  expr *e = static_cast <expr *>(kid->op);
-	  if (e->operation->op->kind != id_base::CODE)
-	    continue;
+	  dt_operand *kid = generic_exprs[j];
+	  expr *e = as_a <expr *>(kid->op);
+	  gcc_assert (e->operation->op->kind == id_base::CODE);
 
 	  /* ??? CONVERT */
 	  fprintf (f, "case %s:\n"
@@ -1760,17 +1795,11 @@  dt_node::gen_generic_kids (FILE *f)
 	}
 
       bool first = true;
-      for (unsigned j = 0; j < kids.length (); ++j)
+      for (unsigned j = 0; j < fns.length (); ++j)
 	{
-	  dt_node *node = kids[j];
-	  if (node->type != DT_OPERAND)
-	    continue;
-	  dt_operand *kid = static_cast<dt_operand *>(node);
-	  if (kid->op->type != operand::OP_EXPR)
-	    continue;
-	  expr *e = static_cast <expr *>(kid->op);
-	  if (e->operation->op->kind != id_base::FN)
-	    continue;
+	  dt_operand *kid = fns[j];
+	  expr *e = as_a <expr *>(kid->op);
+	  gcc_assert (e->operation->op->kind == id_base::FN);
 
 	  if (first)
 	    fprintf (f, "case CALL_EXPR:\n"
@@ -1797,6 +1826,26 @@  dt_node::gen_generic_kids (FILE *f)
 	       "}\n");
     }
 
+  for (unsigned i = 0; i < preds.length (); ++i)
+    {
+      expr *e = as_a <expr *> (preds[i]->op);
+      predicate_id *p = as_a <predicate_id *> (e->operation->op);
+      char kid_opname[128];
+      preds[i]->get_name (kid_opname);
+      fprintf (f, "tree %s_pops[%d];\n", kid_opname, p->nargs);
+      fprintf (f, "if (tree_%s (%s, %s_pops))\n", p->id,
+	       kid_opname, kid_opname);
+      fprintf (f, "{\n");
+      for (int j = 0; j < p->nargs; ++j)
+	{
+	  char child_opname[20];
+	  preds[i]->gen_opname (child_opname, j);
+	  fprintf (f, "tree %s = %s_pops[%d];\n", child_opname, kid_opname, j);
+	}
+      preds[i]->gen_generic_kids (f);
+      fprintf (f, "}\n");
+    }
+
   for (unsigned j = 0; j < kids.length (); ++j)
     {
       dt_node *node = kids[j];
@@ -1887,23 +1936,27 @@  dt_simplify::gen (FILE *f, bool gimple)
     {
       if (s->result->type == operand::OP_EXPR)
 	{
-	  expr *e = static_cast <expr *> (s->result);
-	  fprintf (f, "*res_code = %s;\n", e->operation->op->id);
+	  expr *e = as_a <expr *> (s->result);
+	  bool is_predicate = is_a <predicate_id *> (e->operation->op);
+	  if (!is_predicate)
+	    fprintf (f, "*res_code = %s;\n", e->operation->op->id);
 	  for (unsigned j = 0; j < e->ops.length (); ++j)
 	    {
 	      char dest[32];
 	      snprintf (dest, 32, "  res_ops[%d]", j);
 	      const char *optype
-	        = get_operand_type (e->operation->op,
-				    "type", e->expr_type,
-				    j == 0
-				    ? NULL : "TREE_TYPE (res_ops[0])");
+		  = get_operand_type (e->operation->op,
+				      "type", e->expr_type,
+				      j == 0
+				      ? NULL : "TREE_TYPE (res_ops[0])");
 	      e->ops[j]->gen_transform (f, dest, true, 1, optype, indexes);
 	    }
+
 	  /* Re-fold the toplevel result.  It's basically an embedded
 	     gimple_build w/o actually building the stmt.  */
-	  fprintf (f, "gimple_resimplify%d (seq, res_code, type, "
-		   "res_ops, valueize);\n", e->ops.length ());
+	  if (!is_predicate)
+	    fprintf (f, "gimple_resimplify%d (seq, res_code, type, "
+		     "res_ops, valueize);\n", e->ops.length ());
 	}
       else if (s->result->type == operand::OP_CAPTURE
 	       || s->result->type == operand::OP_C_EXPR)
@@ -1919,12 +1972,18 @@  dt_simplify::gen (FILE *f, bool gimple)
     {
       if (s->result->type == operand::OP_EXPR)
 	{
-	  expr *e = static_cast <expr *> (s->result);
+	  expr *e = as_a <expr *> (s->result);
+	  bool is_predicate = is_a <predicate_id *> (e->operation->op);
 	  for (unsigned j = 0; j < e->ops.length (); ++j)
 	    {
-	      fprintf (f, "   tree res_op%d;\n", j);
 	      char dest[32];
-	      snprintf (dest, 32, "  res_op%d", j);
+	      if (is_predicate)
+		snprintf (dest, 32, "res_ops[%d]", j);
+	      else
+		{
+		  fprintf (f, "   tree res_op%d;\n", j);
+		  snprintf (dest, 32, "  res_op%d", j);
+		}
 	      const char *optype
 	        = get_operand_type (e->operation->op,
 				    "type", e->expr_type,
@@ -1932,16 +1991,21 @@  dt_simplify::gen (FILE *f, bool gimple)
 				    ? NULL : "TREE_TYPE (res_op0)");
 	      e->ops[j]->gen_transform (f, dest, false, 1, optype, indexes);
 	    }
-	  /* Re-fold the toplevel result.  */
-	  if (e->operation->op->kind == id_base::CODE)
-	    fprintf (f, "  return fold_build%d (%s, type",
-		     e->ops.length (), e->operation->op->id);
+	  if (is_a <predicate_id *> (e->operation->op))
+	    fprintf (f, "return true;\n");
 	  else
-	    fprintf (f, "  return build_call_expr (builtin_decl_implicit (%s), %d",
-		     e->operation->op->id, e->ops.length());
-	  for (unsigned j = 0; j < e->ops.length (); ++j)
-	    fprintf (f, ", res_op%d", j);
-	  fprintf (f, ");\n");
+	    {
+	      /* Re-fold the toplevel result.  */
+	      if (e->operation->op->kind == id_base::CODE)
+		fprintf (f, "  return fold_build%d (%s, type",
+			 e->ops.length (), e->operation->op->id);
+	      else
+		fprintf (f, "  return build_call_expr (builtin_decl_implicit (%s), %d",
+			 e->operation->op->id, e->ops.length());
+	      for (unsigned j = 0; j < e->ops.length (); ++j)
+		fprintf (f, ", res_op%d", j);
+	      fprintf (f, ");\n");
+	    }
 	}
       else if (s->result->type == operand::OP_CAPTURE
 	       || s->result->type == operand::OP_C_EXPR)
@@ -2062,12 +2126,22 @@  decision_tree::gen_generic (FILE *f)
 }
 
 void
+write_predicate_prototype (FILE *f, predicate_id *p, bool gimple)
+{
+  fprintf (f, "bool %s%s (tree t%s%s);\n",
+	   gimple ? "gimple_" : "tree_", p->id,
+	   p->nargs > 0 ? ", tree *res_ops" : "",
+	   gimple ? ", tree (*valueize)(tree) = NULL" : "");
+}
+
+void
 write_predicate (FILE *f, predicate_id *p, decision_tree &dt, bool gimple)
 {
   fprintf (f, "\nbool\n"
-	   "%s%s (tree t%s)\n"
+	   "%s%s (tree t%s%s)\n"
 	   "{\n", gimple ? "gimple_" : "tree_", p->id,
-	   gimple ? ", tree (*valueize)(tree) = NULL" : "");
+	   p->nargs > 0 ? ", tree *res_ops" : "",
+	   gimple ? ", tree (*valueize)(tree)" : "");
   /* Conveniently make 'type' available.  */
   fprintf (f, "tree type = TREE_TYPE (t);\n");
 
@@ -2458,13 +2532,16 @@  copy_reverse (vec<T> v)
    and fill SIMPLIFIERS with the results.  */
 
 static void
-parse_simplify (cpp_reader *r, const char *id, source_location match_location,
-		vec<simplify *>& simplifiers)
+parse_simplify (cpp_reader *r, source_location match_location,
+		vec<simplify *>& simplifiers, predicate_id *matcher)
 {
   const cpp_token *loc = peek (r);
   struct operand *match = parse_op (r);
-  if (match->type != operand::OP_EXPR)
-    fatal_at (loc, "expected uncaptured expression");
+  if (match->type == operand::OP_CAPTURE && !matcher)
+    fatal_at (loc, "outermost expression cannot be captured");
+  if (match->type == operand::OP_EXPR
+      && is_a <predicate_id *> (as_a <expr *> (match)->operation->op))
+    fatal_at (loc, "outermost expression cannot be a predicate");
 
   const cpp_token *token = peek (r);
 
@@ -2472,8 +2549,14 @@  parse_simplify (cpp_reader *r, const cha
      definition.  Push it.  */
   if (token->type == CPP_CLOSE_PAREN)
     {
+      if (!matcher)
+	fatal_at (token, "expected transform expression");
+      else if (matcher->nargs > 0)
+	fatal_at (token, "expected match operand expression");
+      if (matcher->nargs == -1)
+	matcher->nargs = 0;
       simplifiers.safe_push
-	(new simplify (id, match, match_location, NULL, token->src_loc));
+	(new simplify (match, match_location, NULL, token->src_loc));
       return;
     }
 
@@ -2493,9 +2576,17 @@  parse_simplify (cpp_reader *r, const cha
 	         manual matcher or is part of a predicate definition.
 		 Push it.  */
 	      if (peek (r)->type == CPP_CLOSE_PAREN)
-		simplifiers.safe_push
-		   (new simplify (id, match, match_location, NULL,
-				  paren_loc, copy_reverse (ifexprs)));
+		{
+		  if (!matcher)
+		    fatal_at (token, "manual transform not implemented");
+		  else if (matcher->nargs > 0)
+		    fatal_at (token, "expected match operand expression");
+		  if (matcher->nargs == -1)
+		    matcher->nargs = 0;
+		  simplifiers.safe_push
+		      (new simplify (match, match_location, NULL,
+				     paren_loc, copy_reverse (ifexprs)));
+		}
 	    }
 	  else if (peek_ident (r, "with"))
 	    {
@@ -2507,8 +2598,20 @@  parse_simplify (cpp_reader *r, const cha
 	    }
 	  else
 	    {
+	      operand *op = parse_expr (r);
+	      if (matcher)
+		{
+		  expr *e = dyn_cast <expr *> (op);
+		  if (!e)
+		    fatal_at (token, "match operand expression cannot be captured");
+		  if (matcher->nargs == -1)
+		    matcher->nargs = e->ops.length ();
+		  if (matcher->nargs == 0
+		      || (unsigned) matcher->nargs != e->ops.length ())
+		    fatal_at (token, "match arity doesn't match");
+		}
 	      simplifiers.safe_push
-		  (new simplify (id, match, match_location, parse_expr (r),
+		  (new simplify (match, match_location, op,
 				 token->src_loc, copy_reverse (ifexprs)));
 	      eat_token (r, CPP_CLOSE_PAREN);
 	      /* A "default" result closes the enclosing scope.  */
@@ -2535,8 +2638,10 @@  parse_simplify (cpp_reader *r, const cha
 	}
       else
 	{
+	  if (matcher)
+	    fatal_at (token, "expected match operand expression");
 	  simplifiers.safe_push
-	      (new simplify (id, match, match_location, parse_op (r),
+	      (new simplify (match, match_location, parse_op (r),
 			     token->src_loc, copy_reverse (ifexprs)));
 	  /* A "default" result closes the enclosing scope.  */
 	  if (ifexprs.length () > 0)
@@ -2654,7 +2759,7 @@  parse_for (cpp_reader *r, source_locatio
 		ifexpr_vec[k].cexpr = replace_id (ifexpr_vec[k].cexpr, user_ids[i], oper);
 
 	    }
-	  simplify *ns = new simplify (s->name, match_op, s->match_location,
+	  simplify *ns = new simplify (match_op, s->match_location,
 				       result_op, s->result_location, ifexpr_vec);
 	  simplifiers.safe_push (ns);
 	}
@@ -2713,7 +2818,7 @@  parse_pattern (cpp_reader *r, vec<simpli
   const cpp_token *token = peek (r);
   const char *id = get_ident (r);
   if (strcmp (id, "simplify") == 0)
-    parse_simplify (r, NULL, token->src_loc, simplifiers);
+    parse_simplify (r, token->src_loc, simplifiers, NULL);
   else if (strcmp (id, "match") == 0)
     {
       const char *name = get_ident (r);
@@ -2725,8 +2830,7 @@  parse_pattern (cpp_reader *r, vec<simpli
 	;
       else
 	fatal_at (token, "cannot add a match to a non-predicate ID");
-      parse_simplify (r, name, token->src_loc, p->matchers);
-      /* ???  Sanity check the added "simplifiers".  */
+      parse_simplify (r, token->src_loc, p->matchers, p);
     }
   else if (strcmp (id, "for") == 0)
     parse_for (r, token->src_loc, simplifiers); 
@@ -2839,6 +2943,15 @@  add_operator (CONVERT2, "CONVERT2", "tcc
   for (hash_table<id_base>::iterator iter = operators->begin ();
        iter != operators->end (); ++iter)
     {
+      id_base *id = *iter;
+      if (predicate_id *p = dyn_cast <predicate_id *> (id))
+	if (p->matchers.exists ())
+	  /* ???  Write prototypes to some header?  */
+	  write_predicate_prototype (stdout, p, gimple);
+    }
+  for (hash_table<id_base>::iterator iter = operators->begin ();
+       iter != operators->end (); ++iter)
+    {
       id_base *id = *iter;
       if (predicate_id *p = dyn_cast <predicate_id *> (id))
 	if (p->matchers.exists ())
Index: gcc/match-bitwise.pd
===================================================================
--- gcc/match-bitwise.pd	(revision 215499)
+++ gcc/match-bitwise.pd	(working copy)
@@ -65,6 +65,42 @@  along with GCC; see the file COPYING3.
 
 /* Try simple folding for X op !X, and X op X.
    From tree-ssa-forwprop.c:simplify_bitwise_binary_1.  */
+/* tree-ssa-forwprop.c:truth_valued_ssa_name.  */
+(match truth_valued_p
+ @0
+ (if (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1)))
+#if 0
+/* ???  for doesn't yet work for matchers.  */
+(for op (lt le eq ne ge gt truth_and truth_andif truth_or truth_orif truth_xor)
+ (match truth_valued_p
+  (op @0 @1)))
+#endif
+(match truth_valued_p
+  (truth_not @0))
+(match logical_inverted_value
+ (bit_not truth_valued_p@0)
+ (logical_inverted_value @0))
+(match logical_inverted_value
+ (eq @0 integer_zerop)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))
+  (logical_inverted_value @0)))
+(match logical_inverted_value
+ (ne truth_valued_p@0 integer_onep)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))
+  (logical_inverted_value @0)))
+(match logical_inverted_value
+ (bit_xor truth_valued_p@0 integer_onep)
+ (logical_inverted_value @0))
+/* X & !X -> 0.  */
+(simplify
+ (bit_and @0 (logical_inverted_value @0))
+ { build_zero_cst (type); })
+/* X | !X and X ^ !X -> 1, , if X is truth-valued.  */
+(for op (bit_ior bit_xor)
+ (simplify
+  (op truth_valued_p@0 (logical_inverted_value @0))
+  { build_one_cst (type); }))
+#if 0
 /* x & x -> x,  x | x -> x  */
 (for bitop (bit_and bit_ior)
  (simplify
@@ -98,6 +134,7 @@  along with GCC; see the file COPYING3.
    (if (truth_valued_ssa_name (@0))
     { bitop == BIT_AND ? build_zero_cst (type) : build_one_cst (type); }))))
 #endif
+#endif
 
 (for bitop (bit_and bit_ior)
      rbitop (bit_ior bit_and)