--- gcc/doc/invoke.texi.jj	2021-09-29 10:07:41.841880681 +0200
+++ gcc/doc/invoke.texi	2021-09-30 20:21:37.736147295 +0200
@@ -15229,7 +15229,7 @@ ISO C90 and C99, etc.
 
 @item -fsanitize=integer-divide-by-zero
 @opindex fsanitize=integer-divide-by-zero
-Detect integer division by zero as well as @code{INT_MIN / -1} division.
+Detect integer division by zero.
 
 @item -fsanitize=unreachable
 @opindex fsanitize=unreachable
@@ -15261,7 +15261,8 @@ returning a value.  This option works in
 @opindex fsanitize=signed-integer-overflow
 This option enables signed integer overflow checking.  We check that
 the result of @code{+}, @code{*}, and both unary and binary @code{-}
-does not overflow in the signed arithmetics.  Note, integer promotion
+does not overflow in the signed arithmetics.  This also detects
+@code{INT_MIN / -1} signed division.  Note, integer promotion
 rules must be taken into account.  That is, the following is not an
 overflow:
 @smallexample
--- gcc/c-family/c-ubsan.c.jj	2021-01-04 10:25:50.355103357 +0100
+++ gcc/c-family/c-ubsan.c	2021-09-30 20:18:53.273433013 +0200
@@ -39,8 +39,9 @@ along with GCC; see the file COPYING3.
 tree
 ubsan_instrument_division (location_t loc, tree op0, tree op1)
 {
-  tree t, tt;
+  tree t, tt, x = NULL_TREE;
   tree type = TREE_TYPE (op0);
+  enum sanitize_code flag = SANITIZE_DIVIDE;
 
   /* At this point both operands should have the same type,
      because they are already converted to RESULT_TYPE.
@@ -58,24 +59,42 @@ ubsan_instrument_division (location_t lo
 		     op1, build_int_cst (type, 0));
   else if (TREE_CODE (type) == REAL_TYPE
 	   && sanitize_flags_p (SANITIZE_FLOAT_DIVIDE))
-    t = fold_build2 (EQ_EXPR, boolean_type_node,
-		     op1, build_real (type, dconst0));
+    {
+      t = fold_build2 (EQ_EXPR, boolean_type_node,
+		       op1, build_real (type, dconst0));
+      flag = SANITIZE_FLOAT_DIVIDE;
+    }
   else
-    return NULL_TREE;
+    t = NULL_TREE;
 
   /* We check INT_MIN / -1 only for signed types.  */
   if (TREE_CODE (type) == INTEGER_TYPE
-      && sanitize_flags_p (SANITIZE_DIVIDE)
+      && sanitize_flags_p (SANITIZE_SI_OVERFLOW)
       && !TYPE_UNSIGNED (type))
     {
-      tree x;
       tt = fold_build2 (EQ_EXPR, boolean_type_node, unshare_expr (op1),
 			build_int_cst (type, -1));
       x = fold_build2 (EQ_EXPR, boolean_type_node, op0,
 		       TYPE_MIN_VALUE (type));
       x = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, x, tt);
-      t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, x);
+      if (t == NULL_TREE || integer_zerop (t))
+	{
+	  t = x;
+	  x = NULL_TREE;
+	  flag = SANITIZE_SI_OVERFLOW;
+	}
+      else if (flag_sanitize_undefined_trap_on_error
+	       || (((flag_sanitize_recover & SANITIZE_DIVIDE) == 0)
+		   == ((flag_sanitize_recover & SANITIZE_SI_OVERFLOW) == 0)))
+	{
+	  t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, x);
+	  x = NULL_TREE;
+	}
+      else if (integer_zerop (x))
+	x = NULL_TREE;
     }
+  else if (t == NULL_TREE)
+    return NULL_TREE;
 
   /* If the condition was folded to 0, no need to instrument
      this expression.  */
@@ -95,7 +114,7 @@ ubsan_instrument_division (location_t lo
 				     NULL_TREE);
       data = build_fold_addr_expr_loc (loc, data);
       enum built_in_function bcode
-	= (flag_sanitize_recover & SANITIZE_DIVIDE)
+	= (flag_sanitize_recover & flag)
 	  ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
 	  : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT;
       tt = builtin_decl_explicit (bcode);
@@ -103,8 +122,20 @@ ubsan_instrument_division (location_t lo
       op1 = unshare_expr (op1);
       tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
 				ubsan_encode_value (op1));
+      if (x)
+	{
+	  bcode = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
+		  ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
+		  : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT;
+	  tree xt = builtin_decl_explicit (bcode);
+	  op0 = unshare_expr (op0);
+	  op1 = unshare_expr (op1);
+	  xt = build_call_expr_loc (loc, xt, 3, data, ubsan_encode_value (op0),
+				    ubsan_encode_value (op1));
+	  x = fold_build3 (COND_EXPR, void_type_node, x, xt, void_node);
+	}
     }
-  t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
+  t = fold_build3 (COND_EXPR, void_type_node, t, tt, x ? x : void_node);
 
   return t;
 }
--- gcc/c/c-typeck.c.jj	2021-09-29 10:07:41.789881404 +0200
+++ gcc/c/c-typeck.c	2021-09-30 20:50:00.990465683 +0200
@@ -12733,7 +12733,9 @@ build_binary_op (location_t location, en
     }
 
   if (sanitize_flags_p ((SANITIZE_SHIFT
-			 | SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))
+			 | SANITIZE_DIVIDE
+			 | SANITIZE_FLOAT_DIVIDE
+			 | SANITIZE_SI_OVERFLOW))
       && current_function_decl != NULL_TREE
       && (doing_div_or_mod || doing_shift)
       && !require_constant_value)
@@ -12744,7 +12746,8 @@ build_binary_op (location_t location, en
       op0 = c_fully_fold (op0, false, NULL);
       op1 = c_fully_fold (op1, false, NULL);
       if (doing_div_or_mod && (sanitize_flags_p ((SANITIZE_DIVIDE
-						  | SANITIZE_FLOAT_DIVIDE))))
+						  | SANITIZE_FLOAT_DIVIDE
+						  | SANITIZE_SI_OVERFLOW))))
 	instrument_expr = ubsan_instrument_division (location, op0, op1);
       else if (doing_shift && sanitize_flags_p (SANITIZE_SHIFT))
 	instrument_expr = ubsan_instrument_shift (location, code, op0, op1);
--- gcc/cp/typeck.c.jj	2021-09-09 10:40:26.096175666 +0200
+++ gcc/cp/typeck.c	2021-09-30 20:50:23.806147945 +0200
@@ -6038,7 +6038,9 @@ cp_build_binary_op (const op_location_t
     }
 
   if (sanitize_flags_p ((SANITIZE_SHIFT
-			 | SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))
+			 | SANITIZE_DIVIDE
+			 | SANITIZE_FLOAT_DIVIDE
+			 | SANITIZE_SI_OVERFLOW))
       && current_function_decl != NULL_TREE
       && !processing_template_decl
       && (doing_div_or_mod || doing_shift))
@@ -6050,7 +6052,9 @@ cp_build_binary_op (const op_location_t
       op1 = fold_non_dependent_expr (op1, complain);
       tree instrument_expr1 = NULL_TREE;
       if (doing_div_or_mod
-	  && sanitize_flags_p (SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE))
+	  && sanitize_flags_p (SANITIZE_DIVIDE
+			       | SANITIZE_FLOAT_DIVIDE
+			       | SANITIZE_SI_OVERFLOW))
 	{
 	  /* For diagnostics we want to use the promoted types without
 	     shorten_binary_op.  So convert the arguments to the
--- gcc/testsuite/c-c++-common/ubsan/div-by-zero-3.c.jj	2020-01-12 11:54:37.029404115 +0100
+++ gcc/testsuite/c-c++-common/ubsan/div-by-zero-3.c	2021-09-30 20:51:00.522636616 +0200
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-overflow" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -Wno-overflow" } */
 
 #include <limits.h>
 
--- gcc/testsuite/c-c++-common/ubsan/div-by-zero-4.c.jj	2020-01-12 11:54:37.029404115 +0100
+++ gcc/testsuite/c-c++-common/ubsan/div-by-zero-4.c	2021-09-30 20:24:17.051933114 +0200
@@ -1,5 +1,5 @@
 /* { dg-do run } */
-/* { dg-options "-fsanitize=integer-divide-by-zero -Wno-overflow" } */
+/* { dg-options "-fsanitize=signed-integer-overflow -fsanitize-undefined-trap-on-error -Wno-overflow" } */
 
 #define INT_MIN (-__INT_MAX__ - 1)
 
--- gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c.jj	2020-01-12 11:54:37.029404115 +0100
+++ gcc/testsuite/c-c++-common/ubsan/div-by-zero-5.c	2021-09-30 20:24:55.559397933 +0200
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-fsanitize=integer-divide-by-zero" } */
+/* { dg-options "-fsanitize=signed-integer-overflow" } */
 
 void
 foo (void)
--- gcc/testsuite/c-c++-common/ubsan/float-div-by-zero-2.c.jj	2021-10-01 12:28:23.485086791 +0200
+++ gcc/testsuite/c-c++-common/ubsan/float-div-by-zero-2.c	2021-10-01 12:29:35.875062499 +0200
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-options "-fsanitize=float-divide-by-zero -fno-sanitize-recover=float-divide-by-zero -fsanitize-recover=integer-divide-by-zero" } */
+
+int
+main (void)
+{
+  volatile float a = 1.3f;
+  volatile double b = 0.0;
+  volatile int c = 4;
+  volatile float res;
+
+  res = a / b;
+
+  return 0;
+}
+
+/* { dg-output "division by zero" } */
--- gcc/testsuite/c-c++-common/ubsan/overflow-div-1.c.jj	2021-10-01 12:30:48.269038146 +0200
+++ gcc/testsuite/c-c++-common/ubsan/overflow-div-1.c	2021-10-01 12:31:49.532171295 +0200
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=integer-divide-by-zero -fno-sanitize-recover=undefined,float-divide-by-zero -Wno-overflow" } */
+
+#include <limits.h>
+
+int
+main (void)
+{
+  volatile int min = INT_MIN;
+  volatile int zero = 0;
+
+  INT_MIN / -1;
+  min / -1;
+  min / (10 * zero - (2 - 1));
+
+  return 0;
+}
--- gcc/testsuite/c-c++-common/ubsan/overflow-div-2.c.jj	2021-10-01 12:34:28.814917433 +0200
+++ gcc/testsuite/c-c++-common/ubsan/overflow-div-2.c	2021-10-01 12:50:24.398395074 +0200
@@ -0,0 +1,41 @@
+/* { dg-do run { target *-*-linux* *-*-gnu* } } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=integer-divide-by-zero" } */
+
+#include <limits.h>
+#include <signal.h>
+#include <stdlib.h>
+
+int cnt;
+
+__attribute__((noipa)) int
+foo (int x, int y)
+{
+  return x / y;
+}
+
+void
+handler (int i)
+{
+  if (cnt++ != 0)
+    exit (0);
+  volatile int b = foo (5, 0);
+  exit (0);
+}
+
+int
+main (void)
+{
+  struct sigaction s;
+  sigemptyset (&s.sa_mask);
+  s.sa_handler = handler;
+  s.sa_flags = 0;
+  sigaction (SIGFPE, &s, NULL);
+  volatile int a = foo (INT_MIN, -1);
+  cnt++;
+  volatile int b = foo (5, 0);
+  return 0;
+}
+
+/* { dg-output "division of -2147483648 by -1 cannot be represented in type 'int'\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*division by zero\[^\n\r]*" } */
--- gcc/testsuite/c-c++-common/ubsan/overflow-div-3.c.jj	2021-10-01 12:39:28.230680432 +0200
+++ gcc/testsuite/c-c++-common/ubsan/overflow-div-3.c	2021-10-01 12:50:58.652910346 +0200
@@ -0,0 +1,41 @@
+/* { dg-do run { target *-*-linux* *-*-gnu* } } */
+/* { dg-shouldfail "ubsan" } */
+/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=signed-integer-overflow" } */
+
+#include <limits.h>
+#include <signal.h>
+#include <stdlib.h>
+
+int cnt;
+
+__attribute__((noipa)) int
+foo (int x, int y)
+{
+  return x / y;
+}
+
+void
+handler (int i)
+{
+  if (cnt++ != 0)
+    exit (0);
+  volatile int b = foo (INT_MIN, -1);
+  exit (0);
+}
+
+int
+main (void)
+{
+  struct sigaction s;
+  sigemptyset (&s.sa_mask);
+  s.sa_handler = handler;
+  s.sa_flags = 0;
+  sigaction (SIGFPE, &s, NULL);
+  volatile int a = foo (42, 0);
+  cnt++;
+  volatile int b = foo (INT_MIN, -1);
+  return 0;
+}
+
+/* { dg-output "division by zero\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "\[^\n\r]*division of -2147483648 by -1 cannot be represented in type 'int'" } */
