extend fwprop optimization

Wei Mi wmi@google.com
Mon Mar 25 17:29:00 GMT 2013


On Mon, Mar 25, 2013 at 2:35 AM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Sun, Mar 24, 2013 at 5:18 AM, Wei Mi <wmi@google.com> wrote:
>> This is the patch to add the shift truncation in
>> simplify_binary_operation_1. I add a new hook
>> TARGET_SHIFT_COUNT_TRUNCATED which uses enum rtx_code to decide
>> whether we can do shift truncation. I didn't use
>> TARGET_SHIFT_TRUNCATION_MASK in simplify_binary_operation_1 because it
>> uses the macro SHIFT_COUNT_TRUNCATED. If I change
>> SHIFT_COUNT_TRUNCATED to targetm.shift_count_truncated in
>> TARGET_SHIFT_TRUNCATION_MASK, I need to give
>> TARGET_SHIFT_TRUNCATION_MASK a enum rtx_code param, which wasn't
>> trivial to get at many places in existing code.
>>
>> patch.1 ~ patch.4 pass regression and bootstrap on x86_64-unknown-linux-gnu.
>
> Doing this might prove dangerous in case some pass may later decide
> to use an instruction that behaves in different ways.  Consider
>
>    tem = 1<< (n & 255);   // count truncated
>    x = y & tem;  // bittest instruction bit nr _not_ truncated
>
> so if tem is expanded to use a shift instruction which truncates the shift
> count the explicit and is dropped.  If later combine comes around and
> combines the bit-test to use the bittest instruction which does not
> implicitely truncate the cound you have generated wrong-code.
>

So it means the existing truncation pattern defined in insn split is
also incorrect because the truncated shift may be combined into a bit
test pattern?

// The following define_insn_and_split will do shift truncation.
(define_insn_and_split "*<shift_insn><mode>3_mask"
  [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm")
        (any_shiftrt:SWI48
          (match_operand:SWI48 1 "nonimmediate_operand" "0")
          (subreg:QI
            (and:SI
              (match_operand:SI 2 "nonimmediate_operand" "c")
              (match_operand:SI 3 "const_int_operand" "n")) 0)))
   (clobber (reg:CC FLAGS_REG))]
  "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)
   && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode)-1))
      == GET_MODE_BITSIZE (<MODE>mode)-1"
  "#"
  "&& 1"
  [(parallel [(set (match_dup 0)
                   (any_shiftrt:SWI48 (match_dup 1) (match_dup 2)))
              (clobber (reg:CC FLAGS_REG))])]
{
  if (can_create_pseudo_p ())
    operands [2] = force_reg (SImode, operands[2]);

  operands[2] = simplify_gen_subreg (QImode, operands[2], SImode, 0);
}
  [(set_attr "type" "ishift")
   (set_attr "mode" "<MODE>")])

> So we need to make sure any explicit truncation originally in place
> is kept in the RTL - which means SHIFT_COUNT_TRUNCATED should
> not exist at all, but instead there would be two patterns for shifts
> with implicit truncation - one involving the truncation (canonicalized to
> bitwise and) and one not involving the truncation.
>
> Richard.
>

I am trying to figure out a way not to lose the opportunity when shift
truncation is not combined in a bit test pattern. Can we keep the
explicit truncation in RTL, but generate truncation code in assembly?
Then only shift truncation which not combined in a bit test
pattershift truncationn will happen.

(define_insn "*<shift_insn_and><mode>"
  [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm")
        (any_shiftrt:SWI48
          (match_operand:SWI48 1 "nonimmediate_operand" "0")
          (subreg:QI
            (and:SI
              (match_operand:SI 2 "nonimmediate_operand" "c")
              (match_operand:SI 3 "const_int_operand" "n")) 0)))
   (clobber (reg:CC FLAGS_REG))]
  "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
{
   if ((INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode)-1))
      == GET_MODE_BITSIZE (<MODE>mode)-1)
      return "and\t{%3, %2|%2, %3}\n\r shift\t{%b2, %0|%0, %b2}";
   else
      "shift\t{%2, %0|%0, %2}";
}

Thanks,
Wei.



More information about the Gcc-patches mailing list