[PR,rtl-optimization/91173] Backport to GCC 8 and 9

Message ID CAOrE4X0kd8gS05EaMFnRToav6zsLu6OFOb+VU+vstTyNN4qOFA@mail.gmail.com
State New
Headers show
Series
  • [PR,rtl-optimization/91173] Backport to GCC 8 and 9
Related show

Commit Message

Matthew Beliveau July 23, 2019, 2:02 p.m.
Tested on GCC 8 and 9.

Patch

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2019-07-23  Matthew Beliveau  <mbelivea@redhat.com>
	
	Backported from mainline
	2019-07-16  Jeff Law  <law@redhat.com>
	
	PR rtl-optimization/91173
	* tree-ssa-address.c (addr_for_mem_ref): If the base is an
	SSA_NAME with a constant value, fold its value into the offset
	and clear the base before calling gen_addr_rtx.

	* g++.dg/pr91173.C: New test.

diff --git gcc/testsuite/g++.dg/pr91173.C gcc/testsuite/g++.dg/pr91173.C
new file mode 100644
index 00000000000..b8fb41ba0cd
--- /dev/null
+++ gcc/testsuite/g++.dg/pr91173.C
@@ -0,0 +1,45 @@ 
+class a {
+  int b;
+  void *c;
+
+public:
+  bool aa();
+  int &ab() {
+    if (aa()) {
+      void *d(c);
+      return static_cast<int *>(d)[b];
+    }
+    return *(int *)0;
+  }
+};
+typedef enum {E} e;
+class f : public a {
+  int g;
+
+public:
+  int ac() {
+    if (g)
+      return 1;
+    return ac();
+  }
+};
+int *ad;
+struct h {
+  static int ae(e, int *m) {
+    f ag;
+    int *ah;
+    while (!0) {
+      ad = &ag.ab();
+      ah = ad + ag.ac();
+      while (ad < ah)
+        *m = *ad++;
+    }
+  }
+};
+template <class, class>
+void i(int *, int *, int, int *, e n, int *o) {
+  h::ae(n, o);
+}
+int aq, ar, as, at, au;
+void aw() { i<int, bool>(&aq, &ar, as, &at, (e)0, &au); }
+
diff --git gcc/tree-ssa-address.c gcc/tree-ssa-address.c
index 1c17e935914..2e5d87734d6 100644
--- gcc/tree-ssa-address.c
+++ gcc/tree-ssa-address.c
@@ -259,6 +259,20 @@  addr_for_mem_ref (struct mem_address *addr, addr_space_t as,
 	 ? expand_expr (addr->index, NULL_RTX, pointer_mode, EXPAND_NORMAL)
 	 : NULL_RTX);
 
+  /* addr->base could be an SSA_NAME that was set to a constant value.  The
+     call to expand_expr may expose that constant.  If so, fold the value
+     into OFF and clear BSE.  Otherwise we may later try to pull a mode from
+     BSE to generate a REG, which won't work with constants because they
+     are modeless.  */
+  if (bse && GET_CODE (bse) == CONST_INT)
+    {
+      if (off)
+	off = simplify_gen_binary (PLUS, pointer_mode, bse, off);
+      else
+	off = bse;
+      gcc_assert (GET_CODE (off) == CONST_INT);
+      bse = NULL_RTX;
+    }
   gen_addr_rtx (pointer_mode, sym, bse, idx, st, off, &address, NULL, NULL);
   if (pointer_mode != address_mode)
     address = convert_memory_address (address_mode, address);