This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: compare instructions


> 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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]