Ian Lance Taylor wrote: > Georg-Johann Lay: >> >> What about that predicate? >> >> (define_predicate "low_io_mem" >> (and (match_code "mem") >> (match_test "low_io_address_operand (XEXP (op, 0))"))) >> >> Guess it operates the same because the drag-volatile-over-volatile >> happens not in recog(_for_combine) but already when combine >> synthesizes new patterns.
Jepp, I tried that. Just as I expected, it is no cure. >> As combine juggles with data flow, it must >> not exchange volatiles. That's all. The backend will know if it's ok >> to place a specific operand into a specific insn or not. >> >> And skipping optimizations like these altogether because they are >> uncomfortable to handle is the wrong direction, IMHO. > > OK, what is your proposed patch to combine? Maybe it is easy to make it > do what you want. I haven't looked. > > Ian No, I have no patch. But I had a closer look at combine.c: In try_combine, just after the "Trying..." dump output, we have: i0 = 0 i1 = 0 i2 = (set (reg/v:QI 43 [ status ]) (mem/v:QI (const_int 43 [0x2b]))) i3 = (set (pc) (if_then_else (eq (zero_extract:QI (reg/v:QI 43 [ status ]) (const_int 1) (const_int 4)) (const_int 0)) (label_ref:HI 16) (pc))) where to potential insertion is i2 into i3. These insns are fed into can_combine_p with src = (mem/v:QI (const_int 43)) dest = (reg/v:QI 43) and then there is this part of an if-clause: /* Make sure that the value that is to be substituted for the register does not use any registers whose values alter in between. However, If the insns are adjacent, a use can't cross a set even though we think it might (this can happen for a sequence of insns each setting the same destination; last_set of that register might point to a NOTE). If INSN has a REG_EQUIV note, the register is always equivalent to the memory so the substitution is valid even if there are intervening stores. Also, don't move a volatile asm or UNSPEC_VOLATILE across any other insns. */ || (! all_adjacent && (((!MEM_P (src) || ! find_reg_note (insn, REG_EQUIV, src)) && use_crosses_set_p (src, DF_INSN_LUID (insn))) || (GET_CODE (src) == ASM_OPERANDS && MEM_VOLATILE_P (src)) || GET_CODE (src) == UNSPEC_VOLATILE)) In addition to these tests, the following must be disallowed: If src contains volatile memory, then disallow moving it across: * volatile memory * unspec_volatile * asm volatile As far as I can see, use_crosses_set_p (src,...) returns 0 (false) which is incorrect. So either use_crosses_set_p is incorrect or it relies on incorrect data from data flow analysis or from wherever. Johann