Commit 68f9c5e2 by Ulrich Weigand Committed by Ulrich Weigand

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
parent 22116d84
2004-08-10 Ulrich Weigand <uweigand@de.ibm.com>
* 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 <hongjiu.lu@intel.com> 2004-08-10 H.J. Lu <hongjiu.lu@intel.com>
PR target/16909 PR target/16909
......
...@@ -50,6 +50,7 @@ extern int tls_symbolic_operand (rtx); ...@@ -50,6 +50,7 @@ extern int tls_symbolic_operand (rtx);
extern int s390_match_ccmode (rtx, enum machine_mode); extern int s390_match_ccmode (rtx, enum machine_mode);
extern enum machine_mode s390_tm_ccmode (rtx, rtx, int); extern enum machine_mode s390_tm_ccmode (rtx, rtx, int);
extern enum machine_mode s390_select_ccmode (enum rtx_code, rtx, rtx); 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_alc_comparison (rtx op, enum machine_mode mode);
extern int s390_slb_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); extern rtx s390_emit_compare (enum rtx_code, rtx, rtx);
......
...@@ -474,6 +474,87 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1) ...@@ -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 /* Emit a compare instruction suitable to implement the comparison
OP0 CODE OP1. Return the correct condition RTL to be placed in OP0 CODE OP1. Return the correct condition RTL to be placed in
the IF_THEN_ELSE of the conditional branch testing the result. */ the IF_THEN_ELSE of the conditional branch testing the result. */
......
...@@ -813,6 +813,10 @@ CUMULATIVE_ARGS; ...@@ -813,6 +813,10 @@ CUMULATIVE_ARGS;
return the mode to be used for the comparison. */ return the mode to be used for the comparison. */
#define SELECT_CC_MODE(OP, X, Y) s390_select_ccmode ((OP), (X), (Y)) #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 /* 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 stored from the compare operation. Note that we can't use "rtx" here
since it hasn't been defined! */ since it hasn't been defined! */
......
...@@ -286,159 +286,13 @@ ...@@ -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 ; 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" (define_insn "*tmqi_mem"
[(set (reg 33) [(set (reg 33)
(compare (and:SI (subreg:SI (match_operand:QI 0 "memory_operand" "Q,S") 0) (compare (and:QI (match_operand:QI 0 "memory_operand" "Q,S")
(match_operand:SI 1 "immediate_operand" "n,n")) (match_operand:QI 1 "immediate_operand" "n,n"))
(match_operand:SI 2 "immediate_operand" "n,n")))] (match_operand:QI 2 "immediate_operand" "n,n")))]
"s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))" "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))"
"@ "@
tm\t%0,%b1 tm\t%0,%b1
...@@ -5196,7 +5050,9 @@ ...@@ -5196,7 +5050,9 @@
(match_operand:DI 2 "general_operand" "d,m")) (match_operand:DI 2 "general_operand" "d,m"))
(const_int 0))) (const_int 0)))
(clobber (match_scratch:DI 0 "=d,d"))] (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 ngr\t%0,%2
ng\t%0,%2" ng\t%0,%2"
...@@ -5262,7 +5118,9 @@ ...@@ -5262,7 +5118,9 @@
(match_operand:SI 2 "general_operand" "d,R,T")) (match_operand:SI 2 "general_operand" "d,R,T"))
(const_int 0))) (const_int 0)))
(clobber (match_scratch:SI 0 "=d,d,d"))] (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 nr\t%0,%2
n\t%0,%2 n\t%0,%2
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment