From 4fe6dea8ffc4ca9e1d502c29f0148c4a2c90ba07 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Wed, 22 Jul 2009 07:47:04 +0000 Subject: [PATCH] constraints.md (ZQ, ZR, ZS, ZT): New constraints. 2009-07-22 Andreas Krebbel * 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 --- gcc/ChangeLog | 15 +++ gcc/config/s390/constraints.md | 32 +++++-- gcc/config/s390/s390.c | 210 +++++++++++++++++++++-------------------- gcc/config/s390/s390.md | 67 +++++++------ 4 files changed, 185 insertions(+), 139 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ced279d..7e939cd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2009-07-22 Andreas Krebbel + + * 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 * config/mep/mep.c (mep_legitimize_arg): Leave control registers diff --git a/gcc/config/s390/constraints.md b/gcc/config/s390/constraints.md index 8fec7e1..8564b66 100644 --- a/gcc/config/s390/constraints.md +++ b/gcc/config/s390/constraints.md @@ -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)")) diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 350850a..1454fde 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -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,79 +2037,93 @@ 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) { - struct s390_address addr; - char c = str[0]; + HOST_WIDE_INT tmpaddend = 0; - /* Check for offsettable variants of memory constraints. */ - if (c == 'A') + if (GET_CODE (addr) == CONST) + addr = XEXP (addr, 0); + + if (GET_CODE (addr) == PLUS) { - /* Only accept non-volatile MEMs. */ - if (!MEM_P (op) || MEM_VOLATILE_P (op)) - return 0; + 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 ((reload_completed || reload_in_progress) - ? !offsettable_memref_p (op) : !offsettable_nonstrict_memref_p (op)) - return 0; + if (symref) + *symref = addr; + if (addend) + *addend = tmpaddend; - c = str[1]; - } + 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. */ - /* Check for non-literal-pool variants of memory constraints. */ - else if (c == 'B') +static int +s390_check_qrst_address (char c, rtx op, bool lit_pool_ok) +{ + struct s390_address addr; + bool decomposed = false; + + /* 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)) { - if (GET_CODE (op) != MEM) + if (!lit_pool_ok) return 0; - if (!s390_decompose_address (XEXP (op, 0), &addr)) + if (!s390_decompose_address (op, &addr)) return 0; - if (addr.literal_pool) + if (!addr.literal_pool) return 0; - - c = str[1]; + decomposed = true; } switch (c) { - case 'Q': - if (GET_CODE (op) != MEM) - return 0; - if (!s390_decompose_address (XEXP (op, 0), &addr)) + case 'Q': /* no index short displacement */ + if (!decomposed && !s390_decompose_address (op, &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) + if (!s390_short_displacement (addr.disp)) return 0; + break; + case 'R': /* with index short displacement */ if (TARGET_LONG_DISPLACEMENT) { - if (!s390_decompose_address (XEXP (op, 0), &addr)) + 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': + case 'S': /* no index long displacement */ if (!TARGET_LONG_DISPLACEMENT) return 0; - if (GET_CODE (op) != MEM) - return 0; - if (!s390_decompose_address (XEXP (op, 0), &addr)) + if (!decomposed && !s390_decompose_address (op, &addr)) return 0; if (addr.indx) return 0; @@ -2112,52 +2131,74 @@ s390_mem_constraint (const char *str, rtx op) return 0; break; - case 'T': + case 'T': /* with index long displacement */ 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)) + /* 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; +} - case 'U': - if (TARGET_LONG_DISPLACEMENT) - { - if (!s390_decompose_address (op, &addr)) - return 0; - if (!s390_short_displacement (addr.disp)) - return 0; - } - break; - case 'W': - if (!TARGET_LONG_DISPLACEMENT) +/* 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 (!s390_decompose_address (op, &addr)) + if ((reload_completed || reload_in_progress) + ? !offsettable_memref_p (op) : !offsettable_nonstrict_memref_p (op)) return 0; - if (s390_short_displacement (addr.disp)) + 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; - break; - + return s390_check_qrst_address (str[1], XEXP (op, 0), false); + case 'Q': + case 'R': + case 'S': + case 'T': + if (GET_CODE (op) != MEM) + return 0; + return s390_check_qrst_address (c, XEXP (op, 0), true); + case 'U': + return (s390_check_qrst_address ('Q', op, true) + || s390_check_qrst_address ('R', op, true)); + case 'W': + 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. */ diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index ed08f6e..b6a5446 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -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"; - - 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 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 ""; + 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: + + /* This might be reached for symbolic operands with an odd + addend. We simply omit the prefetch for such rare cases. */ + + 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")]) ; -- 2.7.4