2008-12-04 16:15:40 +00:00
|
|
|
Hello,
|
|
|
|
|
|
|
|
in the appended testcase (obtained from linux kernel), the following
|
|
|
|
bug occurred: load motion decides to optimize non-volatile instance
|
|
|
|
of src_pte, and not to take volatile instance into account. When
|
|
|
|
checking for availability, we however consider these instances to be equal,
|
|
|
|
which causes us to believe that the second load of pte is redundant.
|
|
|
|
|
|
|
|
The patch fixes it.
|
|
|
|
|
|
|
|
Zdenek
|
|
|
|
|
|
|
|
typedef struct { unsigned long pte_low; } pte_t;
|
|
|
|
static inline void clear_bit(int nr, volatile void * addr)
|
|
|
|
{
|
|
|
|
__asm__ __volatile__(
|
|
|
|
"btrl %1,%0"
|
|
|
|
:"=m" ((*(volatile long *) addr))
|
|
|
|
:"Ir" (nr));
|
|
|
|
}
|
|
|
|
static inline void ptep_set_wrprotect(pte_t *ptep) { clear_bit(1, ptep); }
|
|
|
|
int copy_page_range(void)
|
|
|
|
{
|
|
|
|
pte_t * src_pte;
|
|
|
|
pte_t pte = *src_pte;
|
|
|
|
|
|
|
|
if (pte.pte_low) {
|
|
|
|
ptep_set_wrprotect(src_pte);
|
|
|
|
pte = *src_pte;
|
|
|
|
}
|
|
|
|
|
|
|
|
foo (pte);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Changelog:
|
|
|
|
* gcse.c (expr_equiv_p): Don't consider anything to be equal to
|
|
|
|
volatile mem.
|
|
|
|
|
2009-11-20 12:08:01 +00:00
|
|
|
Index: gcc/gcse.c
|
2008-12-04 16:15:40 +00:00
|
|
|
===================================================================
|
2009-11-20 12:08:01 +00:00
|
|
|
--- gcc/gcse.c.orig 2009-11-20 13:04:56.000000000 +0100
|
|
|
|
+++ gcc/gcse.c 2009-11-20 13:05:44.000000000 +0100
|
|
|
|
@@ -1847,6 +1847,10 @@ expr_equiv_p (x, y)
|
|
|
|
due to it being set with the different alias set. */
|
|
|
|
if (MEM_ALIAS_SET (x) != MEM_ALIAS_SET (y))
|
|
|
|
return 0;
|
|
|
|
+
|
|
|
|
+ /* A volatile mem should not be considered equivalent to any other. */
|
|
|
|
+ if (MEM_VOLATILE_P (x) || MEM_VOLATILE_P (y))
|
|
|
|
+ return 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* For commutative operations, check both orders. */
|