On Tue, Jun 06, 2006 at 07:42:20AM +0200, Wolfgang Mües wrote: > Rask, > > On Monday 05 June 2006 16:16, Rask Ingemann Lambertsen wrote:
> > I think the comment in arm.h is wrong. The manual seems to agree with > > the code. > > Just to make it easy for beginners... In mainline GCC, it is defined like this in arm/constraints.md: (define_memory_constraint "Q" "@internal In ARM state an address that is a single base register." (and (match_code "mem") (match_test "REG_P (XEXP (op, 0))"))) > Hmmm... I have searched 'Q' in the arm files. Not used in arm.md, only > for some variants of arm (cirrus). Maybe only implemented for them? > > I assume there is no way to tell the direction in > arm_legitimate_address_p() ? Hmmm. There isn't. arm_legitimate_address_p() just implements the macro GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL). The only trick I know here is to use a different mode for special addresses. I'm writing an Intel 8086 backend which uses #define FUNCTION_MODE PQImode to let GO_IF_LEGITIMATE_ADDRESS handle function addresses specially. I just can't think of a way of using such a trick in this case. > > + swp%?b\\t%1, %1, %0\;ldr%?b\\t%1, %0" > > You should get a price for cleverness here! Thanks! Indeed it looks good until you think of volatile variables. > > +; Avoid reading the stored value back if we have a spare register. > > +(define_peephole2 > > + [(match_scratch:QI 2 "r") [snip] > > As far as I can tell now, this works good. But I think there are many > cases in which the source operand is not needed after the store. Is > there a possibility to clobber the source operand and not using another > register? I don't know if (match_scratch ...) might reuse the source operand. It can be attempted more specifically with an additional peephole definition: (define_peephole2 [(set (match_operand:QI 0 "memory_operand" "") (match_operand:QI 1 "register_operand" ""))] "TARGET_ARM && TARGET_SWP_BYTE_WRITES && peep2_reg_dead_p (1, operands[1])" [(parallel [(set (match_dup 0) (match_dup 1)) (clobber (match_dup 1))] )] ) Yet another register which stands a good chance of being reusable is the register containing the address. This can be covered as well (assuming the match_scratch version doesn't do this): (define_peephole2 [(set (mem:QI (match_operand 0 "pmode_register_operand" "")) (match_operand:QI 1 "register_operand" ""))] "TARGET_ARM && TARGET_SWP_BYTE_WRITES && peep2_reg_dead_p (1, operands[0])" [(parallel [(set (mem:QI (match_dup 0)) (match_dup 1)) (clobber (match_dup 0))] )] ) I haven't tested these two peephole definitions. I can't think of any preferred order. It'll be your call, I guess. > > The register allocator chooses to use the lr register, in turn > > causing link register save alimination to fail, which doesn't help. > > I can't understand this without explanation... is it bad? GCC now needs more registers to hold addresses. The increased number of registers used disable som ARM specific optimizations of the function prologue and epilogue. This is bad, but only because the code becomes larger and slower. But I think that bytewritetest() suffers relatively much because it is a small function, using only a few registers to begin with. -- Rask Ingemann Lambertsen