diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
index 93ac6562b22..86f94152a96 100644
--- a/gcc/config/xtensa/xtensa.cc
+++ b/gcc/config/xtensa/xtensa.cc
@@ -102,6 +102,7 @@ struct GTY(()) machine_function
   int callee_save_size;
   bool frame_laid_out;
   bool epilogue_done;
+  bool inhibit_logues_a1_adjusts;
 };
 
 /* Vector, indexed by hard register number, which contains 1 for a
@@ -3048,7 +3049,7 @@ xtensa_output_literal (FILE *file, rtx x, machine_mode mode, int labelno)
 }
 
 static bool
-xtensa_call_save_reg(int regno)
+xtensa_call_save_reg (int regno)
 {
   if (TARGET_WINDOWED_ABI)
     return false;
@@ -3084,7 +3085,7 @@ compute_frame_size (poly_int64 size)
   cfun->machine->callee_save_size = 0;
   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
     {
-      if (xtensa_call_save_reg(regno))
+      if (xtensa_call_save_reg (regno))
 	cfun->machine->callee_save_size += UNITS_PER_WORD;
     }
 
@@ -3139,6 +3140,49 @@ xtensa_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED)
   return offset;
 }
 
+#define ADJUST_SP_NONE      0x0
+#define ADJUST_SP_NEED_NOTE 0x1
+#define ADJUST_SP_FRAME_PTR 0x2
+static void
+xtensa_emit_adjust_stack_ptr (HOST_WIDE_INT offset, int flags)
+{
+  rtx_insn *insn;
+  rtx ptr = (flags & ADJUST_SP_FRAME_PTR) ? hard_frame_pointer_rtx
+					  : stack_pointer_rtx;
+
+  if (cfun->machine->inhibit_logues_a1_adjusts)
+    return;
+
+  if (xtensa_simm8 (offset)
+      || xtensa_simm8x256 (offset))
+    insn = emit_insn (gen_addsi3 (stack_pointer_rtx, ptr, GEN_INT (offset)));
+  else
+    {
+      rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
+
+      if (offset < 0)
+	{
+	  emit_move_insn (tmp_reg, GEN_INT (-offset));
+	  insn = emit_insn (gen_subsi3 (stack_pointer_rtx, ptr, tmp_reg));
+	}
+      else
+	{
+	  emit_move_insn (tmp_reg, GEN_INT (offset));
+	  insn = emit_insn (gen_addsi3 (stack_pointer_rtx, ptr,	tmp_reg));
+	}
+    }
+
+  if (flags & ADJUST_SP_NEED_NOTE)
+    {
+      rtx note_rtx = gen_rtx_SET (stack_pointer_rtx,
+				  plus_constant (Pmode, stack_pointer_rtx,
+						 offset));
+
+      RTX_FRAME_RELATED_P (insn) = 1;
+      add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
+    }
+}
+
 /* minimum frame = reg save area (4 words) plus static chain (1 word)
    and the total number of words must be a multiple of 128 bits.  */
 #define MIN_FRAME_SIZE (8 * UNITS_PER_WORD)
@@ -3174,17 +3218,28 @@ xtensa_expand_prologue (void)
       int regno;
       HOST_WIDE_INT offset = 0;
       int callee_save_size = cfun->machine->callee_save_size;
+      df_ref ref;
+      bool stack_pointer_really_used = false;
+
+      /* Check if the function body really needs the stack pointer.  */
+      for (ref = DF_REG_USE_CHAIN (A1_REG);
+	   ref; ref = DF_REF_NEXT_REG (ref))
+	if (DF_REF_CLASS (ref) == DF_REF_REGULAR)
+	  stack_pointer_really_used = true;
+      /* Check if callee-saved registers really need saving to the stack.  */
+      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
+	if (xtensa_call_save_reg (regno))
+	  stack_pointer_really_used = true;
+
+      cfun->machine->inhibit_logues_a1_adjusts = ! (stack_pointer_really_used
+						    || frame_pointer_needed
+						    || crtl->calls_eh_return);
 
       /* -128 is a limit of single addi instruction. */
       if (IN_RANGE (total_size, 1, 128))
 	{
-	  insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-					GEN_INT (-total_size)));
-	  RTX_FRAME_RELATED_P (insn) = 1;
-	  note_rtx = gen_rtx_SET (stack_pointer_rtx,
-				  plus_constant (Pmode, stack_pointer_rtx,
-						 -total_size));
-	  add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
+	  xtensa_emit_adjust_stack_ptr (-total_size,
+					ADJUST_SP_NEED_NOTE);
 	  offset = total_size - UNITS_PER_WORD;
 	}
       else if (callee_save_size)
@@ -3194,33 +3249,14 @@ xtensa_expand_prologue (void)
 	   * move it to its final location. */
 	  if (total_size > 1024)
 	    {
-	      insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-					    GEN_INT (-callee_save_size)));
-	      RTX_FRAME_RELATED_P (insn) = 1;
-	      note_rtx = gen_rtx_SET (stack_pointer_rtx,
-				      plus_constant (Pmode, stack_pointer_rtx,
-						     -callee_save_size));
-	      add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
+	      xtensa_emit_adjust_stack_ptr (-callee_save_size,
+					    ADJUST_SP_NEED_NOTE);
 	      offset = callee_save_size - UNITS_PER_WORD;
 	    }
 	  else
 	    {
-	      if (xtensa_simm8x256 (-total_size))
-		insn = emit_insn (gen_addsi3 (stack_pointer_rtx,
-					      stack_pointer_rtx,
-					      GEN_INT (-total_size)));
-	      else
-		{
-		  rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
-		  emit_move_insn (tmp_reg, GEN_INT (total_size));
-		  insn = emit_insn (gen_subsi3 (stack_pointer_rtx,
-						stack_pointer_rtx, tmp_reg));
-		}
-	      RTX_FRAME_RELATED_P (insn) = 1;
-	      note_rtx = gen_rtx_SET (stack_pointer_rtx,
-				      plus_constant (Pmode, stack_pointer_rtx,
-						     -total_size));
-	      add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
+	      xtensa_emit_adjust_stack_ptr (-total_size,
+					    ADJUST_SP_NEED_NOTE);
 	      offset = total_size - UNITS_PER_WORD;
 	    }
 	}
@@ -3242,27 +3278,8 @@ xtensa_expand_prologue (void)
 	}
       if (total_size > 1024
 	  || (!callee_save_size && total_size > 128))
-	{
-	  if (xtensa_simm8x256 (callee_save_size - total_size))
-	    insn = emit_insn (gen_addsi3 (stack_pointer_rtx,
-					  stack_pointer_rtx,
-					  GEN_INT (callee_save_size -
-						   total_size)));
-	  else
-	    {
-	      rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
-	      emit_move_insn (tmp_reg, GEN_INT (total_size -
-						callee_save_size));
-	      insn = emit_insn (gen_subsi3 (stack_pointer_rtx,
-					    stack_pointer_rtx, tmp_reg));
-	    }
-	  RTX_FRAME_RELATED_P (insn) = 1;
-	  note_rtx = gen_rtx_SET (stack_pointer_rtx,
-				  plus_constant (Pmode, stack_pointer_rtx,
-						 callee_save_size -
-						 total_size));
-	  add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
-	}
+	xtensa_emit_adjust_stack_ptr (callee_save_size - total_size,
+				      ADJUST_SP_NEED_NOTE);
     }
 
   if (frame_pointer_needed)
@@ -3329,21 +3346,11 @@ xtensa_expand_epilogue (bool sibcall_p)
 
       if (cfun->machine->current_frame_size > (frame_pointer_needed ? 127 : 1024))
 	{
-	  if (xtensa_simm8x256 (cfun->machine->current_frame_size -
-				cfun->machine->callee_save_size))
-	    emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_needed ?
-				   hard_frame_pointer_rtx : stack_pointer_rtx,
-				   GEN_INT (cfun->machine->current_frame_size -
-					    cfun->machine->callee_save_size)));
-	  else
-	    {
-	      rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
-	      emit_move_insn (tmp_reg, GEN_INT (cfun->machine->current_frame_size -
-						cfun->machine->callee_save_size));
-	      emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_needed ?
-				     hard_frame_pointer_rtx : stack_pointer_rtx,
-				     tmp_reg));
-	    }
+	  xtensa_emit_adjust_stack_ptr (cfun->machine->current_frame_size -
+					cfun->machine->callee_save_size,
+					frame_pointer_needed
+					? ADJUST_SP_FRAME_PTR
+					: ADJUST_SP_NONE);
 	  offset = cfun->machine->callee_save_size - UNITS_PER_WORD;
 	}
       else
@@ -3384,24 +3391,11 @@ xtensa_expand_epilogue (bool sibcall_p)
 	      else
 		offset = cfun->machine->callee_save_size;
 	      if (offset)
-		emit_insn (gen_addsi3 (stack_pointer_rtx,
-				       stack_pointer_rtx,
-				       GEN_INT (offset)));
+		xtensa_emit_adjust_stack_ptr (offset, ADJUST_SP_NONE);
 	    }
 	  else
-	    {
-	      if (xtensa_simm8x256 (cfun->machine->current_frame_size))
-		emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-				       GEN_INT (cfun->machine->current_frame_size)));
-	      else
-		{
-		  rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
-		  emit_move_insn (tmp_reg,
-				  GEN_INT (cfun->machine->current_frame_size));
-		  emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
-					 tmp_reg));
-		}
-	    }
+	    xtensa_emit_adjust_stack_ptr (cfun->machine->current_frame_size,
+					  ADJUST_SP_NONE);
 	}
 
       if (crtl->calls_eh_return)
