diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 66dfd25ad21379042a2a40c9993844757058a6b0..f680292fd91d2dae84b8ddb270a0ed0afabd363d 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -13859,10 +13859,10 @@ goa_lhs_expr_p (tree expr, tree addr)
 
 static int
 goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
-		    tree lhs_var, tree &target_expr, bool rhs)
+		    tree lhs_var, tree &target_expr, bool rhs, int depth)
 {
   tree expr = *expr_p;
-  int saw_lhs;
+  int saw_lhs = 0;
 
   if (goa_lhs_expr_p (expr, lhs_addr))
     {
@@ -13873,17 +13873,22 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
   if (is_gimple_val (expr))
     return 0;
 
-  saw_lhs = 0;
+  /* Maximum depth of lhs in expression is for the
+     __builtin_clear_padding (...), __builtin_clear_padding (...),
+     __builtin_memcmp (&TARGET_EXPR <lhs, >, ...) == 0 ? ... : lhs;  */
+  if (++depth > 7)
+    goto finish;
+
   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
     {
     case tcc_binary:
     case tcc_comparison:
       saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, lhs_addr,
-				     lhs_var, target_expr, true);
+				     lhs_var, target_expr, true, depth);
       /* FALLTHRU */
     case tcc_unary:
       saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, lhs_addr,
-				     lhs_var, target_expr, true);
+				     lhs_var, target_expr, true, depth);
       break;
     case tcc_expression:
       switch (TREE_CODE (expr))
@@ -13895,84 +13900,101 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
 	case TRUTH_XOR_EXPR:
 	case BIT_INSERT_EXPR:
 	  saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
-					 lhs_addr, lhs_var, target_expr, true);
+					 lhs_addr, lhs_var, target_expr, true,
+					 depth);
 	  /* FALLTHRU */
 	case TRUTH_NOT_EXPR:
 	  saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
-					 lhs_addr, lhs_var, target_expr, true);
+					 lhs_addr, lhs_var, target_expr, true,
+					 depth);
 	  break;
 	case MODIFY_EXPR:
+	  if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr, lhs_var,
+					    target_expr, true, depth))
+	    break;
 	  saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
-					 lhs_addr, lhs_var, target_expr, true);
+					 lhs_addr, lhs_var, target_expr, true,
+					 depth);
+	  saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
+					 lhs_addr, lhs_var, target_expr, false,
+					 depth);
+	  break;
 	  /* FALLTHRU */
 	case ADDR_EXPR:
+	  if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr, lhs_var,
+					    target_expr, true, depth))
+	    break;
 	  saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
-					 lhs_addr, lhs_var, target_expr, false);
+					 lhs_addr, lhs_var, target_expr, false,
+					 depth);
 	  break;
 	case COMPOUND_EXPR:
-	  /* Special-case __builtin_clear_padding call before
-	     __builtin_memcmp.  */
-	  if (TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR)
-	    {
-	      tree fndecl = get_callee_fndecl (TREE_OPERAND (expr, 0));
-	      if (fndecl
-		  && fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING)
-		  && VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0))))
+	  /* Break out any preevaluations from cp_build_modify_expr.  */
+	  for (; TREE_CODE (expr) == COMPOUND_EXPR;
+	       expr = TREE_OPERAND (expr, 1))
+	    {
+	      /* Special-case __builtin_clear_padding call before
+		 __builtin_memcmp.  */
+	      if (TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR)
 		{
-		  saw_lhs = goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
-						lhs_addr, lhs_var,
-						target_expr, true);
-		  if (!saw_lhs)
-		    {
-		      expr = TREE_OPERAND (expr, 1);
-		      if (!pre_p)
-			return goa_stabilize_expr (&expr, pre_p, lhs_addr,
-						   lhs_var, target_expr, true);
-		      *expr_p = expr;
-		      return goa_stabilize_expr (expr_p, pre_p, lhs_addr,
-						 lhs_var, target_expr, true);
-		    }
-		  else
+		  tree fndecl = get_callee_fndecl (TREE_OPERAND (expr, 0));
+		  if (fndecl
+		      && fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING)
+		      && VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0)))
+		      && (!pre_p
+			  || goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL,
+						 lhs_addr, lhs_var,
+						 target_expr, true, depth)))
 		    {
+		      if (pre_p)
+			*expr_p = expr;
+		      saw_lhs = goa_stabilize_expr (&TREE_OPERAND (expr, 0),
+						    pre_p, lhs_addr, lhs_var,
+						    target_expr, true, depth);
 		      saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1),
 						     pre_p, lhs_addr, lhs_var,
-						     target_expr, rhs);
-		      break;
+						     target_expr, rhs, depth);
+		      return saw_lhs;
 		    }
 		}
+
+	      if (pre_p)
+		gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p);
 	    }
-	  /* Break out any preevaluations from cp_build_modify_expr.  */
-	  for (; TREE_CODE (expr) == COMPOUND_EXPR;
-	       expr = TREE_OPERAND (expr, 1))
-	    if (pre_p)
-	      gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p);
 	  if (!pre_p)
 	    return goa_stabilize_expr (&expr, pre_p, lhs_addr, lhs_var,
-				       target_expr, rhs);
+				       target_expr, rhs, depth);
 	  *expr_p = expr;
 	  return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var,
-				     target_expr, rhs);
+				     target_expr, rhs, depth);
 	case COND_EXPR:
 	  if (!goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL, lhs_addr,
-				   lhs_var, target_expr, true))
+				   lhs_var, target_expr, true, depth))
 	    break;
 	  saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
-					 lhs_addr, lhs_var, target_expr, true);
+					 lhs_addr, lhs_var, target_expr, true,
+					 depth);
 	  saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
-					 lhs_addr, lhs_var, target_expr, true);
+					 lhs_addr, lhs_var, target_expr, true,
+					 depth);
 	  saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 2), pre_p,
-					 lhs_addr, lhs_var, target_expr, true);
+					 lhs_addr, lhs_var, target_expr, true,
+					 depth);
 	  break;
 	case TARGET_EXPR:
 	  if (TARGET_EXPR_INITIAL (expr))
 	    {
+	      if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr,
+						lhs_var, target_expr, true,
+						depth))
+		break;
 	      if (expr == target_expr)
 		saw_lhs = 1;
 	      else
 		{
 		  saw_lhs = goa_stabilize_expr (&TARGET_EXPR_INITIAL (expr),
 						pre_p, lhs_addr, lhs_var,
-						target_expr, true);
+						target_expr, true, depth);
 		  if (saw_lhs && target_expr == NULL_TREE && pre_p)
 		    target_expr = expr;
 		}
@@ -13986,7 +14008,8 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
       if (TREE_CODE (expr) == BIT_FIELD_REF
 	  || TREE_CODE (expr) == VIEW_CONVERT_EXPR)
 	saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
-				       lhs_addr, lhs_var, target_expr, true);
+				       lhs_addr, lhs_var, target_expr, true,
+				       depth);
       break;
     case tcc_vl_exp:
       if (TREE_CODE (expr) == CALL_EXPR)
@@ -13999,24 +14022,24 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
 		for (int i = 0; i < nargs; i++)
 		  saw_lhs |= goa_stabilize_expr (&CALL_EXPR_ARG (expr, i),
 						 pre_p, lhs_addr, lhs_var,
-						 target_expr, true);
+						 target_expr, true, depth);
 	      }
-	  if (saw_lhs == 0 && VOID_TYPE_P (TREE_TYPE (expr)))
-	    {
-	      if (pre_p)
-		gimplify_stmt (&expr, pre_p);
-	      return 0;
-	    }
 	}
       break;
     default:
       break;
     }
 
+ finish:
   if (saw_lhs == 0 && pre_p)
     {
       enum gimplify_status gs;
-      if (rhs)
+      if (TREE_CODE (expr) == CALL_EXPR && VOID_TYPE_P (TREE_TYPE (expr)))
+	{
+	  gimplify_stmt (&expr, pre_p);
+	  return saw_lhs;
+	}
+      else if (rhs)
 	gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_val, fb_rvalue);
       else
 	gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_lvalue, fb_lvalue);
@@ -14044,7 +14067,7 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
   tmp_load = create_tmp_reg (type);
   if (rhs
       && goa_stabilize_expr (&rhs, pre_p, addr, tmp_load, target_expr,
-			     true) < 0)
+			     true, 0) < 0)
     return GS_ERROR;
 
   if (gimplify_expr (&addr, pre_p, NULL, is_gimple_val, fb_rvalue)