https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85185

--- Comment #10 from Jim Wilson <wilson at gcc dot gnu.org> ---
It is the same basic problem as before, but more serious.  The original
testcase uses a short variable, and can be fixed by adding a cast to int.  But
the new testcase does not use any short variables.

There seems to be a disconnect between the C parser and the RTL expander here. 
the C parser is giving the asm operand a type of short unsigned int, which is
the smallest integer type that the constant can fit in.  The RTL expander is
then generating a HImode reg for it, but loading a constant into an HImode reg
will implicitly sign extend it, which is wrong for a short unsigned int asm
operand.

Before the expand_expr call...

Breakpoint 6, expand_asm_stmt (stmt=stmt@entry=0x7ffff6274108)
    at ../../gcc-git/gcc/cfgexpand.c:3247
(gdb) print val
$11 = <integer_cst 0x7ffff6258fc0>
(gdb) pt
warning: Expression is not an assignment (and might have no effect)
 <integer_cst 0x7ffff6258fc0 type <integer_type 0x7ffff6169540 short unsigned
i\
nt> constant 65532>
(gdb) 

after the expand_expr call...
gdb) print op
$12 = (rtx) 0x7ffff6163450
(gdb) pr
warning: Expression is not an assignment (and might have no effect)
(const_int -4 [0xfffffffffffffffc])
(gdb) 

then it does
            op = force_reg (TYPE_MODE (type), op);
and we end up with
gdb) print op
$13 = (rtx) 0x7ffff6272828
(gdb) pr
warning: Expression is not an assignment (and might have no effect)
(reg:HI 72)


Maybe what we need here is some equivalent to PROMOTE_MODES to force asm
operands to word mode on targets where this makes more sense.  But this needs
to happen before the constant gets sign extended, which means it has to happen
before or inside the expand_expr call.

Reply via email to