diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
index f64326b944e..89e4dd069ac 100644
--- a/gcc/cfgloop.c
+++ b/gcc/cfgloop.c
@@ -355,6 +355,7 @@ alloc_loop (void)
   loop->nb_iterations_upper_bound = 0;
   loop->nb_iterations_likely_upper_bound = 0;
   loop->nb_iterations_estimate = 0;
+  loop->is_finite = false;
   return loop;
 }

diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index 2f8ab106d03..08ec930597e 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -224,6 +224,9 @@ struct GTY ((chain_next ("%h.next"))) loop {
   /* True if the loop is part of an oacc kernels region.  */
   unsigned in_oacc_kernels_region : 1;

+  /* True if middle end analysis ensure this loop is finite.  */
+  unsigned is_finite : 1;
+
   /* The number of times to unroll the loop.  0 means no information given,
      just do what we always do.  A value of 1 means do not unroll the loop.
      A value of USHRT_MAX means unroll with no specific unrolling factor.
diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c
index 50250ec4d7c..f1033d11865 100644
--- a/gcc/cfgloopmanip.c
+++ b/gcc/cfgloopmanip.c
@@ -1026,6 +1026,7 @@ copy_loop_info (struct loop *loop, struct loop *target)
   target->in_oacc_kernels_region = loop->in_oacc_kernels_region;
   target->unroll = loop->unroll;
   target->owned_clique = loop->owned_clique;
+  target->is_finite = loop->is_finite;
 }

 /* Copies copy of LOOP as subloop of TARGET loop, placing newly
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index bb561d00853..f7282adc5b1 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -1089,7 +1089,7 @@ end:
 	      struct loop *loop;
 	      scev_initialize ();
 	      FOR_EACH_LOOP (loop, 0)
-		if (!finite_loop_p (loop))
+		if (!test_and_update_loop_finite (loop))
 		  {
 		    if (dump_file)
 		      fprintf (dump_file, "    cannot prove finiteness of "
diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c
index 82b4bdb1523..a6bc82975cc 100644
--- a/gcc/loop-iv.c
+++ b/gcc/loop-iv.c
@@ -2997,6 +2997,19 @@ find_simple_exit (struct loop *loop, struct niter_desc *desc)
 	fprintf (dump_file, "Loop %d is not simple.\n", loop->num);
     }

+  /* Fix up the finiteness if possible.  We can only do it for single exit,
+     since the loop is finite, but it's possible that we predicate one loop
+     exit to be finite which can not be determined as finite in middle-end as
+     well.  It results in incorrect predicate information on the exit condition
+     expression.  For example, if says [(int) _1 + -8, + , -8] != 0 finite,
+     it means _1 can exactly divide -8.  */
+  if (single_exit (loop) && desc->infinite && loop->is_finite)
+    {
+      desc->infinite = NULL_RTX;
+      if (dump_file)
+	fprintf (dump_file, "  infinite updated to finite.\n");
+    }
+
   free (body);
 }

diff --git a/gcc/testsuite/gcc.target/powerpc/pr62147.c b/gcc/testsuite/gcc.target/powerpc/pr62147.c
new file mode 100644
index 00000000000..635c73711da
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr62147.c
@@ -0,0 +1,24 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns" } */
+
+/* Note that it's required to disable loop-distribute-patterns, otherwise the
+   loop will be optimized to memset.  */
+
+/* Expect loop_iv can know the loop is finite so the doloop_optimize
+   can perform the doloop transformation.  */
+
+typedef struct {
+  int l;
+  int b[258];
+} S;
+
+void clear (S* s )
+{
+  int i;
+  int len = s->l + 1;
+
+  for (i = 0; i <= len; i++)
+    s->b[i] = 0;
+}
+
+/* { dg-final { scan-assembler {\mbdnz\M} } } */
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index 2478219d873..7c183c7269a 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -417,7 +417,7 @@ find_obviously_necessary_stmts (bool aggressive)
 	  }

       FOR_EACH_LOOP (loop, 0)
-	if (!finite_loop_p (loop))
+	if (!test_and_update_loop_finite (loop))
 	  {
 	    if (dump_file)
 	      fprintf (dump_file, "cannot prove finiteness of loop %i\n", loop->num);
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 2064c2900fb..49b8577ccd1 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -2484,7 +2484,7 @@ fill_always_executed_in_1 (struct loop *loop, sbitmap contains_call)
 	      /* Or we enter a possibly non-finite loop.  */
 	      if (flow_loop_nested_p (bb->loop_father,
 				      e->dest->loop_father)
-		  && ! finite_loop_p (e->dest->loop_father))
+		  && ! test_and_update_loop_finite (e->dest->loop_father))
 		break;
 	    }
 	  if (e)
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 890f9b788b4..484a6626c05 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -612,6 +612,9 @@ struct ivopts_data

   /* Whether the loop body can only be exited via single exit.  */
   bool loop_single_exit_p;
+
+  /* Whether to compute loop finiteness for loop iv.  */
+  bool compute_loop_finite_p;
 };

 /* An assignment of iv candidates to uses.  */
@@ -7145,6 +7148,9 @@ rewrite_use_compare (struct ivopts_data *data,
       gimple_cond_set_lhs (cond_stmt, var);
       gimple_cond_set_code (cond_stmt, compare);
       gimple_cond_set_rhs (cond_stmt, op);
+
+      data->compute_loop_finite_p = true;
+
       return;
     }

@@ -7526,6 +7532,7 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop,
   data->current_loop = loop;
   data->loop_loc = find_loop_location (loop).get_location_t ();
   data->speed = optimize_loop_for_speed_p (loop);
+  data->compute_loop_finite_p = false;

   if (dump_file && (dump_flags & TDF_DETAILS))
     {
@@ -7592,6 +7599,10 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop,
   /* Remove the ivs that are unused after rewriting.  */
   remove_unused_ivs (data, toremove);

+  /* Update loop finiteness info.  */
+  if (data->compute_loop_finite_p)
+    test_and_update_loop_finite (data->current_loop);
+
 finish:
   free (body);
   free_loop_data (data);
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 84e6e313c85..78152714791 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -2808,10 +2808,14 @@ find_loop_niter (struct loop *loop, edge *exit)
 /* Return true if loop is known to have bounded number of iterations.  */

 bool
-finite_loop_p (struct loop *loop)
+test_and_update_loop_finite (struct loop *loop)
 {
   widest_int nit;
   int flags;
+  bool finite_p = false;
+
+  if (loop->is_finite)
+    return true;

   flags = flags_from_decl_or_type (current_function_decl);
   if ((flags & (ECF_CONST|ECF_PURE)) && !(flags & ECF_LOOPING_CONST_OR_PURE))
@@ -2819,7 +2823,8 @@ finite_loop_p (struct loop *loop)
       if (dump_file && (dump_flags & TDF_DETAILS))
 	fprintf (dump_file, "Found loop %i to be finite: it is within pure or const function.\n",
 		 loop->num);
-      return true;
+      finite_p = true;
+      goto finish;
     }

   if (loop->any_upper_bound
@@ -2828,9 +2833,14 @@ finite_loop_p (struct loop *loop)
       if (dump_file && (dump_flags & TDF_DETAILS))
 	fprintf (dump_file, "Found loop %i to be finite: upper bound found.\n",
 		 loop->num);
-      return true;
+      finite_p = true;
+      goto finish;
     }
-  return false;
+
+  finish:
+    if (finite_p)
+      loop->is_finite = true;
+  return finite_p;
 }

 /*
diff --git a/gcc/tree-ssa-loop-niter.h b/gcc/tree-ssa-loop-niter.h
index dc116489218..01d587f1cbb 100644
--- a/gcc/tree-ssa-loop-niter.h
+++ b/gcc/tree-ssa-loop-niter.h
@@ -30,7 +30,7 @@ extern bool number_of_iterations_exit_assumptions (struct loop *, edge,
 						   struct tree_niter_desc *,
 						   gcond **, bool = true);
 extern tree find_loop_niter (struct loop *, edge *);
-extern bool finite_loop_p (struct loop *);
+extern bool test_and_update_loop_finite (struct loop *);
 extern tree loop_niter_by_eval (struct loop *, edge);
 extern tree find_loop_niter_by_eval (struct loop *, edge *);
 extern bool estimated_loop_iterations (struct loop *, widest_int *);
