C:\devel\gccnew\gcc>gccmvs -DUSE_MEMMGR -Os -S -ansi -pedantic-errors -DHAVE_CON
FIG_H -DIN_GCC -DPUREISO -I ../../pdos/pdpclib -I . -I config/i370 -I
../include
varasm.c
(insn 117 429 118 7 (parallel [
(set (reg:SI 64)
(compare:SI (mem/s:BLK (plus:SI (reg/f:SI 21
virtual-stack-vars)
(const_int 456 [0x1c8])) [232 value+0 S196
A64])
(mem:BLK (plus:SI (reg/v/f:SI 61 [ desc ])
(const_int 8 [0x8])) [0 A8])))
(use (const_int 196 [0xc4]))
]) -1 (nil)
(nil))
varasm.c: In function `force_const_mem':
varasm.c:3021: internal compiler error: in
instantiate_virtual_regs_lossage,
at function.c:3767
OK, so what goes on here is that GCC attempts to replace the "virtual"
register 21 (virtual-stack-vars) with some real register, that is
frame pointer + STARTING_FRAME_OFFSET. It seems for the i370 port,
this should resolve to
register 13 + STACK_POINTER_OFFSET + current_function_outgoing_args_size
Overall, the middle-end would therefore replace "reg 21 + 456" with
"reg 13 + X", where X is constant computed from 456 + STACK_POINTER_OFFSET
+ current_function_outgoing_args_size.
It will then re-process the insn pattern constraints to verify that the
resulting insn is still valid. At this stage, it appears we're running
into the above error. I'm not quite sure why this would be case, this
will require some further debugging why the insn was not recognized ...
Ok, I spent today trying to solve this problem. Although I didn't succeed
in solving it properly, I did at least find a workaround for the one
instance.
I found that in the failing circumstance, neither of the two things being
compared fell into the "force copy" situation. I don't know whether that
is right or wrong, but at least I can detect whether a "force copy" was
done. If no force copy was done, I stop doing the short CLC and let
it do the CLCL instead. See below where I have introduced the "copy"
variable. Unfortunately it affects other things, ie good CLCs have been
converted into CLCL also, which is a shame. However, it may at least
mean the compiler doesn't have a bug as far as the end user is
concerned, ie it generates valid code.
I have a theory that if both displacements in the S-type (ie register plus
displacement) address are non-zero, that something fails. So the
next thing I will do is see if I can detect just that situation, and stop
it going into the CLC.
Some of these md constructs are beginning to make more sense. :-)
BFN. Paul.
;
; cmpmemsi instruction pattern(s).
;
(define_expand "cmpmemsi"
[(set (match_operand:SI 0 "general_operand" "")
(compare (match_operand:BLK 1 "general_operand" "")
(match_operand:BLK 2 "general_operand" "")))
(use (match_operand:SI 3 "general_operand" ""))
(use (match_operand:SI 4 "" ""))]
""
"
{
rtx op1, op2;
int copy = 0;
op1 = XEXP (operands[1], 0);
if (GET_CODE (op1) == REG
|| (GET_CODE (op1) == PLUS && GET_CODE (XEXP (op1, 0)) == REG
&& GET_CODE (XEXP (op1, 1)) == CONST_INT
&& (unsigned) INTVAL (XEXP (op1, 1)) < 4096))
{
op1 = operands[1];
}
else
{
op1 = gen_rtx_MEM (BLKmode, copy_to_mode_reg (SImode, op1));
copy = 1;
}
op2 = XEXP (operands[2], 0);
if (GET_CODE (op2) == REG
|| (GET_CODE (op2) == PLUS && GET_CODE (XEXP (op2, 0)) == REG
&& GET_CODE (XEXP (op2, 1)) == CONST_INT
&& (unsigned) INTVAL (XEXP (op2, 1)) < 4096))
{
op2 = operands[2];
}
else
{
op2 = gen_rtx_MEM (BLKmode, copy_to_mode_reg (SImode, op2));
copy = 1;
}
/* so long as at least one operand was copied, this seems safe */
if (copy &&
GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) < 256)
{
emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_COMPARE (SImode, op1, op2)), /* was VOIDmode */
gen_rtx_USE (VOIDmode, operands[3]))));
}
else
{
/* implementation suggested by Richard Henderson <r...@cygnus.com>
*/
rtx reg1 = gen_reg_rtx (DImode);
rtx reg2 = gen_reg_rtx (DImode);
rtx result = operands[0];
rtx mem1 = operands[1];
rtx mem2 = operands[2];
rtx len = operands[3];
if (!CONSTANT_P (len))
len = force_reg (SImode, len);
/* Load up the address+length pairs. */
emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1));
emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0),
force_operand (XEXP (mem1, 0), NULL_RTX));
emit_move_insn (gen_rtx_SUBREG (SImode, reg1, GET_MODE_SIZE
(SImode)), len);
emit_insn (gen_rtx_CLOBBER (VOIDmode, reg2));
emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 0),
force_operand (XEXP (mem2, 0), NULL_RTX));
emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE
(SImode)), len);
/* Compare! */
emit_insn (gen_cmpmemsi_1 (result, reg1, reg2));
}
DONE;
}")
; Compare a block that is less than 256 bytes in length.
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
(compare:SI (match_operand:BLK 1 "s_operand" "m")
(match_operand:BLK 2 "s_operand" "m")))
(use (match_operand:QI 3 "immediate_operand" "I"))]
"((unsigned) INTVAL (operands[3]) < 256)"
"*
{
check_label_emit ();
mvs_check_page (0, 22, 0);
return \"CLC %O1(%c3,%R1),%2\;BH *+12\;BL *+6\;SLR %0,%0\;LNR %0,%0\";
}"
[(set_attr "length" "22")]
)
; Compare a block that is larger than 255 bytes in length.
; (mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "+d")
0))
; (mem:BLK (subreg:SI (match_operand:DI 2 "register_operand" "+d")
0))))
(define_insn "cmpmemsi_1"
[(set (match_operand:SI 0 "register_operand" "+d")
(compare:SI
(mem:BLK (match_operand:DI 1 "register_operand" "+d") )
(mem:BLK (match_operand:DI 2 "register_operand" "+d") )))
(use (match_dup 1))
(use (match_dup 2))
(clobber (match_dup 1))
(clobber (match_dup 2))]
""
"*
{
check_label_emit ();
mvs_check_page (0, 18, 0);
return \"LA %0,1(0,0)\;CLCL %1,%2\;BH *+12\;BL *+6\;SLR %0,%0\;LNR
%0,%0\";
}"
[(set_attr "length" "18")]
)