This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR optimization/12926
- From: Eric Botcazou <ebotcazou at libertysurf dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 12 Nov 2003 19:34:03 +0100
- Subject: [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;
}