diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr64705.c b/gcc/testsuite/gcc.dg/tree-ssa/pr64705.c
index fd24e38a53e9f3a4659dece5af4d71fbc0ce2c18..3c9c2e5deed1ba755d1fae15a6553d68b6ad0098 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr64705.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr64705.c
@@ -23,4 +23,4 @@ int foo(char *flags, long len, long i, long steps)
 
 /* Don't expand iv {base+step, step}_loop into {base+x+y, step}_loop
    even if "step == x + y".  */
-/* { dg-final { scan-tree-dump "Base:\\tstep_\[0-9\]* \\+ iter|Base:\\titer_\[0-9\]* \\+ step" "ivopts"} } */
+/* { dg-final { scan-tree-dump {Base:\t\(unsigned ?.*\) step_[0-9]* \+ \(unsigned ?.*\) iter|Base:\t\(unsigned ?.*\) iter_[0-9]* \+ \(unsigned ?.*\) step} "ivopts"} } */
diff --git a/gcc/testsuite/gfortran.dg/addressing-modes_1.f90 b/gcc/testsuite/gfortran.dg/addressing-modes_1.f90
new file mode 100644
index 0000000000000000000000000000000000000000..334d5bc47a16e53e9168bb1f90dfeff584b4e494
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/addressing-modes_1.f90
@@ -0,0 +1,37 @@
+! { dg-do compile { target aarch64-*-* } }
+! { dg-additional-options "-w -Ofast" }
+
+  module brute_force
+    integer, parameter :: r=9
+     integer  block(r, r, 0)
+    contains
+  subroutine brute
+     do
+      do
+          do
+           do
+                do
+                     do
+                         do i7 = l0, 1
+                       select case(1 )
+                       case(1)
+                           block(:2, 7:, 1) = block(:2, 7:, i7) - 1
+                       end select
+                            do i8 = 1, 1
+                               do i9 = 1, 1
+                            if(1 == 1) then
+                                    call digits_20
+                                end if
+                                end do
+                          end do
+                    end do
+                    end do
+              end do
+              end do
+           end do
+     end do
+  end do
+ end
+  end
+
+! { dg-final { scan-assembler-not {ldr\s+d([0-9]+),\s+\[x[0-9]+, x[0-9]+\]} } }
diff --git a/gcc/tree-ssa-loop-ivopts.cc b/gcc/tree-ssa-loop-ivopts.cc
index b05e4ac1e63b5c110707a8a3ed5e614b7ccc702f..5fc188ae3f8207943a9503e2dc51b067c3f85739 100644
--- a/gcc/tree-ssa-loop-ivopts.cc
+++ b/gcc/tree-ssa-loop-ivopts.cc
@@ -1184,23 +1184,41 @@ static struct iv *
 alloc_iv (struct ivopts_data *data, tree base, tree step,
 	  bool no_overflow = false)
 {
-  tree expr = base;
   struct iv *iv = (struct iv*) obstack_alloc (&data->iv_obstack,
 					      sizeof (struct iv));
   gcc_assert (step != NULL_TREE);
 
-  /* Lower address expression in base except ones with DECL_P as operand.
-     By doing this:
+  /* Lower address expression in base by folding if possible while maintaining
+     the original type of the expression.  Any ADDR_EXPR should not be folded as
+     we will end up folding this into an integer and losing the fact it's an
+     address.
+     By doing this folding we gain:
        1) More accurate cost can be computed for address expressions;
        2) Duplicate candidates won't be created for bases in different
 	  forms, like &a[0] and &a.  */
+  tree expr = base;
   STRIP_NOPS (expr);
-  if ((TREE_CODE (expr) == ADDR_EXPR && !DECL_P (TREE_OPERAND (expr, 0)))
-      || contain_complex_addr_expr (expr))
+  if (TREE_CODE (expr) != ADDR_EXPR)
     {
       aff_tree comb;
-      tree_to_aff_combination (expr, TREE_TYPE (expr), &comb);
-      base = fold_convert (TREE_TYPE (base), aff_combination_to_tree (&comb));
+      tree addr = NULL_TREE;
+      /* Contrary to the comment above, IVopts does not deal well with folding
+	 address the pointers.  We avoid folding ADDR_EXPR but when we have a
+	 POINTER_PLUS_EXPR we want to keep the base the same but still fold the
+	 offset.  */
+      if (TREE_CODE (expr) == POINTER_PLUS_EXPR)
+	{
+	  addr = TREE_OPERAND (expr, 0);
+	  expr = TREE_OPERAND (expr, 1);
+	}
+
+      tree utype = unsigned_type_for (TREE_TYPE (expr));
+      tree_to_aff_combination (expr, utype, &comb);
+      expr = aff_combination_to_tree (&comb);
+      if (addr)
+	expr = fold_build_pointer_plus (addr, expr);
+
+      base = fold_convert (TREE_TYPE (base), expr);
     }
 
   iv->base = base;
