On Mon, Mar 25, 2013 at 2:35 AM, Richard Biener <richard.guent...@gmail.com> wrote: > On Sun, Mar 24, 2013 at 5:18 AM, Wei Mi <w...@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.