diff --git a/gcc/combine.cc b/gcc/combine.cc
index 53dcac92abc..dede573982a 100644
--- a/gcc/combine.cc
+++ b/gcc/combine.cc
@@ -2569,6 +2569,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
   rtx new_other_notes;
   int i;
   scalar_int_mode dest_mode, temp_mode;
+  bool nce_any_eh_region_note = false;
 
   /* Immediately return if any of I0,I1,I2 are the same insn (I3 can
      never be).  */
@@ -2951,6 +2952,32 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
       return 0;
     }
 
+  /* With non-call exceptions we can end up trying to combine multiple
+     stmts with possible EH side effects.  Make sure we can combine
+     that to a single stmt which means there must be at most one insn
+     in the combination with an EH side effect.  */
+  if (cfun->can_throw_non_call_exceptions)
+    {
+      if (find_reg_note (i3, REG_EH_REGION, NULL_RTX)
+	  || find_reg_note (i2, REG_EH_REGION, NULL_RTX)
+	  || (i1 && find_reg_note (i1, REG_EH_REGION, NULL_RTX))
+	  || (i0 && find_reg_note (i0, REG_EH_REGION, NULL_RTX)))
+	{
+	  nce_any_eh_region_note = true;
+	  if (insn_could_throw_p (i3)
+	      + insn_could_throw_p (i2)
+	      + (i1 ? insn_could_throw_p (i1) : 0)
+	      + (i0 ? insn_could_throw_p (i0) : 0) > 1)
+	    {
+	      if (dump_file && (dump_flags & TDF_DETAILS))
+		fprintf (dump_file, "Can't combine multiple insns with EH "
+			 "side-effects\n");
+	      undo_all ();
+	      return 0;
+	    }
+	}
+    }
+
   /* Record whether i2 and i3 are trivial moves.  */
   i2_was_move = is_just_move (i2);
   i3_was_move = is_just_move (i3);
@@ -3685,7 +3712,13 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
 	      || !modified_between_p (*split, i2, i3))
 	  /* We can't overwrite I2DEST if its value is still used by
 	     NEWPAT.  */
-	  && ! reg_referenced_p (i2dest, newpat))
+	  && ! reg_referenced_p (i2dest, newpat)
+	  /* We should not split a possibly trapping part when we
+	     care about non-call EH and have REG_EH_REGION notes
+	     to distribute.  */
+	  && (!cfun->can_throw_non_call_exceptions
+	      || !nce_any_eh_region_note
+	      || !may_trap_p (*split)))
 	{
 	  rtx newdest = i2dest;
 	  enum rtx_code split_code = GET_CODE (*split);
@@ -14175,23 +14208,35 @@ distribute_notes (rtx notes, rtx_insn *from_insn, rtx_insn *i3, rtx_insn *i2,
 	  break;
 
 	case REG_EH_REGION:
-	  /* These notes must remain with the call or trapping instruction.  */
-	  if (CALL_P (i3))
-	    place = i3;
-	  else if (i2 && CALL_P (i2))
-	    place = i2;
-	  else
-	    {
-	      gcc_assert (cfun->can_throw_non_call_exceptions);
-	      if (may_trap_p (i3))
-		place = i3;
-	      else if (i2 && may_trap_p (i2))
-		place = i2;
-	      /* ??? Otherwise assume we've combined things such that we
-		 can now prove that the instructions can't trap.  Drop the
-		 note in this case.  */
-	    }
-	  break;
+	  {
+	    /* This handling needs to be kept in sync with the
+	       prerequisite checking in try_combine.  */
+	    int lp_nr = INTVAL (XEXP (note, 0));
+	    /* A REG_EH_REGION note transfering control can only ever come
+	       from i3.  */
+	    if (lp_nr > 0)
+	      gcc_assert (from_insn == i3);
+	    /* We are making sure there is a single effective REG_EH_REGION
+	       note and it's valid to put it on i3.  */
+	    if (!insn_could_throw_p (from_insn))
+	      /* Deal with stray notes on insns that can never throw.  */
+	      ;
+	    else
+	      {
+		if (CALL_P (i3))
+		  place = i3;
+		else
+		  {
+		    gcc_assert (cfun->can_throw_non_call_exceptions);
+		    /* If i3 can still trap preserve the note, otherwise we've
+		       combined things such that we can now prove that the
+		       instructions can't trap.  Drop the note in this case.  */
+		    if (may_trap_p (i3))
+		      place = i3;
+		  }
+	      }
+	    break;
+	  }
 
 	case REG_ARGS_SIZE:
 	  /* ??? How to distribute between i3-i1.  Assume i3 contains the
diff --git a/gcc/testsuite/gcc.dg/torture/pr105231.c b/gcc/testsuite/gcc.dg/torture/pr105231.c
new file mode 100644
index 00000000000..50459219c08
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr105231.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target int32plus } */
+/* { dg-require-effective-target dfp } */
+/* { dg-additional-options "-fsanitize-coverage=trace-pc -fnon-call-exceptions --param=max-cse-insns=1 -frounding-math" } */
+/* { dg-additional-options "-mstack-arg-probe" { target x86_64-*-* i?86-*-* } } */
+
+void baz (int *);
+void bar (double, double, _Decimal64);
+
+void
+foo (void)
+{
+  int s __attribute__((cleanup (baz)));
+  bar (0xfffffffffffffffe, 0xebf3fff2fbebaf7f, 0xffffffffffffff);
+}
