In expr.c, this code if (TREE_THIS_VOLATILE (exp)) MEM_VOLATILE_P (temp) = 1; sets MEM_VOLATILE_P for a volatile MEM_REF. But this is not done for a volatile TARGET_MEM_REF. This doesn't matter right now because tree-ssa-loop-ivopts.c bails out if it sees a volatile memory reference, so volatile TARGET_MEM_REFs don't (yet) occur in the wild.
It looks like set_mem_attributes () will set it via a similar check.
case TARGET_MEM_REF: { addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)))); unsigned int align; op0 = addr_for_mem_ref (exp, as, true); op0 = memory_address_addr_space (mode, op0, as); temp = gen_rtx_MEM (mode, op0); set_mem_attributes (temp, exp, 0); ..... void set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp, poly_int64 bitpos) { ... /* If T is not a type, we may be able to deduce some more information about the expression. */ if (! TYPE_P (t)) { tree base; if (TREE_THIS_VOLATILE (t)) MEM_VOLATILE_P (ref) = 1; ----- CUT ---- The code in set_mem_attributes has been there since Oct 2001 (r0-37666, 3.1.0) The code to call set_mem_attributes has not changed since Aug 2010, r0-102267 (when TMR_ORIGINAL was removed and instead of calling set_mem_attributes on TMR_ORIGINAL, it is called on the TMR itself). So GCC is doing the correct thing for TARGET_MEM_REF as Richard Biener reported in comment #1.