Attached patch converts a bunch of indirect function calls to use generic gen_{add2,sub3,extend}_insn functions. The patch corrects and<mode>3 expander, which generated invalid RTX (non-existent QI/HImode->DImode extend instructions for 32bit STV targets), so fake insn-and-split patterns were necessary. The new approach is to leave DImode and instructions up to STV pass, and split them just before register allocation to zero-extends.
2019-06-13 Uroš Bizjak <ubiz...@gmail.com> * config/i386/i386.md (SWIM1248s): Rename from SWIM1248x. Update all uses. (and<mode>3): Use gen_extend_insn instead of indirect functions. Do not generate DImode extends for 32bit targets. (and->zext post-reload splitter): Use gen_extend_insn instead of indirect functions. (anddi->zext pre-reload splitter): New. (*zext<mode>_doubleword_and): Remove. (*zext<mode>_doubleword): Ditto. (*zextsi_doubleword): Dittto. 2019-06-13 Uroš Bizjak <ubiz...@gmail.com> * config/i386/i386-expand.c (ix86_expand_int_sse_cmp): Use gen_sub3_insn instead of indirect function. (ix86_expand_ashl_const): Use gen_add2_insn instead of indirect function. (ix86_adjust_counter): Ditto. Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Committed to mainline SVN. Uros.
diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c index 0585c7d08bd0..770106162fb0 100644 --- a/gcc/config/i386/i386-expand.c +++ b/gcc/config/i386/i386-expand.c @@ -4303,27 +4303,15 @@ ix86_expand_int_sse_cmp (rtx dest, enum rtx_code code, rtx cop0, rtx cop1, case E_V2DImode: { rtx t1, t2, mask; - rtx (*gen_sub3) (rtx, rtx, rtx); - switch (mode) - { - case E_V16SImode: gen_sub3 = gen_subv16si3; break; - case E_V8DImode: gen_sub3 = gen_subv8di3; break; - case E_V8SImode: gen_sub3 = gen_subv8si3; break; - case E_V4DImode: gen_sub3 = gen_subv4di3; break; - case E_V4SImode: gen_sub3 = gen_subv4si3; break; - case E_V2DImode: gen_sub3 = gen_subv2di3; break; - default: - gcc_unreachable (); - } /* Subtract (-(INT MAX) - 1) from both operands to make them signed. */ mask = ix86_build_signbit_mask (mode, true, false); t1 = gen_reg_rtx (mode); - emit_insn (gen_sub3 (t1, cop0, mask)); + emit_insn (gen_sub3_insn (t1, cop0, mask)); t2 = gen_reg_rtx (mode); - emit_insn (gen_sub3 (t2, cop1, mask)); + emit_insn (gen_sub3_insn (t2, cop1, mask)); cop0 = t1; cop1 = t2; @@ -4339,9 +4327,8 @@ ix86_expand_int_sse_cmp (rtx dest, enum rtx_code code, rtx cop0, rtx cop1, case E_V8HImode: /* Perform a parallel unsigned saturating subtraction. */ x = gen_reg_rtx (mode); - emit_insn (gen_rtx_SET (x, gen_rtx_US_MINUS (mode, cop0, - cop1))); - + emit_insn (gen_rtx_SET + (x, gen_rtx_US_MINUS (mode, cop0, cop1))); cop0 = x; cop1 = CONST0_RTX (mode); code = EQ; @@ -5562,18 +5549,17 @@ ix86_split_long_move (rtx operands[]) static void ix86_expand_ashl_const (rtx operand, int count, machine_mode mode) { - rtx (*insn)(rtx, rtx, rtx); - if (count == 1 || (count * ix86_cost->add <= ix86_cost->shift_const && !optimize_insn_for_size_p ())) { - insn = mode == DImode ? gen_addsi3 : gen_adddi3; while (count-- > 0) - emit_insn (insn (operand, operand, operand)); + emit_insn (gen_add2_insn (operand, operand)); } else { + rtx (*insn)(rtx, rtx, rtx); + insn = mode == DImode ? gen_ashlsi3 : gen_ashldi3; emit_insn (insn (operand, operand, GEN_INT (count))); } @@ -6506,10 +6492,7 @@ expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx vec_value, static void ix86_adjust_counter (rtx countreg, HOST_WIDE_INT value) { - rtx (*gen_add)(rtx, rtx, rtx) - = GET_MODE (countreg) == DImode ? gen_adddi3 : gen_addsi3; - - emit_insn (gen_add (countreg, countreg, GEN_INT (-value))); + emit_insn (gen_add2_insn (countreg, GEN_INT (-value))); } /* Depending on ISSETMEM, copy enough from SRCMEM to DESTMEM or set enough to diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 01338e294ab4..b484caebc453 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1018,10 +1018,11 @@ (HI "TARGET_HIMODE_MATH") SI]) -;; Math-dependant integer modes with DImode. -(define_mode_iterator SWIM1248x [(QI "TARGET_QIMODE_MATH") - (HI "TARGET_HIMODE_MATH") - SI (DI "(TARGET_STV && TARGET_SSE2) || TARGET_64BIT")]) +;; Math-dependant integer modes with DImode (enabled for 32bit with STV). +(define_mode_iterator SWIM1248s + [(QI "TARGET_QIMODE_MATH") + (HI "TARGET_HIMODE_MATH") + SI (DI "TARGET_64BIT || (TARGET_STV && TARGET_SSE2)")]) ;; Math-dependant single word integer modes without QImode. (define_mode_iterator SWIM248 [(HI "TARGET_HIMODE_MATH") @@ -4076,45 +4077,6 @@ [(set_attr "isa" "*,avx512dq,avx512dq") (set_attr "type" "imovx,mskmov,mskmov") (set_attr "mode" "SI,QI,QI")]) - -(define_insn_and_split "*zext<mode>_doubleword_and" - [(set (match_operand:DI 0 "register_operand" "=&<r>") - (zero_extend:DI (match_operand:SWI12 1 "nonimmediate_operand" "<r>m")))] - "!TARGET_64BIT && TARGET_STV && TARGET_SSE2 - && TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun)" - "#" - "&& reload_completed && GENERAL_REG_P (operands[0])" - [(set (match_dup 2) (const_int 0))] -{ - split_double_mode (DImode, &operands[0], 1, &operands[0], &operands[2]); - - emit_move_insn (operands[0], const0_rtx); - - gcc_assert (!TARGET_PARTIAL_REG_STALL); - emit_insn (gen_movstrict<mode> - (gen_lowpart (<MODE>mode, operands[0]), operands[1])); -}) - -(define_insn_and_split "*zext<mode>_doubleword" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (match_operand:SWI12 1 "nonimmediate_operand" "<r>m")))] - "!TARGET_64BIT && TARGET_STV && TARGET_SSE2 - && !(TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun))" - "#" - "&& reload_completed && GENERAL_REG_P (operands[0])" - [(set (match_dup 0) (zero_extend:SI (match_dup 1))) - (set (match_dup 2) (const_int 0))] - "split_double_mode (DImode, &operands[0], 1, &operands[0], &operands[2]);") - -(define_insn_and_split "*zextsi_doubleword" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm")))] - "!TARGET_64BIT && TARGET_STV && TARGET_SSE2" - "#" - "&& reload_completed && GENERAL_REG_P (operands[0])" - [(set (match_dup 0) (match_dup 1)) - (set (match_dup 2) (const_int 0))] - "split_double_mode (DImode, &operands[0], 1, &operands[0], &operands[2]);") ;; Sign extension instructions @@ -8394,48 +8356,34 @@ ;; it should be done with splitters. (define_expand "and<mode>3" - [(set (match_operand:SWIM1248x 0 "nonimmediate_operand") - (and:SWIM1248x (match_operand:SWIM1248x 1 "nonimmediate_operand") - (match_operand:SWIM1248x 2 "<general_szext_operand>")))] + [(set (match_operand:SWIM1248s 0 "nonimmediate_operand") + (and:SWIM1248s (match_operand:SWIM1248s 1 "nonimmediate_operand") + (match_operand:SWIM1248s 2 "<general_szext_operand>")))] "" { machine_mode mode = <MODE>mode; - rtx (*insn) (rtx, rtx); - if (CONST_INT_P (operands[2]) && REG_P (operands[0])) + if (<MODE>mode == DImode && !TARGET_64BIT) + ; + else if (CONST_INT_P (operands[2]) && REG_P (operands[0])) { - HOST_WIDE_INT ival = INTVAL (operands[2]); + unsigned HOST_WIDE_INT ival = UINTVAL (operands[2]); - if (ival == (HOST_WIDE_INT) 0xffffffff) + if (ival == GET_MODE_MASK (SImode)) mode = SImode; - else if (ival == 0xffff) + else if (ival == GET_MODE_MASK (HImode)) mode = HImode; - else if (ival == 0xff) + else if (ival == GET_MODE_MASK (QImode)) mode = QImode; - } - - if (mode == <MODE>mode) - { - ix86_expand_binary_operator (AND, <MODE>mode, operands); - DONE; } - if (<MODE>mode == DImode) - insn = (mode == SImode) - ? gen_zero_extendsidi2 - : (mode == HImode) - ? gen_zero_extendhidi2 - : gen_zero_extendqidi2; - else if (<MODE>mode == SImode) - insn = (mode == HImode) - ? gen_zero_extendhisi2 - : gen_zero_extendqisi2; - else if (<MODE>mode == HImode) - insn = gen_zero_extendqihi2; + if (mode != <MODE>mode) + emit_insn (gen_extend_insn + (operands[0], gen_lowpart (mode, operands[1]), + <MODE>mode, mode, 1)); else - gcc_unreachable (); + ix86_expand_binary_operator (AND, <MODE>mode, operands); - emit_insn (insn (operands[0], gen_lowpart (mode, operands[1]))); DONE; }) @@ -8471,6 +8419,40 @@ DONE; }) +(define_split + [(set (match_operand:DI 0 "register_operand") + (and:DI + (match_operand:DI 1 "nonimmediate_operand") + (match_operand:DI 2 "const_int_operand"))) + (clobber (reg:CC FLAGS_REG))] + "!TARGET_64BIT && TARGET_STV && TARGET_SSE2 + && can_create_pseudo_p ()" + [(const_int 0)] +{ + unsigned HOST_WIDE_INT ival = UINTVAL (operands[2]); + machine_mode mode; + + if (ival == GET_MODE_MASK (SImode)) + mode = SImode; + else if (ival == GET_MODE_MASK (HImode)) + mode = HImode; + else if (ival == GET_MODE_MASK (QImode)) + mode = QImode; + else + FAIL; + + split_double_mode (DImode, &operands[0], 3, &operands[0], &operands[3]); + + if (mode == SImode) + emit_move_insn (operands[0], operands[1]); + else + emit_insn (gen_extend_insn + (operands[0], gen_lowpart (mode, operands[1]), + SImode, mode, 1)); + emit_move_insn (operands[3], const0_rtx); + DONE; +}) + (define_insn "*anddi_1" [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r,r") (and:DI @@ -8617,37 +8599,25 @@ || REGNO (operands[0]) != REGNO (operands[1]))" [(const_int 0)] { - HOST_WIDE_INT ival = INTVAL (operands[2]); + unsigned HOST_WIDE_INT ival = UINTVAL (operands[2]); machine_mode mode; - rtx (*insn) (rtx, rtx); - if (ival == (HOST_WIDE_INT) 0xffffffff) + if (ival == GET_MODE_MASK (SImode)) mode = SImode; - else if (ival == 0xffff) + else if (ival == GET_MODE_MASK (HImode)) mode = HImode; + else if (ival == GET_MODE_MASK (QImode)) + mode = QImode; else - { - gcc_assert (ival == 0xff); - mode = QImode; - } + gcc_unreachable (); - if (<MODE>mode == DImode) - insn = (mode == SImode) - ? gen_zero_extendsidi2 - : (mode == HImode) - ? gen_zero_extendhidi2 - : gen_zero_extendqidi2; - else - { - if (<MODE>mode != SImode) - /* Zero extend to SImode to avoid partial register stalls. */ - operands[0] = gen_lowpart (SImode, operands[0]); + /* Zero extend to SImode to avoid partial register stalls. */ + if (<MODE_SIZE> < GET_MODE_SIZE (SImode)) + operands[0] = gen_lowpart (SImode, operands[0]); - insn = (mode == HImode) - ? gen_zero_extendhisi2 - : gen_zero_extendqisi2; - } - emit_insn (insn (operands[0], gen_lowpart (mode, operands[1]))); + emit_insn (gen_extend_insn + (operands[0], gen_lowpart (mode, operands[1]), + GET_MODE (operands[0]), mode, 1)); DONE; }) @@ -9003,9 +8973,9 @@ ;; If this is considered useful, it should be done with splitters. (define_expand "<code><mode>3" - [(set (match_operand:SWIM1248x 0 "nonimmediate_operand") - (any_or:SWIM1248x (match_operand:SWIM1248x 1 "nonimmediate_operand") - (match_operand:SWIM1248x 2 "<general_operand>")))] + [(set (match_operand:SWIM1248s 0 "nonimmediate_operand") + (any_or:SWIM1248s (match_operand:SWIM1248s 1 "nonimmediate_operand") + (match_operand:SWIM1248s 2 "<general_operand>")))] "" "ix86_expand_binary_operator (<CODE>, <MODE>mode, operands); DONE;") @@ -9697,8 +9667,8 @@ ;; One complement instructions (define_expand "one_cmpl<mode>2" - [(set (match_operand:SWIM1248x 0 "nonimmediate_operand") - (not:SWIM1248x (match_operand:SWIM1248x 1 "nonimmediate_operand")))] + [(set (match_operand:SWIM1248s 0 "nonimmediate_operand") + (not:SWIM1248s (match_operand:SWIM1248s 1 "nonimmediate_operand")))] "" "ix86_expand_unary_operator (NOT, <MODE>mode, operands); DONE;")