From: Ulrich Weigand Date: Tue, 10 Aug 2004 21:46:33 +0000 (+0000) Subject: s390-protos.h (s390_canonicalize_comparison): Declare. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=68f9c5e21e381b28ed2f1d96dedf507af53d4e54;p=gcc.git s390-protos.h (s390_canonicalize_comparison): Declare. * config/s390/s390-protos.h (s390_canonicalize_comparison): Declare. * config/s390/s390.c (s390_canonicalize_comparison): New function. * config/s390/s390.h (CANONICALIZE_COMPARISON): Define. * config/s390/s390.md ("*tmdi_ext", "*tmsi_ext", "*tmqisi_ext", "*tmqidi_ext", "*tmdi_mem", "*tmsi_mem", "*tmhi_mem"): Remove. ("*tmqi_mem"): Remove SUBREG from pattern. ("*anddi3_cconly"): Prevent accidentally matching TM pattern. ("*andsi3_cconly"): Likewise. From-SVN: r85770 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 56acb0ebee6..0f02c9de6fc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2004-08-10 Ulrich Weigand + + * config/s390/s390-protos.h (s390_canonicalize_comparison): Declare. + * config/s390/s390.c (s390_canonicalize_comparison): New function. + * config/s390/s390.h (CANONICALIZE_COMPARISON): Define. + * config/s390/s390.md ("*tmdi_ext", "*tmsi_ext", "*tmqisi_ext", + "*tmqidi_ext", "*tmdi_mem", "*tmsi_mem", "*tmhi_mem"): Remove. + ("*tmqi_mem"): Remove SUBREG from pattern. + ("*anddi3_cconly"): Prevent accidentally matching TM pattern. + ("*andsi3_cconly"): Likewise. + 2004-08-10 H.J. Lu PR target/16909 diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index acb32b23117..a7498e2d2f3 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -50,6 +50,7 @@ extern int tls_symbolic_operand (rtx); extern int s390_match_ccmode (rtx, enum machine_mode); extern enum machine_mode s390_tm_ccmode (rtx, rtx, int); extern enum machine_mode s390_select_ccmode (enum rtx_code, rtx, rtx); +extern void s390_canonicalize_comparison (enum rtx_code *, rtx *, rtx *); extern int s390_alc_comparison (rtx op, enum machine_mode mode); extern int s390_slb_comparison (rtx op, enum machine_mode mode); extern rtx s390_emit_compare (enum rtx_code, rtx, rtx); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 83e0c629e10..083d7259fdb 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -474,6 +474,87 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1) } } +/* Replace the comparison OP0 CODE OP1 by a semantically equivalent one + that we can implement more efficiently. */ + +void +s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1) +{ + /* Convert ZERO_EXTRACT back to AND to enable TM patterns. */ + if ((*code == EQ || *code == NE) + && *op1 == const0_rtx + && GET_CODE (*op0) == ZERO_EXTRACT + && GET_CODE (XEXP (*op0, 1)) == CONST_INT + && GET_CODE (XEXP (*op0, 2)) == CONST_INT + && SCALAR_INT_MODE_P (GET_MODE (XEXP (*op0, 0)))) + { + rtx inner = XEXP (*op0, 0); + HOST_WIDE_INT modesize = GET_MODE_BITSIZE (GET_MODE (inner)); + HOST_WIDE_INT len = INTVAL (XEXP (*op0, 1)); + HOST_WIDE_INT pos = INTVAL (XEXP (*op0, 2)); + + if (len > 0 && len < modesize + && pos >= 0 && pos + len <= modesize + && modesize <= HOST_BITS_PER_WIDE_INT) + { + unsigned HOST_WIDE_INT block; + block = ((unsigned HOST_WIDE_INT) 1 << len) - 1; + block <<= modesize - pos - len; + + *op0 = gen_rtx_AND (GET_MODE (inner), inner, + gen_int_mode (block, GET_MODE (inner))); + } + } + + /* Narrow AND of memory against immediate to enable TM. */ + if ((*code == EQ || *code == NE) + && *op1 == const0_rtx + && GET_CODE (*op0) == AND + && GET_CODE (XEXP (*op0, 1)) == CONST_INT + && SCALAR_INT_MODE_P (GET_MODE (XEXP (*op0, 0)))) + { + rtx inner = XEXP (*op0, 0); + rtx mask = XEXP (*op0, 1); + + /* Ignore paradoxical SUBREGs if all extra bits are masked out. */ + if (GET_CODE (inner) == SUBREG + && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (inner))) + && (GET_MODE_SIZE (GET_MODE (inner)) + >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (inner)))) + && ((INTVAL (mask) + & GET_MODE_MASK (GET_MODE (inner)) + & ~GET_MODE_MASK (GET_MODE (SUBREG_REG (inner)))) + == 0)) + inner = SUBREG_REG (inner); + + /* Do not change volatile MEMs. */ + if (MEM_P (inner) && !MEM_VOLATILE_P (inner)) + { + int part = s390_single_part (XEXP (*op0, 1), + GET_MODE (inner), QImode, 0); + if (part >= 0) + { + mask = gen_int_mode (s390_extract_part (mask, QImode, 0), QImode); + inner = adjust_address_nv (inner, QImode, part); + *op0 = gen_rtx_AND (QImode, inner, mask); + } + } + } + + /* Narrow comparisons against 0xffff to HImode if possible. */ + + if ((*code == EQ || *code == NE) + && GET_CODE (*op1) == CONST_INT + && INTVAL (*op1) == 0xffff + && SCALAR_INT_MODE_P (GET_MODE (*op0)) + && (nonzero_bits (*op0, GET_MODE (*op0)) + & ~(unsigned HOST_WIDE_INT) 0xffff) == 0) + { + *op0 = gen_lowpart (HImode, *op0); + *op1 = constm1_rtx; + } +} + /* Emit a compare instruction suitable to implement the comparison OP0 CODE OP1. Return the correct condition RTL to be placed in the IF_THEN_ELSE of the conditional branch testing the result. */ diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 3d9180578a5..c92d6ad272d 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -813,6 +813,10 @@ CUMULATIVE_ARGS; return the mode to be used for the comparison. */ #define SELECT_CC_MODE(OP, X, Y) s390_select_ccmode ((OP), (X), (Y)) +/* Canonicalize a comparison from one we don't have to one we do have. */ +#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \ + s390_canonicalize_comparison (&(CODE), &(OP0), &(OP1)) + /* Define the information needed to generate branch and scc insns. This is stored from the compare operation. Note that we can't use "rtx" here since it hasn't been defined! */ diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index d15e7c9a63c..f18fe13d647 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -286,159 +286,13 @@ }) -; Test-under-Mask (zero_extract) instructions - -(define_insn "*tmdi_ext" - [(set (reg 33) - (compare (zero_extract:DI (match_operand:DI 0 "register_operand" "d") - (match_operand:DI 1 "const_int_operand" "n") - (match_operand:DI 2 "const_int_operand" "n")) - (const_int 0)))] - "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT - && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0 - && INTVAL (operands[1]) + INTVAL (operands[2]) <= 64 - && (INTVAL (operands[1]) + INTVAL (operands[2]) - 1) >> 4 - == INTVAL (operands[2]) >> 4" -{ - int part = INTVAL (operands[2]) >> 4; - int block = (1 << INTVAL (operands[1])) - 1; - int shift = 16 - INTVAL (operands[1]) - (INTVAL (operands[2]) & 15); - - operands[2] = GEN_INT (block << shift); - - switch (part) - { - case 0: return "tmhh\t%0,%x2"; - case 1: return "tmhl\t%0,%x2"; - case 2: return "tmlh\t%0,%x2"; - case 3: return "tmll\t%0,%x2"; - default: abort (); - } -} - [(set_attr "op_type" "RI")]) - -(define_insn "*tmsi_ext" - [(set (reg 33) - (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "const_int_operand" "n") - (match_operand:SI 2 "const_int_operand" "n")) - (const_int 0)))] - "s390_match_ccmode(insn, CCTmode) - && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0 - && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32 - && (INTVAL (operands[1]) + INTVAL (operands[2]) - 1) >> 4 - == INTVAL (operands[2]) >> 4" -{ - int part = INTVAL (operands[2]) >> 4; - int block = (1 << INTVAL (operands[1])) - 1; - int shift = 16 - INTVAL (operands[1]) - (INTVAL (operands[2]) & 15); - - operands[2] = GEN_INT (block << shift); - - switch (part) - { - case 0: return "tmh\t%0,%x2"; - case 1: return "tml\t%0,%x2"; - default: abort (); - } -} - [(set_attr "op_type" "RI")]) - -(define_insn "*tmqisi_ext" - [(set (reg 33) - (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "Q,S") - (match_operand:SI 1 "const_int_operand" "n,n") - (match_operand:SI 2 "const_int_operand" "n,n")) - (const_int 0)))] - "!TARGET_64BIT && s390_match_ccmode(insn, CCTmode) - && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0 - && INTVAL (operands[1]) + INTVAL (operands[2]) <= 8" -{ - int block = (1 << INTVAL (operands[1])) - 1; - int shift = 8 - INTVAL (operands[1]) - INTVAL (operands[2]); - - operands[2] = GEN_INT (block << shift); - return which_alternative == 0 ? "tm\t%0,%b2" : "tmy\t%0,%b2"; -} - [(set_attr "op_type" "SI,SIY")]) - -(define_insn "*tmqidi_ext" - [(set (reg 33) - (compare (zero_extract:DI (match_operand:QI 0 "memory_operand" "Q,S") - (match_operand:SI 1 "const_int_operand" "n,n") - (match_operand:SI 2 "const_int_operand" "n,n")) - (const_int 0)))] - "TARGET_64BIT && s390_match_ccmode(insn, CCTmode) - && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0 - && INTVAL (operands[1]) + INTVAL (operands[2]) <= 8" -{ - int block = (1 << INTVAL (operands[1])) - 1; - int shift = 8 - INTVAL (operands[1]) - INTVAL (operands[2]); - - operands[2] = GEN_INT (block << shift); - return which_alternative == 0 ? "tm\t%0,%b2" : "tmy\t%0,%b2"; -} - [(set_attr "op_type" "SI,SIY")]) - - ; Test-under-Mask instructions -(define_insn "*tmdi_mem" - [(set (reg 33) - (compare (and:DI (match_operand:DI 0 "memory_operand" "Q,S") - (match_operand:DI 1 "immediate_operand" "n,n")) - (match_operand:DI 2 "immediate_operand" "n,n")))] - "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0)) - && s390_single_part (operands[1], DImode, QImode, 0) >= 0" -{ - int part = s390_single_part (operands[1], DImode, QImode, 0); - operands[1] = GEN_INT (s390_extract_part (operands[1], QImode, 0)); - - operands[0] = gen_rtx_MEM (QImode, - plus_constant (XEXP (operands[0], 0), part)); - return which_alternative == 0 ? "tm\t%0,%b1" : "tmy\t%0,%b1"; -} - [(set_attr "op_type" "SI,SIY")]) - -(define_insn "*tmsi_mem" - [(set (reg 33) - (compare (and:SI (match_operand:SI 0 "memory_operand" "Q,S") - (match_operand:SI 1 "immediate_operand" "n,n")) - (match_operand:SI 2 "immediate_operand" "n,n")))] - "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0)) - && s390_single_part (operands[1], SImode, QImode, 0) >= 0" -{ - int part = s390_single_part (operands[1], SImode, QImode, 0); - operands[1] = GEN_INT (s390_extract_part (operands[1], QImode, 0)); - - operands[0] = gen_rtx_MEM (QImode, - plus_constant (XEXP (operands[0], 0), part)); - return which_alternative == 0 ? "tm\t%0,%b1" : "tmy\t%0,%b1"; -} - [(set_attr "op_type" "SI")]) - -(define_insn "*tmhi_mem" - [(set (reg 33) - (compare (and:SI (subreg:SI (match_operand:HI 0 "memory_operand" "Q,S") 0) - (match_operand:SI 1 "immediate_operand" "n,n")) - (match_operand:SI 2 "immediate_operand" "n,n")))] - "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0)) - && s390_single_part (operands[1], HImode, QImode, 0) >= 0" -{ - int part = s390_single_part (operands[1], HImode, QImode, 0); - operands[1] = GEN_INT (s390_extract_part (operands[1], QImode, 0)); - - operands[0] = gen_rtx_MEM (QImode, - plus_constant (XEXP (operands[0], 0), part)); - return which_alternative == 0 ? "tm\t%0,%b1" : "tmy\t%0,%b1"; -} - [(set_attr "op_type" "SI")]) - (define_insn "*tmqi_mem" [(set (reg 33) - (compare (and:SI (subreg:SI (match_operand:QI 0 "memory_operand" "Q,S") 0) - (match_operand:SI 1 "immediate_operand" "n,n")) - (match_operand:SI 2 "immediate_operand" "n,n")))] + (compare (and:QI (match_operand:QI 0 "memory_operand" "Q,S") + (match_operand:QI 1 "immediate_operand" "n,n")) + (match_operand:QI 2 "immediate_operand" "n,n")))] "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))" "@ tm\t%0,%b1 @@ -5196,7 +5050,9 @@ (match_operand:DI 2 "general_operand" "d,m")) (const_int 0))) (clobber (match_scratch:DI 0 "=d,d"))] - "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT" + "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT + /* Do not steal TM patterns. */ + && s390_single_part (operands[2], DImode, HImode, 0) < 0" "@ ngr\t%0,%2 ng\t%0,%2" @@ -5262,7 +5118,9 @@ (match_operand:SI 2 "general_operand" "d,R,T")) (const_int 0))) (clobber (match_scratch:SI 0 "=d,d,d"))] - "s390_match_ccmode(insn, CCTmode)" + "s390_match_ccmode(insn, CCTmode) + /* Do not steal TM patterns. */ + && s390_single_part (operands[2], SImode, HImode, 0) < 0" "@ nr\t%0,%2 n\t%0,%2