This is the mail archive of the gcc-patches@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]

[PATCH, i386]: Truncate shift count


Hello!

SHIFT_COUNT_TRUNCATED can't be used on i386 (see comment in
gccint.info) and TARGET_SHIFT_TRUNCATION mask is not effective for
some reason on attached testcase. To remove unnecessary and
instructions on shift count, let's implement approach, proposed in the
documentation:

<quote>
     However, on some machines, such as the 80386 and the 680x0,
     truncation only applies to shift operations and not the (real or
     pretended) bit-field operations.  Define `SHIFT_COUNT_TRUNCATED'
     to be zero on such machines.  Instead, add patterns to the `md'
     file that include the implied truncation of the shift instructions.
</quote>

So, we add:

(define_insn_and_split "*ashl<mode>3_mask"
  [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm")
	(ashift:SWI48
	  (match_operand:SWI48 1 "nonimmediate_operand" "0")
	  (subreg:QI
	    (and:SI
	      (match_operand:SI 2 "register_operand" "c")
	      (match_operand:SI 3 "const_int_operand" "n")) 0)))
   (clobber (reg:CC FLAGS_REG))]
  "ix86_binary_operator_ok (ASHIFT, <MODE>mode, operands)
   && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode)-1))
      == GET_MODE_BITSIZE (<MODE>mode)-1"
  "#"
  "&& 1"
  [(parallel [(set (match_dup 0)
		   (ashift:SWI48 (match_dup 1) (match_dup 2)))
	      (clobber (reg:CC FLAGS_REG))])]
  "operands[2] = simplify_gen_subreg (QImode, operands[2], SImode, 0);"
  [(set_attr "type" "ishift")
   (set_attr "mode" "<MODE>")])

And similar patterns for other shifts/rotates.

The above pattern is effective for both, SImode and DImode shifts,
since for both modes, combine always generate QImode subregs of SImode
ANDs. I didn't manage to generate a HImode or QImode shift, the shift
has always been promoted to SImode, so I have left them out. Also
note, that ..._cmp version of the shift (that also sets flag register)
operates only with constant shift arguments [see comments in i386.md
about flags and shift-by-zero functionality], so this new pattern
(that operates with variable shift argument exclusively) can't
interfere with ..._cmp versions in any way.

2010-10-01  Uros Bizjak  <ubizjak@gmail.com>

	* config/i386/i386.md (*ashl<mode>3_mask): New insn_and_split pattern.
	(*<shiftrt_insn><mode>3_mask): Ditto.
	(*<rotate_insn><mode>3_mask): Ditto.

testsuite/ChangeLog:

2010-10-01  Uros Bizjak  <ubizjak@gmail.com>

	* gcc.target/i386/shift_mask.c: New test.

Patch was regression tested on x86_64-pc-linux-gnu {,-m32} and
committed to mainline.

Uros.

Attachment: p.diff.txt
Description: Text document


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