--- gcc/tree-call-cdce.cc.jj	2023-01-02 09:32:45.940944935 +0100
+++ gcc/tree-call-cdce.cc	2023-03-30 14:54:25.248544702 +0200
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.
 #include "builtins.h"
 #include "internal-fn.h"
 #include "tree-dfa.h"
+#include "gimple-range.h"
 
 
 /* This pass serves two closely-related purposes:
@@ -425,12 +426,9 @@ comparison_code_if_no_nans (tree_code co
    null tree.  */
 
 static void
-gen_one_condition (tree arg, int lbub,
-                   enum tree_code tcode,
-                   const char *temp_name1,
-		   const char *temp_name2,
-		   vec<gimple *> conds,
-                   unsigned *nconds)
+gen_one_condition (tree arg, int lbub, enum tree_code tcode,
+		   const char *temp_name1, const char *temp_name2,
+		   vec<gimple *> conds, unsigned *nconds, gimple *stmt)
 {
   if (!HONOR_NANS (arg))
     tcode = comparison_code_if_no_nans (tcode);
@@ -451,10 +449,24 @@ gen_one_condition (tree arg, int lbub,
   gimple_assign_set_lhs (stmt1, tempn);
 
   tempc = create_tmp_var (boolean_type_node, temp_name2);
-  stmt2 = gimple_build_assign (tempc,
-                               fold_build2 (tcode,
-					    boolean_type_node,
-					    tempn, lbub_real_cst));
+  tree tcond = build2 (tcode, boolean_type_node, arg, lbub_real_cst);
+  int_range_max r;
+  range_query *q = get_range_query (cfun);
+  if (q == get_global_range_query ())
+    q = enable_ranger (cfun);
+  /* Ask the ranger whether it knows the condition will be always false or
+     always true.  */
+  if (!q->range_of_expr (r, tcond, stmt) || r.undefined_p ())
+    tcond = NULL_TREE;
+  else if (r.upper_bound () == 0)
+    tcond = boolean_false_node;
+  else if (r.lower_bound () == 1)
+    tcond = boolean_true_node;
+  else
+    tcond = NULL_TREE;
+  if (!tcond)
+    tcond = fold_build2 (tcode, boolean_type_node, tempn, lbub_real_cst);
+  stmt2 = gimple_build_assign (tempc, tcond);
   tempcn = make_ssa_name (tempc, stmt2);
   gimple_assign_set_lhs (stmt2, tempcn);
 
@@ -475,16 +487,15 @@ gen_one_condition (tree arg, int lbub,
    for lower bound check, one for upper bound check.  */
 
 static void
-gen_conditions_for_domain (tree arg, inp_domain domain,
-			   vec<gimple *> conds,
-                           unsigned *nconds)
+gen_conditions_for_domain (tree arg, inp_domain domain, vec<gimple *> conds,
+			   unsigned *nconds, gimple *stmt)
 {
   if (domain.has_lb)
     gen_one_condition (arg, domain.lb,
                        (domain.is_lb_inclusive
                         ? UNGE_EXPR : UNGT_EXPR),
                        "DCE_COND_LB", "DCE_COND_LB_TEST",
-                       conds, nconds);
+		       conds, nconds, stmt);
 
   if (domain.has_ub)
     {
@@ -496,7 +507,7 @@ gen_conditions_for_domain (tree arg, inp
                          (domain.is_ub_inclusive
                           ? UNLE_EXPR : UNLT_EXPR),
                          "DCE_COND_UB", "DCE_COND_UB_TEST",
-                         conds, nconds);
+			 conds, nconds, stmt);
     }
 }
 
@@ -518,9 +529,8 @@ gen_conditions_for_domain (tree arg, inp
    and *NCONDS is the number of logical conditions.  */
 
 static void
-gen_conditions_for_pow_cst_base (tree base, tree expn,
-				 vec<gimple *> conds,
-                                 unsigned *nconds)
+gen_conditions_for_pow_cst_base (tree base, tree expn, vec<gimple *> conds,
+				 unsigned *nconds, gimple *stmt)
 {
   inp_domain exp_domain;
   /* Validate the range of the base constant to make
@@ -532,11 +542,9 @@ gen_conditions_for_pow_cst_base (tree ba
   real_from_integer (&mv, TYPE_MODE (TREE_TYPE (base)), 256, UNSIGNED);
   gcc_assert (!real_less (&mv, &bcv));
 
-  exp_domain = get_domain (0, false, false,
-                           127, true, false);
+  exp_domain = get_domain (0, false, false, 127, true, false);
 
-  gen_conditions_for_domain (expn, exp_domain,
-                             conds, nconds);
+  gen_conditions_for_domain (expn, exp_domain, conds, nconds, stmt);
 }
 
 /* Generate error condition code for pow calls with
@@ -554,9 +562,8 @@ gen_conditions_for_pow_cst_base (tree ba
    conditions.  */
 
 static void
-gen_conditions_for_pow_int_base (tree base, tree expn,
-				 vec<gimple *> conds,
-                                 unsigned *nconds)
+gen_conditions_for_pow_int_base (tree base, tree expn, vec<gimple *> conds,
+				 unsigned *nconds, gimple *stmt)
 {
   gimple *base_def;
   tree base_val0;
@@ -600,11 +607,9 @@ gen_conditions_for_pow_int_base (tree ba
   /* Generate condition in reverse order -- first
      the condition for the exp argument.  */
 
-  exp_domain = get_domain (0, false, false,
-                           max_exp, true, true);
+  exp_domain = get_domain (0, false, false, max_exp, true, true);
 
-  gen_conditions_for_domain (expn, exp_domain,
-                             conds, nconds);
+  gen_conditions_for_domain (expn, exp_domain, conds, nconds, stmt);
 
   /* Now generate condition for the base argument.
      Note it does not use the helper function
@@ -660,9 +665,9 @@ gen_conditions_for_pow (gcall *pow_call,
   bc = TREE_CODE (base);
 
   if (bc == REAL_CST)
-    gen_conditions_for_pow_cst_base (base, expn, conds, nconds);
+    gen_conditions_for_pow_cst_base (base, expn, conds, nconds, pow_call);
   else if (bc == SSA_NAME)
-    gen_conditions_for_pow_int_base (base, expn, conds, nconds);
+    gen_conditions_for_pow_int_base (base, expn, conds, nconds, pow_call);
   else
     gcc_unreachable ();
 }
@@ -852,7 +857,7 @@ gen_shrink_wrap_conditions (gcall *bi_ca
       inp_domain domain = get_no_error_domain (fnc);
       *nconds = 0;
       arg = gimple_call_arg (bi_call, 0);
-      gen_conditions_for_domain (arg, domain, conds, nconds);
+      gen_conditions_for_domain (arg, domain, conds, nconds, bi_call);
     }
 
   return;
@@ -1290,6 +1295,8 @@ pass_call_cdce::execute (function *fun)
     return 0;
 
   shrink_wrap_conditional_dead_built_in_calls (cond_dead_built_in_calls);
+  if (get_range_query (fun) != get_global_range_query ())
+    disable_ranger (fun);
   free_dominance_info (CDI_POST_DOMINATORS);
   /* As we introduced new control-flow we need to insert PHI-nodes
      for the call-clobbers of the remaining call.  */
--- gcc/testsuite/gcc.target/i386/pr103559-1.c.jj	2023-03-30 16:28:30.040980530 +0200
+++ gcc/testsuite/gcc.target/i386/pr103559-1.c	2023-03-30 16:29:33.866047038 +0200
@@ -0,0 +1,13 @@
+/* PR tree-optimization/103559 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump " = .SQRT \\\(" "optimized" } } */
+/* { dg-final { scan-tree-dump " = sqrtf \\\(" "optimized" } } */
+
+float sqrtf (float);
+
+float
+foo (float x)
+{
+  return sqrtf (x);
+}
--- gcc/testsuite/gcc.target/i386/pr103559-2.c.jj	2023-03-30 16:28:33.211934155 +0200
+++ gcc/testsuite/gcc.target/i386/pr103559-2.c	2023-03-30 16:29:44.855886307 +0200
@@ -0,0 +1,15 @@
+/* PR tree-optimization/103559 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump " = .SQRT \\\(" "optimized" } } */
+/* { dg-final { scan-tree-dump-not " = sqrtf \\\(" "optimized" } } */
+
+float sqrtf (float);
+
+float
+foo (float x)
+{
+  if (__builtin_isless (x, 0))
+    __builtin_unreachable ();
+  return sqrtf (x);
+}
--- gcc/testsuite/gcc.target/i386/pr103559-3.c.jj	2023-03-30 16:28:36.318888712 +0200
+++ gcc/testsuite/gcc.target/i386/pr103559-3.c	2023-03-30 16:29:51.977782145 +0200
@@ -0,0 +1,15 @@
+/* PR tree-optimization/103559 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not " = .SQRT \\\(" "optimized" } } */
+/* { dg-final { scan-tree-dump " = sqrtf \\\(" "optimized" } } */
+
+float sqrtf (float);
+
+float
+foo (float x)
+{
+  if (!__builtin_isless (x, 0))
+    __builtin_unreachable ();
+  return sqrtf (x);
+}
--- gcc/testsuite/gcc.target/i386/pr103559-4.c.jj	2023-03-30 16:28:39.710839098 +0200
+++ gcc/testsuite/gcc.target/i386/pr103559-4.c	2023-03-30 16:29:57.564700431 +0200
@@ -0,0 +1,13 @@
+/* PR tree-optimization/103559 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not " = sqrtf \\\(" "optimized" } } */
+
+float sqrtf (float);
+
+float
+foo (float x)
+{
+  x = x * x;
+  return sqrtf (x);
+}
