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

            Bug ID: 100228
           Summary: repeated std::atomic<double>::load() misoptimized by
                    x87 peephole
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: aoliva at gcc dot gnu.org
  Target Milestone: ---
            Target: i686-pc-linux-gnu

compile this with -O2 -mfpmath=387 -mno-sse

#include <atomic>

int main() {
  std::atomic<double> a0;
  std::atomic<double> a1(1.0);
  a0 = a1.load();
  if (a0.load() != a1.load())
    __builtin_abort ();
}

it aborts because the first a1.load() is optimized by sync.md:398:

(define_peephole2
  [(set (match_operand:DF 0 "memory_operand")
        (match_operand:DF 1 "any_fp_register_operand"))
   (set (mem:BLK (scratch:SI))
        (unspec:BLK [(mem:BLK (scratch:SI))] UNSPEC_MEMORY_BLOCKAGE))
   (set (match_operand:DF 2 "fp_register_operand")
        (unspec:DF [(match_operand:DI 3 "memory_operand")]
                   UNSPEC_FILD_ATOMIC))
   (set (match_operand:DI 4 "memory_operand")
        (unspec:DI [(match_dup 2)]
                   UNSPEC_FIST_ATOMIC))]
  "!TARGET_64BIT
   && peep2_reg_dead_p (4, operands[2])
   && rtx_equal_p (XEXP (operands[0], 0), XEXP (operands[3], 0))"
  [(const_int 0)]
{
  emit_insn (gen_memory_blockage ());
  emit_move_insn (gen_lowpart (DFmode, operands[4]), operands[1]);
  DONE;
})

the memory location operands[0] stored into by the first instruction is reused
and loaded again in the second a1.load(), but after this peephole, there's no
store before the load.

I don't think we have infrastructure in peephole to test whether there are any
other uses of a store, so I think we have to keep it.  There are other
variations of this peephole around it, that appear to have the same problem.

Reply via email to