Index: tree-ssa-operands.h
===================================================================
--- tree-ssa-operands.h.orig	2012-09-06 16:14:30.000000000 +0200
+++ tree-ssa-operands.h	2012-09-06 16:18:33.000000000 +0200
@@ -34,14 +34,6 @@ typedef ssa_use_operand_t *use_operand_p
 #define NULL_USE_OPERAND_P 		((use_operand_p)NULL)
 #define NULL_DEF_OPERAND_P 		((def_operand_p)NULL)
 
-/* This represents the DEF operands of a stmt.  */
-struct def_optype_d
-{
-  struct def_optype_d *next;
-  tree *def_ptr;
-};
-typedef struct def_optype_d *def_optype_p;
-
 /* This represents the USE operands of a stmt.  */
 struct use_optype_d
 {
@@ -68,7 +60,6 @@ struct GTY(()) ssa_operands {
 
    bool ops_active;
 
-   struct def_optype_d * GTY ((skip (""))) free_defs;
    struct use_optype_d * GTY ((skip (""))) free_uses;
 };
 
@@ -82,9 +73,6 @@ struct GTY(()) ssa_operands {
 #define USE_OP_PTR(OP)		(&((OP)->use_ptr))
 #define USE_OP(OP)		(USE_FROM_PTR (USE_OP_PTR (OP)))
 
-#define DEF_OP_PTR(OP)		((OP)->def_ptr)
-#define DEF_OP(OP)		(DEF_FROM_PTR (DEF_OP_PTR (OP)))
-
 #define PHI_RESULT_PTR(PHI)	gimple_phi_result_ptr (PHI)
 #define PHI_RESULT(PHI)		DEF_FROM_PTR (PHI_RESULT_PTR (PHI))
 #define SET_PHI_RESULT(PHI, V)	SET_DEF (PHI_RESULT_PTR (PHI), (V))
@@ -135,11 +123,12 @@ typedef struct ssa_operand_iterator_d
 {
   bool done;
   enum ssa_op_iter_type iter_type;
-  def_optype_p defs;
+  int flags;
+  unsigned def_i;
   use_optype_p uses;
   int phi_i;
   int num_phi;
-  gimple phi_stmt;
+  gimple stmt;
 } ssa_op_iter;
 
 /* These flags are used to determine which operands are returned during
Index: gimple.h
===================================================================
--- gimple.h.orig	2012-09-06 16:14:30.000000000 +0200
+++ gimple.h	2012-09-07 16:01:27.000000000 +0200
@@ -224,12 +226,12 @@ struct GTY(()) gimple_statement_with_ops
   /* [ WORD 1-6 ]  */
   struct gimple_statement_base gsbase;
 
+  /* XXX adjust word count */
   /* [ WORD 7-8 ]
      SSA operand vectors.  NOTE: It should be possible to
      amalgamate these vectors with the operand vector OP.  However,
      the SSA operand vectors are organized differently and contain
      more information (like immediate use chaining).  */
-  struct def_optype_d GTY((skip (""))) *def_ops;
   struct use_optype_d GTY((skip (""))) *use_ops;
 };
 
@@ -1374,27 +1376,6 @@ gimple_has_mem_ops (const_gimple g)
 }
 
 
-/* Return the set of DEF operands for statement G.  */
-
-static inline struct def_optype_d *
-gimple_def_ops (const_gimple g)
-{
-  if (!gimple_has_ops (g))
-    return NULL;
-  return g->gsops.opbase.def_ops;
-}
-
-
-/* Set DEF to be the set of DEF operands for statement G.  */
-
-static inline void
-gimple_set_def_ops (gimple g, struct def_optype_d *def)
-{
-  gcc_gimple_checking_assert (gimple_has_ops (g));
-  g->gsops.opbase.def_ops = def;
-}
-
-
 /* Return the set of USE operands for statement G.  */
 
 static inline struct use_optype_d *
@@ -1434,15 +1415,12 @@ gimple_vuse_op (const_gimple g)
 /* Return the set of VDEF operand for statement G.  */
 
 static inline def_operand_p
-gimple_vdef_op (const_gimple g)
+gimple_vdef_op (gimple g)
 {
-  struct def_optype_d *ops;
   if (!gimple_has_mem_ops (g))
     return NULL_DEF_OPERAND_P;
-  ops = g->gsops.opbase.def_ops;
-  if (ops
-      && DEF_OP_PTR (ops) == &g->gsmembase.vdef)
-    return DEF_OP_PTR (ops);
+  if (g->gsmembase.vdef)
+    return &g->gsmembase.vdef;
   return NULL_DEF_OPERAND_P;
 }
 
Index: tree-flow-inline.h
===================================================================
--- tree-flow-inline.h.orig	2012-09-06 16:14:30.000000000 +0200
+++ tree-flow-inline.h	2012-09-10 17:48:02.000000000 +0200
@@ -582,7 +582,7 @@ op_iter_next_use (ssa_op_iter *ptr)
     }
   if (ptr->phi_i < ptr->num_phi)
     {
-      return PHI_ARG_DEF_PTR (ptr->phi_stmt, (ptr->phi_i)++);
+      return PHI_ARG_DEF_PTR (ptr->stmt, (ptr->phi_i)++);
     }
   ptr->done = true;
   return NULL_USE_OPERAND_P;
@@ -592,13 +592,37 @@ op_iter_next_use (ssa_op_iter *ptr)
 static inline def_operand_p
 op_iter_next_def (ssa_op_iter *ptr)
 {
-  def_operand_p def_p;
   gcc_checking_assert (ptr->iter_type == ssa_op_iter_def);
-  if (ptr->defs)
+  if (ptr->flags & SSA_OP_VDEF)
     {
-      def_p = DEF_OP_PTR (ptr->defs);
-      ptr->defs = ptr->defs->next;
-      return def_p;
+      tree *p;
+      ptr->flags &= ~SSA_OP_VDEF;
+      p = gimple_vdef_ptr (ptr->stmt);
+      if (p && *p)
+	return p;
+    }
+  if (ptr->flags & SSA_OP_DEF)
+    {
+      if (gimple_code (ptr->stmt) != GIMPLE_ASM)
+	{
+	  tree *val;
+	  ptr->flags &= ~SSA_OP_DEF;
+	  val = gimple_op_ptr (ptr->stmt, 0);
+	  if (is_gimple_assign (ptr->stmt) || *val)
+	    {
+	      if (TREE_CODE (*val) == SSA_NAME
+		  || is_gimple_reg (*val))
+		return val;
+	    }
+	}
+      else while (ptr->def_i < gimple_asm_noutputs (ptr->stmt))
+	{
+	  tree link = gimple_asm_output_op (ptr->stmt, ptr->def_i);
+	  ptr->def_i++;
+	  if (TREE_CODE (TREE_VALUE (link)) == SSA_NAME
+	      || is_gimple_reg (TREE_VALUE (link)))
+	    return &TREE_VALUE (link);
+	}
     }
   ptr->done = true;
   return NULL_DEF_OPERAND_P;
@@ -616,16 +640,37 @@ op_iter_next_tree (ssa_op_iter *ptr)
       ptr->uses = ptr->uses->next;
       return val;
     }
-  if (ptr->defs)
+  if (ptr->flags & SSA_OP_VDEF)
     {
-      val = DEF_OP (ptr->defs);
-      ptr->defs = ptr->defs->next;
-      return val;
+      ptr->flags &= ~SSA_OP_VDEF;
+      if ((val = gimple_vdef (ptr->stmt)))
+	return val;
+    }
+  if (ptr->flags & SSA_OP_DEF)
+    {
+      if (gimple_code (ptr->stmt) != GIMPLE_ASM)
+	{
+	  ptr->flags &= ~SSA_OP_DEF;
+	  val = gimple_op (ptr->stmt, 0);
+	  if (is_gimple_assign (ptr->stmt) || val)
+	    {
+	      if (TREE_CODE (val) == SSA_NAME
+		  || is_gimple_reg (val))
+		return val;
+	    }
+	}
+      else while (ptr->def_i < gimple_asm_noutputs (ptr->stmt))
+	{
+	  tree link = gimple_asm_output_op (ptr->stmt, ptr->def_i);
+	  ptr->def_i++;
+	  if (TREE_CODE (TREE_VALUE (link)) == SSA_NAME
+	      || is_gimple_reg (TREE_VALUE (link)))
+	    return TREE_VALUE (link);
+	}
     }
 
   ptr->done = true;
   return NULL_TREE;
-
 }
 
 
@@ -636,13 +681,14 @@ op_iter_next_tree (ssa_op_iter *ptr)
 static inline void
 clear_and_done_ssa_iter (ssa_op_iter *ptr)
 {
-  ptr->defs = NULL;
+  ptr->def_i = 0;
   ptr->uses = NULL;
   ptr->iter_type = ssa_op_iter_none;
   ptr->phi_i = 0;
   ptr->num_phi = 0;
-  ptr->phi_stmt = NULL;
+  ptr->stmt = NULL;
   ptr->done = true;
+  ptr->flags = 0;
 }
 
 /* Initialize the iterator PTR to the virtual defs in STMT.  */
@@ -655,21 +701,34 @@ op_iter_init (ssa_op_iter *ptr, gimple s
   gcc_checking_assert (gimple_code (stmt) != GIMPLE_PHI
 		       && (!(flags & SSA_OP_VDEF) || (flags & SSA_OP_DEF))
 		       && (!(flags & SSA_OP_VUSE) || (flags & SSA_OP_USE)));
-  ptr->defs = (flags & (SSA_OP_DEF|SSA_OP_VDEF)) ? gimple_def_ops (stmt) : NULL;
-  if (!(flags & SSA_OP_VDEF)
-      && ptr->defs
-      && gimple_vdef (stmt) != NULL_TREE)
-    ptr->defs = ptr->defs->next;
+  if (flags & (SSA_OP_DEF | SSA_OP_VDEF))
+    {
+      switch (gimple_code (stmt))
+	{
+	  case GIMPLE_ASSIGN:
+	  case GIMPLE_ASM:
+	  case GIMPLE_CALL:
+	    break;
+	  default:
+	    flags &= ~(SSA_OP_DEF | SSA_OP_VDEF);
+	    break;
+	}
+    }
   ptr->uses = (flags & (SSA_OP_USE|SSA_OP_VUSE)) ? gimple_use_ops (stmt) : NULL;
   if (!(flags & SSA_OP_VUSE)
       && ptr->uses
       && gimple_vuse (stmt) != NULL_TREE)
     ptr->uses = ptr->uses->next;
   ptr->done = false;
+  /* We would have to initialize this only in the GIMPLE_ASM case above,
+     but GCC isn't clever enough to figure out that the uses of this field
+     in the iterator stepper are then not maybe uninitialized.  */
+  ptr->def_i = 0;
 
   ptr->phi_i = 0;
   ptr->num_phi = 0;
-  ptr->phi_stmt = NULL;
+  ptr->stmt = stmt;
+  ptr->flags = flags;
 }
 
 /* Initialize iterator PTR to the use operands in STMT based on FLAGS. Return
@@ -839,9 +898,10 @@ op_iter_init_phiuse (ssa_op_iter *ptr, g
       return NULL_USE_OPERAND_P;
     }
 
-  ptr->phi_stmt = phi;
+  ptr->stmt = phi;
   ptr->num_phi = gimple_phi_num_args (phi);
   ptr->iter_type = ssa_op_iter_use;
+  ptr->flags = flags;
   return op_iter_next_use (ptr);
 }
 
Index: tree-ssa-operands.c
===================================================================
--- tree-ssa-operands.c.orig	2012-09-06 16:14:30.000000000 +0200
+++ tree-ssa-operands.c	2012-09-06 16:18:33.000000000 +0200
@@ -105,9 +105,6 @@ along with GCC; see the file COPYING3.
 /* Operand is in a place where opf_non_addressable does not apply.  */
 #define opf_not_non_addressable (1 << 4)
 
-/* Array for building all the def operands.  */
-static VEC(tree,heap) *build_defs;
-
 /* Array for building all the use operands.  */
 static VEC(tree,heap) *build_uses;
 
@@ -184,7 +181,6 @@ init_ssa_operands (struct function *fn)
 {
   if (!n_initialized++)
     {
-      build_defs = VEC_alloc (tree, heap, 5);
       build_uses = VEC_alloc (tree, heap, 10);
       build_vuse = NULL_TREE;
       build_vdef = NULL_TREE;
@@ -209,13 +205,11 @@ fini_ssa_operands (void)
 
   if (!--n_initialized)
     {
-      VEC_free (tree, heap, build_defs);
       VEC_free (tree, heap, build_uses);
       build_vdef = NULL_TREE;
       build_vuse = NULL_TREE;
     }
 
-  gimple_ssa_operands (cfun)->free_defs = NULL;
   gimple_ssa_operands (cfun)->free_uses = NULL;
 
   while ((ptr = gimple_ssa_operands (cfun)->operand_memory) != NULL)
@@ -241,8 +235,7 @@ ssa_operand_alloc (unsigned size)
 {
   char *ptr;
 
-  gcc_assert (size == sizeof (struct use_optype_d)
-	      || size == sizeof (struct def_optype_d));
+  gcc_assert (size == sizeof (struct use_optype_d));
 
   if (gimple_ssa_operands (cfun)->operand_memory_index + size
       >= gimple_ssa_operands (cfun)->ssa_operand_mem_size)
@@ -281,25 +274,6 @@ ssa_operand_alloc (unsigned size)
 }
 
 
-/* Allocate a DEF operand.  */
-
-static inline struct def_optype_d *
-alloc_def (void)
-{
-  struct def_optype_d *ret;
-  if (gimple_ssa_operands (cfun)->free_defs)
-    {
-      ret = gimple_ssa_operands (cfun)->free_defs;
-      gimple_ssa_operands (cfun)->free_defs
-	= gimple_ssa_operands (cfun)->free_defs->next;
-    }
-  else
-    ret = (struct def_optype_d *)
-	  ssa_operand_alloc (sizeof (struct def_optype_d));
-  return ret;
-}
-
-
 /* Allocate a USE operand.  */
 
 static inline struct use_optype_d *
@@ -319,21 +293,6 @@ alloc_use (void)
 }
 
 
-/* Adds OP to the list of defs after LAST.  */
-
-static inline def_optype_p
-add_def_op (tree *op, def_optype_p last)
-{
-  def_optype_p new_def;
-
-  new_def = alloc_def ();
-  DEF_OP_PTR (new_def) = op;
-  last->next = new_def;
-  new_def->next = NULL;
-  return new_def;
-}
-
-
 /* Adds OP to the list of uses of statement STMT after LAST.  */
 
 static inline use_optype_p
@@ -357,14 +316,6 @@ add_use_op (gimple stmt, tree *op, use_o
 static inline void
 finalize_ssa_defs (gimple stmt)
 {
-  unsigned new_i;
-  struct def_optype_d new_list;
-  def_optype_p old_ops, last;
-  unsigned int num = VEC_length (tree, build_defs);
-
-  /* There should only be a single real definition per assignment.  */
-  gcc_assert ((stmt && gimple_code (stmt) != GIMPLE_ASSIGN) || num <= 1);
-
   /* Pre-pend the vdef we may have built.  */
   if (build_vdef != NULL_TREE)
     {
@@ -374,17 +325,8 @@ finalize_ssa_defs (gimple stmt)
 	oldvdef = SSA_NAME_VAR (oldvdef);
       if (oldvdef != build_vdef)
 	gimple_set_vdef (stmt, build_vdef);
-      VEC_safe_insert (tree, heap, build_defs, 0, (tree)gimple_vdef_ptr (stmt));
-      ++num;
     }
 
-  new_list.next = NULL;
-  last = &new_list;
-
-  old_ops = gimple_def_ops (stmt);
-
-  new_i = 0;
-
   /* Clear and unlink a no longer necessary VDEF.  */
   if (build_vdef == NULL_TREE
       && gimple_vdef (stmt) != NULL_TREE)
@@ -404,30 +346,6 @@ finalize_ssa_defs (gimple stmt)
       cfun->gimple_df->rename_vops = 1;
       cfun->gimple_df->ssa_renaming_needed = 1;
     }
-
-  /* Check for the common case of 1 def that hasn't changed.  */
-  if (old_ops && old_ops->next == NULL && num == 1
-      && (tree *) VEC_index (tree, build_defs, 0) == DEF_OP_PTR (old_ops))
-    return;
-
-  /* If there is anything in the old list, free it.  */
-  if (old_ops)
-    {
-      old_ops->next = gimple_ssa_operands (cfun)->free_defs;
-      gimple_ssa_operands (cfun)->free_defs = old_ops;
-    }
-
-  /* If there is anything remaining in the build_defs list, simply emit it.  */
-  for ( ; new_i < num; new_i++)
-    {
-      tree *op = (tree *) VEC_index (tree, build_defs, new_i);
-      if (DECL_P (*op))
-	cfun->gimple_df->ssa_renaming_needed = 1;
-      last = add_def_op (op, last);
-    }
-
-  /* Now set the stmt's operands.  */
-  gimple_set_def_ops (stmt, new_list.next);
 }
 
 
@@ -487,8 +405,6 @@ finalize_ssa_uses (gimple stmt)
   for (new_i = 0; new_i < VEC_length (tree, build_uses); new_i++)
     {
       tree *op = (tree *) VEC_index (tree, build_uses, new_i);
-      if (DECL_P (*op))
-	cfun->gimple_df->ssa_renaming_needed = 1;
       last = add_use_op (stmt, op, last);
     }
 
@@ -505,7 +421,6 @@ cleanup_build_arrays (void)
 {
   build_vdef = NULL_TREE;
   build_vuse = NULL_TREE;
-  VEC_truncate (tree, build_defs, 0);
   VEC_truncate (tree, build_uses, 0);
 }
 
@@ -526,22 +441,12 @@ finalize_ssa_stmt_operands (gimple stmt)
 static inline void
 start_ssa_stmt_operands (void)
 {
-  gcc_assert (VEC_length (tree, build_defs) == 0);
   gcc_assert (VEC_length (tree, build_uses) == 0);
   gcc_assert (build_vuse == NULL_TREE);
   gcc_assert (build_vdef == NULL_TREE);
 }
 
 
-/* Add DEF_P to the list of pointers to operands.  */
-
-static inline void
-append_def (tree *def_p)
-{
-  VEC_safe_push (tree, heap, build_defs, (tree) def_p);
-}
-
-
 /* Add USE_P to the list of pointers to operands.  */
 
 static inline void
@@ -619,9 +524,11 @@ add_stmt_operand (tree *var_p, gimple st
     {
       /* The variable is a GIMPLE register.  Add it to real operands.  */
       if (flags & opf_def)
-	append_def (var_p);
+	;
       else
 	append_use (var_p);
+      if (DECL_P (*var_p))
+	cfun->gimple_df->ssa_renaming_needed = 1;
     }
   else
     {
@@ -668,15 +575,10 @@ mark_address_taken (tree ref)
    STMT is the statement being processed, EXPR is the MEM_REF
       that got us here.
 
-   FLAGS is as in get_expr_operands.
-
-   RECURSE_ON_BASE should be set to true if we want to continue
-      calling get_expr_operands on the base pointer, and false if
-      something else will do it for us.  */
+   FLAGS is as in get_expr_operands.  */
 
 static void
-get_indirect_ref_operands (gimple stmt, tree expr, int flags,
-			   bool recurse_on_base)
+get_indirect_ref_operands (gimple stmt, tree expr, int flags)
 {
   tree *pptr = &TREE_OPERAND (expr, 0);
 
@@ -688,10 +590,9 @@ get_indirect_ref_operands (gimple stmt,
   add_virtual_operand (stmt, flags);
 
   /* If requested, add a USE operand for the base pointer.  */
-  if (recurse_on_base)
-    get_expr_operands (stmt, pptr,
-		       opf_non_addressable | opf_use
-		       | (flags & (opf_no_vops|opf_not_non_addressable)));
+  get_expr_operands (stmt, pptr,
+		     opf_non_addressable | opf_use
+		     | (flags & (opf_no_vops|opf_not_non_addressable)));
 }
 
 
@@ -855,7 +756,7 @@ get_expr_operands (gimple stmt, tree *ex
       return;
 
     case MEM_REF:
-      get_indirect_ref_operands (stmt, expr, flags, true);
+      get_indirect_ref_operands (stmt, expr, flags);
       return;
 
     case TARGET_MEM_REF:
@@ -1128,31 +1029,6 @@ verify_ssa_operands (gimple stmt)
 	return true;
       }
 
-  FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_DEF)
-    {
-      FOR_EACH_VEC_ELT (tree, build_defs, i, def)
-	{
-	  if (def_p == (tree *)def)
-	    {
-	      VEC_replace (tree, build_defs, i, NULL_TREE);
-	      break;
-	    }
-	}
-      if (i == VEC_length (tree, build_defs))
-	{
-	  error ("excess def operand for stmt");
-	  debug_generic_expr (DEF_FROM_PTR (def_p));
-	  return true;
-	}
-    }
-  FOR_EACH_VEC_ELT (tree, build_defs, i, def)
-    if (def != NULL_TREE)
-      {
-	error ("def operand missing for stmt");
-	debug_generic_expr (*(tree *)def);
-	return true;
-      }
-
   if (gimple_has_volatile_ops (stmt) != volatile_p)
     {
       error ("stmt volatile flag not up-to-date");
@@ -1170,18 +1046,8 @@ verify_ssa_operands (gimple stmt)
 void
 free_stmt_operands (gimple stmt)
 {
-  def_optype_p defs = gimple_def_ops (stmt), last_def;
   use_optype_p uses = gimple_use_ops (stmt), last_use;
 
-  if (defs)
-    {
-      for (last_def = defs; last_def->next; last_def = last_def->next)
-	continue;
-      last_def->next = gimple_ssa_operands (cfun)->free_defs;
-      gimple_ssa_operands (cfun)->free_defs = defs;
-      gimple_set_def_ops (stmt, NULL);
-    }
-
   if (uses)
     {
       for (last_use = uses; last_use->next; last_use = last_use->next)
Index: gimple.c
===================================================================
--- gimple.c.orig	2012-09-06 16:14:30.000000000 +0200
+++ gimple.c	2012-09-06 16:18:33.000000000 +0200
@@ -2370,10 +2370,7 @@ gimple_copy (gimple stmt)
 
       /* Clear out SSA operand vectors on COPY.  */
       if (gimple_has_ops (stmt))
-	{
-	  gimple_set_def_ops (copy, NULL);
-	  gimple_set_use_ops (copy, NULL);
-	}
+	gimple_set_use_ops (copy, NULL);
 
       if (gimple_has_mem_ops (stmt))
 	{
