constraints.md: Add "C" constraint for call insns.

* config/h8300/constraints.md: Add "C" constraint for call insns.
	* config/h8300/h8300.md (call, call_value): Turn into a define_expand
	and define_insn pair.  Move invalid call targets into a register in
	the expander and fix constraints in the matching pattern.
	* config/h8300/predicates.md (call_expander_operand): Renamed from
	call_insn_operand.  Reject things we shouldn't be trying to handle.
	(call_insn_operand): New predicate for use by the call/call_value
	insns.
	(small_call_insn_operand): Update appropriately.

From-SVN: r266571
This commit is contained in:
Jeff Law 2018-11-28 10:26:03 -07:00
parent 7185a4ebc2
commit 735352d2ee
4 changed files with 81 additions and 29 deletions

View file

@ -1,7 +1,19 @@
2018-11-28 Jeff Law <law@redhat.com>
* config/h8300/constraints.md: Add "C" constraint for call insns.
* config/h8300/h8300.md (call, call_value): Turn into a define_expand
and define_insn pair. Move invalid call targets into a register in
the expander and fix constraints in the matching pattern.
* config/h8300/predicates.md (call_expander_operand): Renamed from
call_insn_operand. Reject things we shouldn't be trying to handle.
(call_insn_operand): New predicate for use by the call/call_value
insns.
(small_call_insn_operand): Update appropriately.
2018-11-28 Sam Tebbs <sam.tebbs@arm.com>
* config/aarch64/aarch64.c (aarch64_process_target_attr): Replace
calls to strtok with strtok_r.
calls to strtok with strtok_r.
2018-11-28 Richard Biener <rguenther@suse.de>

View file

@ -158,6 +158,10 @@
(and (match_code "const_int")
(match_test "!h8300_shift_needs_scratch_p (ival, QImode)")))
(define_constraint "C"
"@internal"
(match_code "symbol_ref"))
(define_constraint "S"
"@internal"
(and (match_code "const_int")

View file

@ -2064,16 +2064,30 @@
;; ??? Even though we use HImode here, this works on the H8/300H and H8S.
(define_insn "call"
[(call (match_operand:QI 0 "call_insn_operand" "or")
(match_operand:HI 1 "general_operand" "g"))]
(define_expand "call"
[(call (match_operand:QI 0 "call_expander_operand" "")
(match_operand:HI 1 "general_operand" ""))]
""
{
if (!register_operand (XEXP (operands[0], 0), Pmode)
&& GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
XEXP (operands[0], 0) = force_reg (Pmode, XEXP (operands[0], 0));
})
(define_insn "call_insn"
[(call (mem:QI (match_operand 0 "call_insn_operand" "Cr"))
(match_operand:HI 1 "general_operand" "g"))]
""
{
if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
&& (SYMBOL_REF_FLAGS (XEXP (operands[0], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
return "jsr\\t@%0:8";
rtx xoperands[1];
xoperands[0] = gen_rtx_MEM (QImode, operands[0]);
gcc_assert (GET_MODE (operands[0]) == Pmode);
if (GET_CODE (XEXP (xoperands[0], 0)) == SYMBOL_REF
&& (SYMBOL_REF_FLAGS (XEXP (xoperands[0], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
output_asm_insn ("jsr\\t@%0:8", xoperands);
else
return "jsr\\t%0";
output_asm_insn ("jsr\\t%0", xoperands);
return "";
}
[(set_attr "type" "call")
(set (attr "length")
@ -2086,17 +2100,33 @@
;; ??? Even though we use HImode here, this works on the H8/300H and H8S.
(define_insn "call_value"
(define_expand "call_value"
[(set (match_operand 0 "" "")
(call (match_operand:QI 1 "call_expander_operand" "")
(match_operand:HI 2 "general_operand" "")))]
""
{
if (!register_operand (XEXP (operands[1], 0), Pmode)
&& GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0));
})
(define_insn "call_value_insn"
[(set (match_operand 0 "" "=r")
(call (match_operand:QI 1 "call_insn_operand" "or")
(match_operand:HI 2 "general_operand" "g")))]
(call (mem:QI (match_operand 1 "call_insn_operand" "Cr"))
(match_operand:HI 2 "general_operand" "g")))]
""
{
if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
&& (SYMBOL_REF_FLAGS (XEXP (operands[1], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
return "jsr\\t@%1:8";
rtx xoperands[2];
gcc_assert (GET_MODE (operands[1]) == Pmode);
xoperands[0] = operands[0];
xoperands[1] = gen_rtx_MEM (QImode, operands[1]);
if (GET_CODE (XEXP (xoperands[1], 0)) == SYMBOL_REF
&& (SYMBOL_REF_FLAGS (XEXP (xoperands[1], 0)) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
output_asm_insn ("jsr\\t@%1:8", xoperands);
else
return "jsr\\t%1";
output_asm_insn ("jsr\\t%1", xoperands);
return "";
}
[(set_attr "type" "call")
(set (attr "length")

View file

@ -216,7 +216,7 @@
;; Return true if OP is a valid call operand.
(define_predicate "call_insn_operand"
(define_predicate "call_expander_operand"
(match_code "mem")
{
if (GET_CODE (op) == MEM)
@ -224,31 +224,37 @@
rtx inside = XEXP (op, 0);
if (register_operand (inside, Pmode))
return 1;
if (CONSTANT_ADDRESS_P (inside))
if (SYMBOL_REF_P (inside))
return 1;
}
return 0;
})
(define_predicate "call_insn_operand"
(match_code "reg,symbol_ref")
{
if (register_operand (op, Pmode))
return 1;
if (SYMBOL_REF_P (op))
return 1;
return 0;
})
;; Return true if OP is a valid call operand, and OP represents an
;; operand for a small call (4 bytes instead of 6 bytes).
(define_predicate "small_call_insn_operand"
(match_code "mem")
(match_code "reg,symbol_ref")
{
if (GET_CODE (op) == MEM)
{
rtx inside = XEXP (op, 0);
/* Register indirect is a small call. */
if (register_operand (op, Pmode))
return 1;
/* Register indirect is a small call. */
if (register_operand (inside, Pmode))
return 1;
/* A call through the function vector is a small call too. */
if (GET_CODE (op) == SYMBOL_REF
&& (SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
return 1;
/* A call through the function vector is a small call too. */
if (GET_CODE (inside) == SYMBOL_REF
&& (SYMBOL_REF_FLAGS (inside) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
return 1;
}
/* Otherwise it's a large call. */
return 0;
})