Hi Ulrich. I put in the following debug:
op0 = find_replacement (&XEXP (in, 0));
op1 = find_replacement (&XEXP (in, 1));
/* Since constraint checking is strict, commutativity won't be
checked, so we need to do that here to avoid spurious failure
if the add instruction is two-address and the second operand
of the add is the same as the reload reg, which is frequently
the case. If the insn would be A = B + A, rearrange it so
it will be A = A + B as constrain_operands expects. */
fprintf(stderr, "REGNO(out) is %d\n", REGNO(out));
fprintf(stderr, " REG in 1 is %d\n", REGNO(XEXP(in,1)));
if (GET_CODE (XEXP (in, 1)) == REG
&& REGNO (out) == REGNO (XEXP (in, 1)))
tem = op0, op0 = op1, op1 = tem;
And it produced this output (for exactly the same code I showed
you previously):
C:\devel\pdos\s370>\devel\gcc\gcc\gccmvs -da -DUSE_MEMMGR -Os -DS390 -S -I
. -I ../pdpclib pdos.c
REGNO(out) is 3
REG in 1 is 32880
REGNO(out) is 2
REG in 1 is 32880
REGNO(out) is 2
REG in 1 is 32880
REGNO(out) is 2
REG in 1 is 112
REGNO(out) is 3
REG in 1 is 32880
REGNO(out) is 4
REG in 1 is 112
REGNO(out) is 2
REG in 1 is 112
which looks to me like it is not seeing a register, only a constant,
so cannot perform a swap.
Let me know if that is not the debugging required.
Thanks. Paul.
-----Original Message-----
From: Ulrich Weigand
Sent: Tuesday, August 16, 2011 11:25 PM
To: Paul Edwards
Cc: gcc@gcc.gnu.org
Subject: Re: i370 port
Paul Edwards wrote:
>> Unfortunately it's not quite right, seemingly not loading R9 properly:
>>
>> LR 9,13
>> AR 9,13
>> MVC 0(10,9),0(2)
> That's weird. What does the reload dump (.greg) say?
I have trimmed the code down to a reasonably small size so that I
could provide the .greg file (below) from the "-da" option. I don't
know how to read it so I don't know if I've provided everything
required.
Here is the current problematic generated code:
* Function pdosLoadExe code
L 2,4(11)
MVC 88(4,13),=A(LC0)
ST 2,92(13)
LA 1,88(,13)
L 15,=V(PRINTF)
BALR 14,15
LR 3,13 <========= probably wrong
AR 3,13 <========= else this is wrong
MVC 0(10,3),0(2)
Reload decides on the following actions:
Reloads for insn # 38
Reload 0: reload_in (SI) = (const_int 32880 [0x8070])
ADDR_REGS, RELOAD_FOR_INPUT_ADDRESS (opnum = 0)
reload_in_reg: (const_int 32880 [0x8070])
reload_reg_rtx: (reg:SI 3 3)
Reload 1: reload_in (SI) = (plus:SI (reg/f:SI 13 13)
(const_int 32880
[0x8070]))
ADDR_REGS, RELOAD_FOR_INPUT (opnum = 0)
reload_in_reg: (plus:SI (reg/f:SI 13 13)
(const_int 32880
[0x8070]))
reload_reg_rtx: (reg:SI 3 3)
That is, first: load the constant 32880 into register 3,
and second: using that reloaded constant, compute the sum
of register 13 plus 32880 and load the result also into
register 3. Then, use that register for addressing.
This leads to the following generated code:
(insn 271 37 273 0 (set (reg:SI 3 3)
(const_int 32880 [0x8070])) 15 {movsi} (nil)
(nil))
Load constant into register 3.
(insn 273 271 274 0 (set (reg:SI 3 3)
(reg/f:SI 13 13)) 15 {movsi} (nil)
(nil))
(insn 274 273 38 0 (set (reg:SI 3 3)
(plus:SI (reg:SI 3 3)
(reg:SI 3 3))) 41 {addsi3} (nil)
(expr_list:REG_EQUIV (plus:SI (reg/f:SI 13 13)
(reg:SI 3 3))
(nil)))
Compute the sum. Note that this code is wrong.
(insn 38 274 41 0 (parallel [
(set (mem/s:BLK (reg:SI 3 3) [6 srchprog+0 S10 A64])
(mem:BLK (reg/v/f:SI 2 2 [orig:27 prog ] [27]) [0 S10
A8]))
(use (const_int 10 [0xa]))
]) 25 {*i370.md:1623} (insn_list 37 (nil))
(nil))
Use register 3 for adressing.
The wrong code comes in when generating the sum (insns 273/274).
I would have expected this to be a simple addsi3 instruction, along the
lines of
(set (reg:SI 3 3) (plus:SI (reg:SI 3 3) (reg:SI 13 13)))
Note that the incoming pattern:
(set (reg:SI 3 3) (plus:SI (reg:SI 13 13) (reg:SI 3 3)))
cannot be immediately resolved, since addsi3 requires the first
operand of the plus to match the result.
However, this could have been fixed by just swapping the operands.
Instead, the code attempts to create the match by reloading the
first operand (reg 13) into the output (reg 3) -- this is bogus,
since it thereby clobbers the *second* input operand, which happens
to match the output.
The code that generates these insns is in reload1.c:gen_reload
/* We need to compute the sum of a register or a MEM and another
register, constant, or MEM, and put it into the reload
register. The best possible way of doing this is if the machine
has a three-operand ADD insn that accepts the required operands.
The simplest approach is to try to generate such an insn and see if
it
is recognized and matches its constraints. If so, it can be used.
It might be better not to actually emit the insn unless it is
valid,
but we need to pass the insn as an operand to `recog' and
`extract_insn' and it is simpler to emit and then delete the insn
if
not valid than to dummy things up. */
rtx op0, op1, tem, insn;
int code;
op0 = find_replacement (&XEXP (in, 0));
op1 = find_replacement (&XEXP (in, 1));
/* Since constraint checking is strict, commutativity won't be
checked, so we need to do that here to avoid spurious failure
if the add instruction is two-address and the second operand
of the add is the same as the reload reg, which is frequently
the case. If the insn would be A = B + A, rearrange it so
it will be A = A + B as constrain_operands expects. */
if (GET_CODE (XEXP (in, 1)) == REG
&& REGNO (out) == REGNO (XEXP (in, 1)))
tem = op0, op0 = op1, op1 = tem;
if (op0 != XEXP (in, 0) || op1 != XEXP (in, 1))
in = gen_rtx_PLUS (GET_MODE (in), op0, op1);
insn = emit_insn (gen_rtx_SET (VOIDmode, out, in));
code = recog_memoized (insn);
Note how this actually performs the check whether to swap operands
for commutativity.
Can you debug this and find out why this doesn't work in your case?
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
ulrich.weig...@de.ibm.com