This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR optimization/12926


Hi,

This is a regression from GCC 3.2.3 on SPARC64, present on the 3.3 branch.

The assignments to the bit-fields in the constructor of

struct A
{
  enum Type {P, U, S};

  const size_t mSize : 8*sizeof(size_t) - 3;
  Type mType : 2;
};

use the same memory address, but the first MEM is marked as unchanging while 
the second MEM is not. From 00.rtl:

(insn 23 22 24 (nil) (set (mem/s/u/j:DI (reg/v/f:DI 110) [0 S8 A64])
        (reg:DI 112)) -1 (nil)
    (nil))

(insn 29 28 31 (nil) (set (mem/s/j:DI (reg/v/f:DI 110) [0 S8 A64])
        (reg:DI 114)) -1 (nil)
    (nil))

So there are not detected as aliasing and are swapped by the scheduler, which 
produces wrong code since the first assignment doesn't contain the value for 
the second bit-field.


The problem is hidden on mainline by

2003-09-12  Roger Sayle  <roger@eyesopen.com>

	PR optimization/8967
	* alias.c (write_dependence_p): Modify to take an additional constp
	argument that controls whether the UNCHANGING_RTX_P flags are used.
	(anti_dependence, output_dependence): Adjust write_dependence_p
	callers to pass this additional argument, to return the same result.
	(unchanging_anti_dependence): New variant of anti_dependence that
	ignores the UNCHANGING_RTX_P property on memory references.
	* rtl.h (unchaning_anti_dependence): Prototype here.
	* flow.c (init_propagate_block): Place fake constant mem writes on
	the mem_set_list so that dead writes to const variables are deleted.
	(insn_dead_p): Change anti_dependence to unchanging_anti_dependence.
	(mark_used_regs): Likewise.

because flow.c is able to delete the first assignment as dead. However, I 
think that the semantics of UNCHANGING_RTX_P is still violated by the RTL 
expander.

The proposed fix is to not put the UNCHANGING_RTX_P flag on a MEM which is 
not addressable, because a non-unchanging object might be referenced by the 
same MEM.


Bootstrapped/regtested on i586-redhat-linux-gnu (3.3 branch except Ada). Ok 
for mainline and 3.3 branch?


2003-11-12  Eric Botcazou  <ebotcazou@libertysurf.fr>

        PR optimization/12926
	* expr.c (expand_assignment) [COMPONENT_REF]: Don't put
	the UNCHANGING_RTX_P flag on memory references to read-only
	components that are not addressable. 


2003-11-12  Eric Botcazou  <ebotcazou@libertysurf.fr>

        * g++.dg/opt/const3.C: New test.


-- 
Eric Botcazou
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.498.2.21
diff -u -p -r1.498.2.21 expr.c
--- expr.c	6 Sep 2003 08:06:00 -0000	1.498.2.21
+++ expr.c	11 Nov 2003 12:49:10 -0000
@@ -4128,7 +4128,11 @@ expand_assignment (to, from, want_value,
 	}
 
       if (TREE_CODE (to) == COMPONENT_REF
-	  && TREE_READONLY (TREE_OPERAND (to, 1)))
+	  && TREE_READONLY (TREE_OPERAND (to, 1))
+	  /* We can't assert that a MEM won't be set more than once
+	     if the component is not addressable because another
+	     non-addressable component may be referenced by the same MEM.  */
+	  && ! (GET_CODE (to_rtx) == MEM && ! can_address_p (to)))
 	{
 	  if (to_rtx == orig_to_rtx)
 	    to_rtx = copy_rtx (to_rtx);
// PR optimization/12926
// This failed on SPARC64 because the assignments to the bit-fields
// were wrongly swapped in the constructor.

// { dg-do run }
// { dg-options "-O2" }

extern void abort(void);

typedef __SIZE_TYPE__ size_t;

void *my_out;

struct A
{
  enum Type {P, U, S};

  int foo1(void *, const char *);
  int foo2(int, const Type);

  A (const size_t size, const Type type): mSize(size), mType(type)
  {
      foo2(foo1(my_out, "type = "), type);
      foo2(foo1(my_out, "mType = "), mType);
  }

  const size_t mSize : 8*sizeof(size_t) - 3;
  Type mType : 2;
};

int i;

int A::foo1(void *ios, const char *str) { }
int A::foo2(int v, const Type t) { i=0; }

int main()
{
  A testa(2, A::S);

  if (testa.mType != A::S)
     abort();

  return 0;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]