http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55139
--- Comment #1 from Andi Kleen <andi-gcc at firstfloor dot org> 2012-11-07
04:03:53 UTC ---
This is an interesting one. This is the gcc code:
enum memmodel
{
MEMMODEL_RELAXED = 0,
MEMMODEL_CONSUME = 1,
MEMMODEL_ACQUIRE = 2,
MEMMODEL_RELEASE = 3,
MEMMODEL_ACQ_REL = 4,
MEMMODEL_SEQ_CST = 5,
MEMMODEL_LAST = 6
};
#define MEMMODEL_MASK ((1<<16)-1)
enum memmodel model;
model = get_memmodel (CALL_EXPR_ARG (exp, 2));
if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED
&& (model & MEMMODEL_MASK) != MEMMODEL_SEQ_CST
&& (model & MEMMODEL_MASK) != MEMMODEL_RELEASE)
{
error ("invalid memory model for %<__atomic_store%>");
return NULL_RTX;
}
HLE_STORE is 1 << 16, so outside the enum range
But when looking at the assembler we see that the & MEMMODEL_MASK
gets optimized away, it just generates a direct sequence of 32bit cmps.
This makes all the != fail, even though they should succeed
I presume the optimizer assumes nothing can be outside the enum.
I tried to expand the enum by adding
MEMMODEL_ARCH1 = 1 << 16,
MEMMODEL_ARCH2 = 1 << 17,
MEMMODEL_ARCH3 = 1 << 18,
MEMMODEL_ARCH4 = 1 << 19
But still doesn't work.
Questions:
- Is it legal for the optimizer to assume this?
- Why does extending the enum not help?
We could fix it by not using an enum here of course, but I wonder if this is an
underlying optimizer bug.