This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: compare instructions
- From: Jan Hubicka <jh at suse dot cz>
- To: Dmitry <diwil at eis dot ru>
- Cc: gcc at gcc dot gnu dot org
- Date: Sat, 26 Jan 2002 00:34:27 +0100
- Subject: Re: compare instructions
- References: <20020125114122.6bc16663.diwil@eis.ru>
> Fellows,
>
> Is there something wrong:
>
> (define_expand "tstsi_for_zero_const"
> [(set (cc0) (and:SI (match_operand:SI 0 "nonimmediate_operand" "")
> (match_operand:SI 1 "immediate_operand" "")))]
> ""
> "")
>
> (define_insn "*tstsi_for_zero_const"
> [(set (cc0) (and:SI (match_operand:SI 0 "nonimmediate_operand" "rm")
> (match_operand:SI 1 "immediate_operand" "i")))]
> ""
> "this_is_a_test %0,%1"
> [(set_attr "length" "2")
> (set_attr "cc" "compare")])
>
>
> I suggest, that this expander will suit:
>
> if( a&CONST ) {...}
>
> where 'a' has SImode.
>
> But the compiler fails to pick up 'tstsi_for_zero_const' defenition.
The combiner is attempting to be smart here and construct often different
form of patterns. One of ways to figure out what is to insert debug_rtx
into recog_for_combine function. i386.md has following code:
;; Combine likes to form bit extractions for some tests. Humor it.
(define_insn "*testqi_ext_3"
[(set (reg 17)
(compare (zero_extract:SI
(match_operand 0 "nonimmediate_operand" "rm")
(match_operand:SI 1 "const_int_operand" "")
(match_operand:SI 2 "const_int_operand" ""))
(const_int 0)))]
"ix86_match_ccmode (insn, CCNOmode)
&& (GET_MODE (operands[0]) == SImode
|| (TARGET_64BIT && GET_MODE (operands[0]) == DImode)
|| GET_MODE (operands[0]) == HImode
|| GET_MODE (operands[0]) == QImode)"
"#")
(define_insn "*testqi_ext_3_rex64"
[(set (reg 17)
(compare (zero_extract:DI
(match_operand 0 "nonimmediate_operand" "rm")
(match_operand:DI 1 "const_int_operand" "")
(match_operand:DI 2 "const_int_operand" ""))
(const_int 0)))]
"TARGET_64BIT
&& ix86_match_ccmode (insn, CCNOmode)
/* The code below cannot deal with constants outside HOST_WIDE_INT. */
&& INTVAL (operands[1]) + INTVAL (operands[2]) < HOST_BITS_PER_WIDE_INT
/* Ensure that resulting mask is zero or sign extended operand. */
&& (INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
|| (INTVAL (operands[1]) + INTVAL (operands[2]) == 64
&& INTVAL (operands[1]) > 32))
&& (GET_MODE (operands[0]) == SImode
|| GET_MODE (operands[0]) == DImode
|| GET_MODE (operands[0]) == HImode
|| GET_MODE (operands[0]) == QImode)"
"#")
(define_split
[(set (reg 17)
(compare (zero_extract
(match_operand 0 "nonimmediate_operand" "")
(match_operand 1 "const_int_operand" "")
(match_operand 2 "const_int_operand" ""))
(const_int 0)))]
"ix86_match_ccmode (insn, CCNOmode)"
[(set (reg:CCNO 17) (compare:CCNO (match_dup 3) (const_int 0)))]
{
HOST_WIDE_INT len = INTVAL (operands[1]);
HOST_WIDE_INT pos = INTVAL (operands[2]);
HOST_WIDE_INT mask;
enum machine_mode mode, submode;
mode = GET_MODE (operands[0]);
if (GET_CODE (operands[0]) == MEM)
{
/* ??? Combine likes to put non-volatile mem extractions in QImode
no matter the size of the test. So find a mode that works. */
if (! MEM_VOLATILE_P (operands[0]))
{
mode = smallest_mode_for_size (pos + len, MODE_INT);
operands[0] = adjust_address (operands[0], mode, 0);
}
}
else if (GET_CODE (operands[0]) == SUBREG
&& (submode = GET_MODE (SUBREG_REG (operands[0])),
GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (submode))
&& pos + len <= GET_MODE_BITSIZE (submode))
{
/* Narrow a paradoxical subreg to prevent partial register stalls. */
mode = submode;
operands[0] = SUBREG_REG (operands[0]);
}
else if (mode == HImode && pos + len <= 8)
{
/* Small HImode tests can be converted to QImode. */
mode = QImode;
operands[0] = gen_lowpart (QImode, operands[0]);
}
mask = ((HOST_WIDE_INT)1 << (pos + len)) - 1;
mask &= ~(((HOST_WIDE_INT)1 << pos) - 1);
operands[3] = gen_rtx_AND (mode, operands[0],
GEN_INT (trunc_int_for_mode (mask, mode)));
})
I guess you need something similar.