From: Uros Bizjak Date: Sun, 22 Nov 2020 21:26:48 +0000 (+0100) Subject: i386: Use SWI48DWI mode iterator for abs and maxmin [PR97873] X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e23f47ec4065e9eec53c4ad9db91bc36a4f90793;p=gcc.git i386: Use SWI48DWI mode iterator for abs and maxmin [PR97873] Generate special double mode sequence also for TImode on 64bit targets. 2020-11-22 Uroš Bizjak PR target/97873 gcc/ * config/i386/i386.md (abs2): Use SWI48DWI mode iterator. (*abs2_doubleword): Use DWIH mode iterator. (3): Use SWI48DWI mode iterator. (*3_doubleword): Use DWIH mode iterator. gcc/testsuite/ * gcc.target/i386/pr97873-2.c: New test. --- diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 2b2ba2f3a20..2beaee5418d 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -10180,9 +10180,9 @@ (define_expand "abs2" [(parallel - [(set (match_operand:SWI48x 0 "register_operand") - (abs:SWI48x - (match_operand:SWI48x 1 "general_operand"))) + [(set (match_operand:SWI48DWI 0 "register_operand") + (abs:SWI48DWI + (match_operand:SWI48DWI 1 "general_operand"))) (clobber (reg:CC FLAGS_REG))])] "TARGET_CMOVE" { @@ -10208,37 +10208,12 @@ } }) -(define_insn_and_split "*abs2_1" - [(set (match_operand:SWI48 0 "register_operand") - (abs:SWI48 - (match_operand:SWI48 1 "general_operand"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_CMOVE && ix86_pre_reload_split ()" - "#" - "&& 1" - [(parallel - [(set (reg:CCGOC FLAGS_REG) - (compare:CCGOC - (neg:SWI48 (match_dup 1)) - (const_int 0))) - (set (match_dup 2) - (neg:SWI48 (match_dup 1)))]) - (set (match_dup 0) - (if_then_else:SWI48 - (ge (reg:CCGOC FLAGS_REG) (const_int 0)) - (match_dup 2) - (match_dup 1)))] -{ - operands[1] = force_reg (mode, operands[1]); - operands[2] = gen_reg_rtx (mode); -}) - -(define_insn_and_split "*absdi2_doubleword" - [(set (match_operand:DI 0 "register_operand") - (abs:DI - (match_operand:DI 1 "general_operand"))) +(define_insn_and_split "*abs2_doubleword" + [(set (match_operand: 0 "register_operand") + (abs: + (match_operand: 1 "general_operand"))) (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && TARGET_CMOVE + "TARGET_CMOVE && ix86_pre_reload_split ()" "#" "&& 1" @@ -10255,25 +10230,51 @@ (parallel [(set (reg:CCGOC FLAGS_REG) (compare:CCGOC - (neg:SI (match_dup 5)) + (neg:DWIH (match_dup 5)) (const_int 0))) (set (match_dup 5) - (neg:SI (match_dup 5)))]) + (neg:DWIH (match_dup 5)))]) (set (match_dup 0) - (if_then_else:SI + (if_then_else:DWIH (ge (reg:CCGOC FLAGS_REG) (const_int 0)) (match_dup 2) (match_dup 1))) (set (match_dup 3) - (if_then_else:SI + (if_then_else:DWIH (ge (reg:CCGOC FLAGS_REG) (const_int 0)) (match_dup 5) (match_dup 4)))] { - operands[1] = force_reg (DImode, operands[1]); - operands[2] = gen_reg_rtx (DImode); + operands[1] = force_reg (mode, operands[1]); + operands[2] = gen_reg_rtx (mode); - split_double_mode (DImode, &operands[0], 3, &operands[0], &operands[3]); + split_double_mode (mode, &operands[0], 3, &operands[0], &operands[3]); +}) + +(define_insn_and_split "*abs2_1" + [(set (match_operand:SWI48 0 "register_operand") + (abs:SWI48 + (match_operand:SWI48 1 "general_operand"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_CMOVE + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(parallel + [(set (reg:CCGOC FLAGS_REG) + (compare:CCGOC + (neg:SWI48 (match_dup 1)) + (const_int 0))) + (set (match_dup 2) + (neg:SWI48 (match_dup 1)))]) + (set (match_dup 0) + (if_then_else:SWI48 + (ge (reg:CCGOC FLAGS_REG) (const_int 0)) + (match_dup 2) + (match_dup 1)))] +{ + operands[1] = force_reg (mode, operands[1]); + operands[2] = gen_reg_rtx (mode); }) (define_expand "tf2" @@ -18966,13 +18967,71 @@ (define_expand "3" [(parallel - [(set (match_operand:SWI48x 0 "register_operand") - (maxmin:SWI48x - (match_operand:SWI48x 1 "register_operand") - (match_operand:SWI48x 2 "general_operand"))) + [(set (match_operand:SWI48DWI 0 "register_operand") + (maxmin:SWI48DWI + (match_operand:SWI48DWI 1 "register_operand") + (match_operand:SWI48DWI 2 "general_operand"))) (clobber (reg:CC FLAGS_REG))])] "TARGET_CMOVE") +(define_insn_and_split "*3_doubleword" + [(set (match_operand: 0 "register_operand") + (maxmin: + (match_operand: 1 "register_operand") + (match_operand: 2 "general_operand"))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_CMOVE + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(set (match_dup 0) + (if_then_else:DWIH (match_dup 6) + (match_dup 1) + (match_dup 2))) + (set (match_dup 3) + (if_then_else:DWIH (match_dup 6) + (match_dup 4) + (match_dup 5)))] +{ + operands[2] = force_reg (mode, operands[2]); + + split_double_mode (mode, &operands[0], 3, &operands[0], &operands[3]); + + rtx cmplo[2] = { operands[1], operands[2] }; + rtx cmphi[2] = { operands[4], operands[5] }; + + enum rtx_code code = ; + + switch (code) + { + case LE: case LEU: + std::swap (cmplo[0], cmplo[1]); + std::swap (cmphi[0], cmphi[1]); + code = swap_condition (code); + /* FALLTHRU */ + + case GE: case GEU: + { + bool uns = (code == GEU); + rtx (*sbb_insn) (machine_mode, rtx, rtx, rtx) + = uns ? gen_sub3_carry_ccc : gen_sub3_carry_ccgz; + + emit_insn (gen_cmp_1 (mode, cmplo[0], cmplo[1])); + + rtx tmp = gen_rtx_SCRATCH (mode); + emit_insn (sbb_insn (mode, tmp, cmphi[0], cmphi[1])); + + rtx flags = gen_rtx_REG (uns ? CCCmode : CCGZmode, FLAGS_REG); + operands[6] = gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx); + + break; + } + + default: + gcc_unreachable (); + } +}) + (define_insn_and_split "*3_1" [(set (match_operand:SWI48 0 "register_operand") (maxmin:SWI48 @@ -19027,63 +19086,6 @@ operands[3] = gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx); }) -(define_insn_and_split "*di3_doubleword" - [(set (match_operand:DI 0 "register_operand") - (maxmin:DI (match_operand:DI 1 "register_operand") - (match_operand:DI 2 "general_operand"))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && TARGET_CMOVE - && ix86_pre_reload_split ()" - "#" - "&& 1" - [(set (match_dup 0) - (if_then_else:SI (match_dup 6) - (match_dup 1) - (match_dup 2))) - (set (match_dup 3) - (if_then_else:SI (match_dup 6) - (match_dup 4) - (match_dup 5)))] -{ - operands[2] = force_reg (DImode, operands[2]); - - split_double_mode (DImode, &operands[0], 3, &operands[0], &operands[3]); - - rtx cmplo[2] = { operands[1], operands[2] }; - rtx cmphi[2] = { operands[4], operands[5] }; - - enum rtx_code code = ; - - switch (code) - { - case LE: case LEU: - std::swap (cmplo[0], cmplo[1]); - std::swap (cmphi[0], cmphi[1]); - code = swap_condition (code); - /* FALLTHRU */ - - case GE: case GEU: - { - bool uns = (code == GEU); - rtx (*sbb_insn) (machine_mode, rtx, rtx, rtx) - = uns ? gen_sub3_carry_ccc : gen_sub3_carry_ccgz; - - emit_insn (gen_cmp_1 (SImode, cmplo[0], cmplo[1])); - - rtx tmp = gen_rtx_SCRATCH (SImode); - emit_insn (sbb_insn (SImode, tmp, cmphi[0], cmphi[1])); - - rtx flags = gen_rtx_REG (uns ? CCCmode : CCGZmode, FLAGS_REG); - operands[6] = gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx); - - break; - } - - default: - gcc_unreachable (); - } -}) - ;; Avoid clearing a register between a flags setting comparison and its use, ;; i.e. prefer "xorl %eax,%eax; test/cmp" over "test/cmp; movl $0, %eax". (define_peephole2 diff --git a/gcc/testsuite/gcc.target/i386/pr97873-2.c b/gcc/testsuite/gcc.target/i386/pr97873-2.c new file mode 100644 index 00000000000..22519ab5af6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr97873-2.c @@ -0,0 +1,23 @@ +/* PR target/97873 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -msse2 -mno-sse3 -mtune=generic" } */ + +#ifdef __SIZEOF_INT128__ +typedef __int128_t T; +#else +typedef long long T; +#endif + +T test_abs (T x) +{ + return (x < 0) ? -x : x; +} + +/* { dg-final { scan-assembler "adc" } } */ + +T test_smin (T x, T y) +{ + return (x < y) ? x : y; +} + +/* { dg-final { scan-assembler "sbb" } } */