constraints.md (ZQ, ZR, ZS, ZT): New constraints.
2009-07-22 Andreas Krebbel <krebbel1@de.ibm.com> * config/s390/constraints.md (ZQ, ZR, ZS, ZT): New constraints. (U, W): Constraints are now deprecated and will be removed if we run out of letters. * config/s390/s390.md (U, W): Replaced with ZQZR, ZSZT throughout the file. ("prefetch"): Add the stcmh instruction for prefetching. * config/s390/s390.c (s390_symref_operand_p): Function moved. No changes. (s390_short_displacement): Return always true if compiling for machines not providing the long displacement facility. (s390_mem_constraint): Support the new constraint letter Z. (s390_check_qrst_address): New function. From-SVN: r149917
This commit is contained in:
parent
40b125d799
commit
4fe6dea8ff
|
@ -1,3 +1,18 @@
|
|||
2009-07-22 Andreas Krebbel <krebbel1@de.ibm.com>
|
||||
|
||||
* config/s390/constraints.md (ZQ, ZR, ZS, ZT): New constraints.
|
||||
(U, W): Constraints are now deprecated and will be removed if we
|
||||
run out of letters.
|
||||
* config/s390/s390.md (U, W): Replaced with ZQZR, ZSZT throughout
|
||||
the file.
|
||||
("prefetch"): Add the stcmh instruction for prefetching.
|
||||
* config/s390/s390.c (s390_symref_operand_p): Function moved. No
|
||||
changes.
|
||||
(s390_short_displacement): Return always true if compiling for
|
||||
machines not providing the long displacement facility.
|
||||
(s390_mem_constraint): Support the new constraint letter Z.
|
||||
(s390_check_qrst_address): New function.
|
||||
|
||||
2009-07-21 DJ Delorie <dj@redhat.com>
|
||||
|
||||
* config/mep/mep.c (mep_legitimize_arg): Leave control registers
|
||||
|
|
|
@ -66,9 +66,14 @@
|
|||
;; B -- Multiple letter constraint followed by Q, R, S, or T:
|
||||
;; Memory reference of the type specified by second letter that
|
||||
;; does *not* refer to a literal pool entry.
|
||||
;; U -- Pointer with short displacement.
|
||||
;; W -- Pointer with long displacement.
|
||||
;; U -- Pointer with short displacement. (deprecated - use ZQZR)
|
||||
;; W -- Pointer with long displacement. (deprecated - use ZSZT)
|
||||
;; Y -- Shift count operand.
|
||||
;; ZQ -- Pointer without index register and with short displacement.
|
||||
;; ZR -- Pointer with index register and short displacement.
|
||||
;; ZS -- Pointer without index register but with long displacement.
|
||||
;; ZT -- Pointer with index register and long displacement.
|
||||
;;
|
||||
;;
|
||||
|
||||
|
||||
|
@ -462,11 +467,26 @@ constraint."
|
|||
|
||||
|
||||
(define_address_constraint "U"
|
||||
"Pointer with short displacement"
|
||||
"Pointer with short displacement. (deprecated - use ZQZR)"
|
||||
(match_test "s390_mem_constraint (\"U\", op)"))
|
||||
|
||||
|
||||
|
||||
(define_address_constraint "W"
|
||||
"Pointer with long displacement"
|
||||
"Pointer with long displacement. (deprecated - use ZSZT)"
|
||||
(match_test "s390_mem_constraint (\"W\", op)"))
|
||||
|
||||
|
||||
(define_address_constraint "ZQ"
|
||||
"Pointer without index register and with short displacement."
|
||||
(match_test "s390_mem_constraint (\"ZQ\", op)"))
|
||||
|
||||
(define_address_constraint "ZR"
|
||||
"Pointer with index register and short displacement."
|
||||
(match_test "s390_mem_constraint (\"ZR\", op)"))
|
||||
|
||||
(define_address_constraint "ZS"
|
||||
"Pointer without index register but with long displacement."
|
||||
(match_test "s390_mem_constraint (\"ZS\", op)"))
|
||||
|
||||
(define_address_constraint "ZT"
|
||||
"Pointer with index register and long displacement."
|
||||
(match_test "s390_mem_constraint (\"ZT\", op)"))
|
||||
|
|
|
@ -1664,6 +1664,11 @@ s390_short_displacement (rtx disp)
|
|||
if (!disp)
|
||||
return true;
|
||||
|
||||
/* Without the long displacement facility we don't need to
|
||||
distingiush between long and short displacement. */
|
||||
if (!TARGET_LONG_DISPLACEMENT)
|
||||
return true;
|
||||
|
||||
/* Integer displacement in range. */
|
||||
if (GET_CODE (disp) == CONST_INT)
|
||||
return INTVAL (disp) >= 0 && INTVAL (disp) < 4096;
|
||||
|
@ -2032,132 +2037,168 @@ s390_legitimate_address_without_index_p (rtx op)
|
|||
}
|
||||
|
||||
|
||||
/* Evaluates constraint strings described by the regular expression
|
||||
([A|B](Q|R|S|T))|U|W and returns 1 if OP is a valid operand for the
|
||||
constraint given in STR, or 0 else. */
|
||||
/* Return true if ADDR is of kind symbol_ref or symbol_ref + const_int
|
||||
and return these parts in SYMREF and ADDEND. You can pass NULL in
|
||||
SYMREF and/or ADDEND if you are not interested in these values. */
|
||||
|
||||
int
|
||||
s390_mem_constraint (const char *str, rtx op)
|
||||
static bool
|
||||
s390_symref_operand_p (rtx addr, rtx *symref, HOST_WIDE_INT *addend)
|
||||
{
|
||||
HOST_WIDE_INT tmpaddend = 0;
|
||||
|
||||
if (GET_CODE (addr) == CONST)
|
||||
addr = XEXP (addr, 0);
|
||||
|
||||
if (GET_CODE (addr) == PLUS)
|
||||
{
|
||||
if (GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
|
||||
&& CONST_INT_P (XEXP (addr, 1)))
|
||||
{
|
||||
tmpaddend = INTVAL (XEXP (addr, 1));
|
||||
addr = XEXP (addr, 0);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if (GET_CODE (addr) != SYMBOL_REF)
|
||||
return false;
|
||||
|
||||
if (symref)
|
||||
*symref = addr;
|
||||
if (addend)
|
||||
*addend = tmpaddend;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Return true if the address in OP is valid for constraint letter C
|
||||
if wrapped in a MEM rtx. Set LIT_POOL_OK to true if it literal
|
||||
pool MEMs should be accepted. Only the Q, R, S, T constraint
|
||||
letters are allowed for C. */
|
||||
|
||||
static int
|
||||
s390_check_qrst_address (char c, rtx op, bool lit_pool_ok)
|
||||
{
|
||||
struct s390_address addr;
|
||||
char c = str[0];
|
||||
bool decomposed = false;
|
||||
|
||||
/* Check for offsettable variants of memory constraints. */
|
||||
if (c == 'A')
|
||||
/* This check makes sure that no symbolic address (except literal
|
||||
pool references) are accepted by the R or T constraints. */
|
||||
if (s390_symref_operand_p (op, NULL, NULL))
|
||||
{
|
||||
/* Only accept non-volatile MEMs. */
|
||||
if (!MEM_P (op) || MEM_VOLATILE_P (op))
|
||||
if (!lit_pool_ok)
|
||||
return 0;
|
||||
|
||||
if ((reload_completed || reload_in_progress)
|
||||
? !offsettable_memref_p (op) : !offsettable_nonstrict_memref_p (op))
|
||||
if (!s390_decompose_address (op, &addr))
|
||||
return 0;
|
||||
|
||||
c = str[1];
|
||||
}
|
||||
|
||||
/* Check for non-literal-pool variants of memory constraints. */
|
||||
else if (c == 'B')
|
||||
{
|
||||
if (GET_CODE (op) != MEM)
|
||||
if (!addr.literal_pool)
|
||||
return 0;
|
||||
if (!s390_decompose_address (XEXP (op, 0), &addr))
|
||||
return 0;
|
||||
if (addr.literal_pool)
|
||||
return 0;
|
||||
|
||||
c = str[1];
|
||||
decomposed = true;
|
||||
}
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'Q': /* no index short displacement */
|
||||
if (!decomposed && !s390_decompose_address (op, &addr))
|
||||
return 0;
|
||||
if (addr.indx)
|
||||
return 0;
|
||||
if (!s390_short_displacement (addr.disp))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 'R': /* with index short displacement */
|
||||
if (TARGET_LONG_DISPLACEMENT)
|
||||
{
|
||||
if (!decomposed && !s390_decompose_address (op, &addr))
|
||||
return 0;
|
||||
if (!s390_short_displacement (addr.disp))
|
||||
return 0;
|
||||
}
|
||||
/* Any invalid address here will be fixed up by reload,
|
||||
so accept it for the most generic constraint. */
|
||||
break;
|
||||
|
||||
case 'S': /* no index long displacement */
|
||||
if (!TARGET_LONG_DISPLACEMENT)
|
||||
return 0;
|
||||
if (!decomposed && !s390_decompose_address (op, &addr))
|
||||
return 0;
|
||||
if (addr.indx)
|
||||
return 0;
|
||||
if (s390_short_displacement (addr.disp))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 'T': /* with index long displacement */
|
||||
if (!TARGET_LONG_DISPLACEMENT)
|
||||
return 0;
|
||||
/* Any invalid address here will be fixed up by reload,
|
||||
so accept it for the most generic constraint. */
|
||||
if ((decomposed || s390_decompose_address (op, &addr))
|
||||
&& s390_short_displacement (addr.disp))
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Evaluates constraint strings described by the regular expression
|
||||
([A|B|Z](Q|R|S|T))|U|W|Y and returns 1 if OP is a valid operand for
|
||||
the constraint given in STR, or 0 else. */
|
||||
|
||||
int
|
||||
s390_mem_constraint (const char *str, rtx op)
|
||||
{
|
||||
char c = str[0];
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'A':
|
||||
/* Check for offsettable variants of memory constraints. */
|
||||
if (!MEM_P (op) || MEM_VOLATILE_P (op))
|
||||
return 0;
|
||||
if ((reload_completed || reload_in_progress)
|
||||
? !offsettable_memref_p (op) : !offsettable_nonstrict_memref_p (op))
|
||||
return 0;
|
||||
return s390_check_qrst_address (str[1], XEXP (op, 0), true);
|
||||
case 'B':
|
||||
/* Check for non-literal-pool variants of memory constraints. */
|
||||
if (!MEM_P (op))
|
||||
return 0;
|
||||
return s390_check_qrst_address (str[1], XEXP (op, 0), false);
|
||||
case 'Q':
|
||||
if (GET_CODE (op) != MEM)
|
||||
return 0;
|
||||
if (!s390_decompose_address (XEXP (op, 0), &addr))
|
||||
return 0;
|
||||
if (addr.indx)
|
||||
return 0;
|
||||
|
||||
if (TARGET_LONG_DISPLACEMENT)
|
||||
{
|
||||
if (!s390_short_displacement (addr.disp))
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
if (GET_CODE (op) != MEM)
|
||||
return 0;
|
||||
|
||||
if (TARGET_LONG_DISPLACEMENT)
|
||||
{
|
||||
if (!s390_decompose_address (XEXP (op, 0), &addr))
|
||||
return 0;
|
||||
if (!s390_short_displacement (addr.disp))
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
if (!TARGET_LONG_DISPLACEMENT)
|
||||
return 0;
|
||||
if (GET_CODE (op) != MEM)
|
||||
return 0;
|
||||
if (!s390_decompose_address (XEXP (op, 0), &addr))
|
||||
return 0;
|
||||
if (addr.indx)
|
||||
return 0;
|
||||
if (s390_short_displacement (addr.disp))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
if (!TARGET_LONG_DISPLACEMENT)
|
||||
return 0;
|
||||
if (GET_CODE (op) != MEM)
|
||||
return 0;
|
||||
if (!s390_decompose_address (XEXP (op, 0), &addr))
|
||||
return 0;
|
||||
if (s390_short_displacement (addr.disp))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
return s390_check_qrst_address (c, XEXP (op, 0), true);
|
||||
case 'U':
|
||||
if (TARGET_LONG_DISPLACEMENT)
|
||||
{
|
||||
if (!s390_decompose_address (op, &addr))
|
||||
return 0;
|
||||
if (!s390_short_displacement (addr.disp))
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
return (s390_check_qrst_address ('Q', op, true)
|
||||
|| s390_check_qrst_address ('R', op, true));
|
||||
case 'W':
|
||||
if (!TARGET_LONG_DISPLACEMENT)
|
||||
return 0;
|
||||
if (!s390_decompose_address (op, &addr))
|
||||
return 0;
|
||||
if (s390_short_displacement (addr.disp))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
return (s390_check_qrst_address ('S', op, true)
|
||||
|| s390_check_qrst_address ('T', op, true));
|
||||
case 'Y':
|
||||
/* Simply check for the basic form of a shift count. Reload will
|
||||
take care of making sure we have a proper base register. */
|
||||
if (!s390_decompose_shift_count (op, NULL, NULL))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
return s390_check_qrst_address (str[1], op, true);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Evaluates constraint strings starting with letter O. Input
|
||||
parameter C is the second letter following the "O" in the constraint
|
||||
string. Returns 1 if VALUE meets the respective constraint and 0
|
||||
|
@ -2775,41 +2816,6 @@ s390_preferred_reload_class (rtx op, enum reg_class rclass)
|
|||
return rclass;
|
||||
}
|
||||
|
||||
/* Return true if ADDR is of kind symbol_ref or symbol_ref + const_int
|
||||
and return these parts in SYMREF and ADDEND. You can pass NULL in
|
||||
SYMREF and/or ADDEND if you are not interested in these values. */
|
||||
|
||||
static bool
|
||||
s390_symref_operand_p (rtx addr, rtx *symref, HOST_WIDE_INT *addend)
|
||||
{
|
||||
HOST_WIDE_INT tmpaddend = 0;
|
||||
|
||||
if (GET_CODE (addr) == CONST)
|
||||
addr = XEXP (addr, 0);
|
||||
|
||||
if (GET_CODE (addr) == PLUS)
|
||||
{
|
||||
if (GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
|
||||
&& CONST_INT_P (XEXP (addr, 1)))
|
||||
{
|
||||
tmpaddend = INTVAL (XEXP (addr, 1));
|
||||
addr = XEXP (addr, 0);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if (GET_CODE (addr) != SYMBOL_REF)
|
||||
return false;
|
||||
|
||||
if (symref)
|
||||
*symref = addr;
|
||||
if (addend)
|
||||
*addend = tmpaddend;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Return true if ADDR is SYMBOL_REF + addend with addend being a
|
||||
multiple of ALIGNMENT and the SYMBOL_REF being naturally
|
||||
aligned. */
|
||||
|
|
|
@ -1440,7 +1440,7 @@
|
|||
|
||||
(define_insn "*la_64"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d,d")
|
||||
(match_operand:QI 1 "address_operand" "U,W"))]
|
||||
(match_operand:QI 1 "address_operand" "ZQZR,ZSZT"))]
|
||||
"TARGET_64BIT"
|
||||
"@
|
||||
la\t%0,%a1
|
||||
|
@ -1623,7 +1623,7 @@
|
|||
|
||||
(define_insn "*la_31"
|
||||
[(set (match_operand:SI 0 "register_operand" "=d,d")
|
||||
(match_operand:QI 1 "address_operand" "U,W"))]
|
||||
(match_operand:QI 1 "address_operand" "ZQZR,ZSZT"))]
|
||||
"!TARGET_64BIT && legitimate_la_operand_p (operands[1])"
|
||||
"@
|
||||
la\t%0,%a1
|
||||
|
@ -1658,7 +1658,7 @@
|
|||
|
||||
(define_insn "*la_31_and"
|
||||
[(set (match_operand:SI 0 "register_operand" "=d,d")
|
||||
(and:SI (match_operand:QI 1 "address_operand" "U,W")
|
||||
(and:SI (match_operand:QI 1 "address_operand" "ZQZR,ZSZT")
|
||||
(const_int 2147483647)))]
|
||||
"!TARGET_64BIT"
|
||||
"@
|
||||
|
@ -1684,7 +1684,7 @@
|
|||
|
||||
(define_insn "force_la_31"
|
||||
[(set (match_operand:SI 0 "register_operand" "=d,d")
|
||||
(match_operand:QI 1 "address_operand" "U,W"))
|
||||
(match_operand:QI 1 "address_operand" "ZQZR,ZSZT"))
|
||||
(use (const_int 0))]
|
||||
"!TARGET_64BIT"
|
||||
"@
|
||||
|
@ -7402,7 +7402,7 @@
|
|||
[(set (pc)
|
||||
(if_then_else
|
||||
(match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
|
||||
(match_operand 0 "address_operand" "U")
|
||||
(match_operand 0 "address_operand" "ZQZR")
|
||||
(pc)))]
|
||||
""
|
||||
{
|
||||
|
@ -7466,7 +7466,7 @@
|
|||
(if_then_else
|
||||
(match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
|
||||
(pc)
|
||||
(match_operand 0 "address_operand" "U")))]
|
||||
(match_operand 0 "address_operand" "ZQZR")))]
|
||||
""
|
||||
{
|
||||
if (get_attr_op_type (insn) == OP_TYPE_RR)
|
||||
|
@ -7673,7 +7673,7 @@
|
|||
(if_then_else
|
||||
(ne (match_operand:SI 1 "register_operand" "d")
|
||||
(const_int 1))
|
||||
(match_operand 0 "address_operand" "U")
|
||||
(match_operand 0 "address_operand" "ZQZR")
|
||||
(pc)))
|
||||
(set (match_operand:SI 2 "register_operand" "=1")
|
||||
(plus:SI (match_dup 1) (const_int -1)))
|
||||
|
@ -7784,7 +7784,7 @@
|
|||
;
|
||||
|
||||
(define_insn "indirect_jump"
|
||||
[(set (pc) (match_operand 0 "address_operand" "U"))]
|
||||
[(set (pc) (match_operand 0 "address_operand" "ZQZR"))]
|
||||
""
|
||||
{
|
||||
if (get_attr_op_type (insn) == OP_TYPE_RR)
|
||||
|
@ -7803,7 +7803,7 @@
|
|||
;
|
||||
|
||||
(define_insn "casesi_jump"
|
||||
[(set (pc) (match_operand 0 "address_operand" "U"))
|
||||
[(set (pc) (match_operand 0 "address_operand" "ZQZR"))
|
||||
(use (label_ref (match_operand 1 "" "")))]
|
||||
""
|
||||
{
|
||||
|
@ -8025,7 +8025,7 @@
|
|||
(set_attr "type" "jsr")])
|
||||
|
||||
(define_insn "*basr"
|
||||
[(call (mem:QI (match_operand 0 "address_operand" "U"))
|
||||
[(call (mem:QI (match_operand 0 "address_operand" "ZQZR"))
|
||||
(match_operand 1 "const_int_operand" "n"))
|
||||
(clobber (match_operand 2 "register_operand" "=r"))]
|
||||
"!SIBLING_CALL_P (insn) && GET_MODE (operands[2]) == Pmode"
|
||||
|
@ -8083,7 +8083,7 @@
|
|||
|
||||
(define_insn "*basr_r"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:QI (match_operand 1 "address_operand" "U"))
|
||||
(call (mem:QI (match_operand 1 "address_operand" "ZQZR"))
|
||||
(match_operand 2 "const_int_operand" "n")))
|
||||
(clobber (match_operand 3 "register_operand" "=r"))]
|
||||
"!SIBLING_CALL_P (insn) && GET_MODE (operands[3]) == Pmode"
|
||||
|
@ -8183,7 +8183,7 @@
|
|||
|
||||
(define_insn "*basr_tls"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:QI (match_operand 1 "address_operand" "U"))
|
||||
(call (mem:QI (match_operand 1 "address_operand" "ZQZR"))
|
||||
(match_operand 2 "const_int_operand" "n")))
|
||||
(clobber (match_operand 3 "register_operand" "=r"))
|
||||
(use (match_operand 4 "" ""))]
|
||||
|
@ -8709,27 +8709,32 @@
|
|||
;
|
||||
|
||||
(define_insn "prefetch"
|
||||
[(prefetch (match_operand 0 "address_operand" "UW,X")
|
||||
(match_operand:SI 1 "const_int_operand" "n,n")
|
||||
(match_operand:SI 2 "const_int_operand" "n,n"))]
|
||||
"TARGET_Z10"
|
||||
[(prefetch (match_operand 0 "address_operand" "ZQZS,ZRZT,X")
|
||||
(match_operand:SI 1 "const_int_operand" " n, n,n")
|
||||
(match_operand:SI 2 "const_int_operand" " n, n,n"))]
|
||||
"TARGET_ZARCH && s390_tune == PROCESSOR_2097_Z10"
|
||||
{
|
||||
if (larl_operand (operands[0], Pmode))
|
||||
return INTVAL (operands[1]) == 1 ? "pfdrl\t2,%a0" : "pfdrl\t1,%a0";
|
||||
switch (which_alternative)
|
||||
{
|
||||
case 0:
|
||||
return INTVAL (operands[1]) == 1 ? "stcmh\t2,0,%a0" : "stcmh\t1,0,%a0";
|
||||
case 1:
|
||||
return INTVAL (operands[1]) == 1 ? "pfd\t2,%a0" : "pfd\t1,%a0";
|
||||
case 2:
|
||||
if (larl_operand (operands[0], Pmode))
|
||||
return INTVAL (operands[1]) == 1 ? "pfdrl\t2,%a0" : "pfdrl\t1,%a0";
|
||||
default:
|
||||
|
||||
if (s390_mem_constraint ("W", operands[0])
|
||||
|| s390_mem_constraint ("U", operands[0]))
|
||||
return INTVAL (operands[1]) == 1 ? "pfd\t2,%a0" : "pfd\t1,%a0";
|
||||
/* This might be reached for symbolic operands with an odd
|
||||
addend. We simply omit the prefetch for such rare cases. */
|
||||
|
||||
/* This point might be reached if op0 is a larl operand with an
|
||||
uneven addend. In this case we simply omit issuing a prefetch
|
||||
instruction. */
|
||||
|
||||
return "";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
[(set_attr "type" "load,larl")
|
||||
(set_attr "op_type" "RXY,RIL")
|
||||
(set_attr "z10prop" "z10_super")])
|
||||
[(set_attr "type" "store,load,larl")
|
||||
(set_attr "op_type" "RSY,RXY,RIL")
|
||||
(set_attr "z10prop" "z10_super")
|
||||
(set_attr "cpu_facility" "*,z10,z10")])
|
||||
|
||||
|
||||
;
|
||||
|
|
Loading…
Reference in New Issue