This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Register constraints + and =


On 04/05/12 14:44, Ian Lance Taylor wrote:
I agree that there is something wrong here.  I agree that as written
the constraints for operands 0, 1, and 2 should have a '+'.

That said, a '+' constraint is most useful for a pattern that expands
into multiple instructions.  I think this would be better written along
the lines of

   (set (match_operand:QI 2 "register_operand" "=d,c") (const_int 0))
   (set (mem:BLK (match_operand:QI 3 "register_operand" "0")
                 (match_operand:QI 4 "register_operand" "1")))
   (set (match_operand:QI 0 "register_operand" "=d,c")
        (plus:QI (match_dup 3)
                 (match_operand:QI 5 "register_operand" "2"))))
   (set (match_operand:QI 1 "register_operand" "=x,c")
        (plus:QI (match_dup 4) (match_dup 5)))
   (clobber (match_scratch:QI 3 "=w,w"))

Also it looks like it might be possible to add a third alternative such
that that alternative does not require the match_scratch.

Ian


Thanks for your suggestion, I use it in my discussion below.


Unfortunately this is in preparation for my block copy instruction bc2.
bc2 instruction takes source address in register RXL, destination in RAH, and count in RAL. After bc2, RAL is set to 0, RXL is RXL + RAL (source address plus count) and RAH is RAH + RAL (destination address plus count). This is specified as:
(define_insn "bc2"
[(set (reg:QI RAL) (const_int 0))
(set (mem:BLK (reg:QI RAH)) (mem:BLK (reg:QI RAL)))
(set (reg:QI RXL) (plus:QI (reg:QI RXL) (reg:QI RAL)))
(set (reg:QI RAH) (plus:QI (reg:QI RAH) (reg:QI RAL)))]
"!TARGET_NO_BLOCK_COPY"
"bc2")


Unfortunately, and due to problems with GCC47 RA (for reasons mentioned in thread "GCC47 movmem breaks RA, GCC46 RA is fine") I am having trouble getting this to work as well as it did with GCC46. In GCC46 I simply generated, during expand, the correct move insns and then expanded the bc2 insn (with the hardcoded registers).

In GCC47 that breaks apart the RA, so I am attempting to get RA to understand that indeed, there's only one register each of the values can end up in. So now I have something:
(define_expand "movmemqi"
[(set (match_operand:BLK 0 "memory_operand") ; destination
(match_operand:BLK 1 "memory_operand")) ; source
(use (match_operand:QI 2 "general_operand")) ; count
(match_operand 3 "" "")]
"!TARGET_NO_BLOCK_COPY && !reload_completed"
{ xap_expand_movmemqi(operands[0], operands[1], operands[2]); DONE; })


(define_insn_and_split "movmem_long"
  [(set (match_operand:QI 2 "register_operand" "=d") (const_int 0))
   (set (mem:BLK (match_operand:QI 3 "register_operand" "0"))
        (mem:BLK (match_operand:QI 4 "register_operand" "1")))
   (set (match_operand:QI 0 "register_operand" "=d")
        (plus:QI (match_dup 3)
                 (match_operand:QI 5 "register_operand" "2")))
   (set (match_operand:QI 1 "register_operand" "=x")
        (plus:QI (match_dup 4) (match_dup 5)))
   (clobber (match_scratch:QI 6 "=w"))]
  "!TARGET_NO_BLOCK_COPY"
  "#"
  "&& reload_completed"
  [(const_int 0)]
{
  if(REGNO(operands[2]) == RAH)
  {
    emit_move_insn(operands[6], operands[0]);
    emit_move_insn(operands[0], operands[2]);
    emit_move_insn(operands[2], operands[6]);
  }
  emit_insn(gen_bc2());
  DONE;
})

xap_expand_movmemqi issues a couple of move_insn if they are required and then does a gen_movmem_long.

I am playing a trick with GCC here... The constraint 'd' applies to register class DATA_REGS, which constains 2 registers: RAL and RAH. When GCC allocates then in bc2, one will be assigned to operand0 and other to operand2. If operand2 ends up with RAH, then I use the scratch to swap operand2 with operand0. The annoying part is that something RA ends up allocating a scratch which I won't use because he was smart enough to allocate everything in order (operand2 with RAL and operand0 with RAH). As a side note, constraint 'x', refers to class ADDR_REGS which only has register RXL.

This solution, however, still causes RA spills which weren't caused by GCC46, but it is better than the GCC46 solution to hardcode the registers straight off expand phase.

Another thing I tried but whose results are terrible (libgcc doesn't even compile due to register spills errors) is to have one class just for RAL, one just for RAH and use those constraints, thereby avoiding the scratch altogether. Turns out GCC doesn't seem to like that.

If you have any further suggestions or ideas that I can try out, please let me know.

--
PMatos


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]