diff --git a/gcc/asan.c b/gcc/asan.c
index af9c01e..571882a 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -1379,57 +1379,15 @@ build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter,
       /* Slow path for 1, 2 and 4 byte accesses.
 	 Test (shadow != 0)
 	      & ((base_addr & 7) + (size_in_bytes - 1)) >= shadow).  */
-      g = gimple_build_assign_with_ops (NE_EXPR,
-					make_ssa_name (boolean_type_node,
-						       NULL),
-					shadow,
-					build_int_cst (shadow_type, 0));
-      gimple_set_location (g, location);
-      gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-      t = gimple_assign_lhs (g);
-
-      g = gimple_build_assign_with_ops (BIT_AND_EXPR,
-					make_ssa_name (uintptr_type,
-						       NULL),
-					base_addr,
-					build_int_cst (uintptr_type, 7));
-      gimple_set_location (g, location);
-      gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-
-      g = gimple_build_assign_with_ops (NOP_EXPR,
-					make_ssa_name (shadow_type,
-						       NULL),
-					gimple_assign_lhs (g), NULL_TREE);
-      gimple_set_location (g, location);
-      gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-
+      gimple_builder_ssa gb(location);
+      t = gb.add (NE_EXPR, shadow, 0);
+      tree t1 = gb.add (BIT_AND_EXPR, base_addr, 7);
+      t1 = gb.add_type_cast (shadow_type, t1);
       if (size_in_bytes > 1)
-	{
-	  g = gimple_build_assign_with_ops (PLUS_EXPR,
-					    make_ssa_name (shadow_type,
-							   NULL),
-					    gimple_assign_lhs (g),
-					    build_int_cst (shadow_type,
-							   size_in_bytes - 1));
-	  gimple_set_location (g, location);
-	  gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-	}
-
-      g = gimple_build_assign_with_ops (GE_EXPR,
-					make_ssa_name (boolean_type_node,
-						       NULL),
-					gimple_assign_lhs (g),
-					shadow);
-      gimple_set_location (g, location);
-      gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-
-      g = gimple_build_assign_with_ops (BIT_AND_EXPR,
-					make_ssa_name (boolean_type_node,
-						       NULL),
-					t, gimple_assign_lhs (g));
-      gimple_set_location (g, location);
-      gsi_insert_after (&gsi, g, GSI_NEW_STMT);
-      t = gimple_assign_lhs (g);
+	t1 = gb.add (PLUS_EXPR, t1, size_in_bytes - 1);
+      t1 = gb.add (GE_EXPR, t1, shadow);
+      t = gb.add (BIT_AND_EXPR, t, t1);
+      gb.insert_after (&gsi, GSI_NEW_STMT);
     }
   else
     t = shadow;
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 785c2f0..c4687df 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -4210,4 +4210,115 @@ gimple_asm_clobbers_memory_p (const_gimple stmt)
 
   return false;
 }
+
+
+/* Return the expression type to use based on the CODE and type of
+   the given operand OP.  If the expression CODE is a comparison,
+   the returned type is boolean_type_node.  Otherwise, it returns
+   the type of OP.  */
+
+tree
+gimple_builder_base::get_expr_type (enum tree_code code, tree op)
+{
+  return (TREE_CODE_CLASS (code) == tcc_comparison)
+	 ? boolean_type_node
+	 : TREE_TYPE (op);
+}
+
+
+/* Add a new assignment to this GIMPLE sequence.  The assignment has
+   the form: GIMPLE_ASSIGN <CODE, LHS, OP1, OP2>. Returns LHS.  */
+
+tree
+gimple_builder_base::add (enum tree_code code, tree lhs, tree op1, tree op2)
+{
+  gimple s = gimple_build_assign_with_ops (code, lhs, op1, op2);
+  gimple_seq_add_stmt (&seq_, s);
+  return lhs;
+}
+
+
+/* Add a new assignment to this GIMPLE sequence.  The new assignment will
+   have the opcode CODE and operands OP1 and OP2.  The type of the
+   expression on the RHS is inferred to be the type of OP1.
+
+   The LHS of the statement will be an SSA name or a GIMPLE temporary
+   in normal form depending on the type of builder invoking this
+   function.  */
+
+tree
+gimple_builder_base::add (enum tree_code code, tree op1, tree op2)
+{
+  tree lhs = create_lhs_for_assignment (get_expr_type (code, op1));
+  return add (code, lhs, op1, op2);
+}
+
+
+/* Add a new assignment to this GIMPLE sequence.  The new
+   assignment will have the opcode CODE and operands OP1 and VAL.
+   VAL is converted into a an INTEGER_CST of the same type as OP1.
+
+   The LHS of the statement will be an SSA name or a GIMPLE temporary
+   in normal form depending on the type of builder invoking this
+   function.  */
+
+tree
+gimple_builder_base::add (enum tree_code code, tree op1, int val)
+{
+  tree type = get_expr_type (code, op1);
+  tree op2 = build_int_cst (TREE_TYPE (op1), val);
+  tree lhs = create_lhs_for_assignment (type);
+  return add (code, lhs, op1, op2);
+}
+
+
+/* Add a type cast assignment to this GIMPLE sequence. This creates a NOP_EXPR
+   that converts OP to TO_TYPE.  Return the LHS of the generated assignment.  */
+
+tree
+gimple_builder_base::add_type_cast (tree to_type, tree op)
+{
+  tree lhs = create_lhs_for_assignment (to_type);
+  return add (NOP_EXPR, lhs, op, NULL_TREE);
+}
+
+
+/* Insert this sequence after the statement pointed-to by iterator I.
+   MODE is an is gs_insert_after.  Scan the statements in SEQ for new
+   operands.  */
+
+void
+gimple_builder_base::insert_after (gimple_stmt_iterator *i,
+				   enum gsi_iterator_update mode)
+{
+  /* Since we are inserting a sequence, the semantics for GSI_NEW_STMT
+     are not quite what the caller is expecting.  GSI_NEW_STMT will
+     leave the iterator pointing to the *first* statement of this
+     sequence.  Rather, we want the iterator to point to the *last*
+     statement in the sequence.  Therefore, we use
+     GSI_CONTINUE_LINKING when GSI_NEW_STMT is requested.  */
+  if (mode == GSI_NEW_STMT)
+    mode = GSI_CONTINUE_LINKING;
+  gsi_insert_seq_after (i, seq_, mode);
+}
+
+
+/* Create a GIMPLE temporary type TYPE to be used as the LHS of an
+   assignment.  */
+
+tree
+gimple_builder_normal::create_lhs_for_assignment (tree type)
+{
+  return create_tmp_var (type, NULL);
+}
+
+
+/* Create an SSA name of type TYPE to be used as the LHS of an assignment.  */
+
+tree
+gimple_builder_ssa::create_lhs_for_assignment (tree type)
+{
+  return make_ssa_name (type, NULL);
+}
+
 #include "gt-gimple.h"
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 204c3c9..7b5e741 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -5393,4 +5393,57 @@ extern tree maybe_fold_or_comparisons (enum tree_code, tree, tree,
 				       enum tree_code, tree, tree);
 
 bool gimple_val_nonnegative_real_p (tree);
+
+
+/* GIMPLE builder class.  This type provides a simplified interface
+   for generating new GIMPLE statements.  */
+
+class gimple_builder_base
+{
+public:
+  tree add (enum tree_code, tree, tree);
+  tree add (enum tree_code, tree, int);
+  tree add (enum tree_code, tree, tree, tree);
+  tree add_type_cast (tree, tree);
+  void insert_after (gimple_stmt_iterator *, enum gsi_iterator_update);
+
+protected:
+  gimple_builder_base() : seq_(NULL), loc_(UNKNOWN_LOCATION) {}
+  gimple_builder_base(location_t l) : seq_(NULL), loc_(l) {}
+  tree get_expr_type (enum tree_code code, tree op);
+  virtual tree create_lhs_for_assignment (tree) = 0;
+
+private:
+  gimple_seq seq_;
+  location_t loc_;
+};
+
+
+/* GIMPLE builder class for statements in normal form.  Statements generated
+   by instances of this class will produce non-SSA temporaries.  */
+
+class gimple_builder_normal : public gimple_builder_base
+{
+public:
+  gimple_builder_normal() : gimple_builder_base() {}
+  gimple_builder_normal(location_t l) : gimple_builder_base(l) {}
+
+protected:
+  virtual tree create_lhs_for_assignment (tree);
+};
+
+
+/* GIMPLE builder class for statements in normal form.  Statements generated
+   by instances of this class will produce SSA names.  */
+
+class gimple_builder_ssa : public gimple_builder_base
+{
+public:
+  gimple_builder_ssa() : gimple_builder_base() {}
+  gimple_builder_ssa(location_t l) : gimple_builder_base(l) {}
+
+protected:
+  virtual tree create_lhs_for_assignment (tree);
+};
+
 #endif  /* GCC_GIMPLE_H */
