From 1bd906a3a94bb5d5420280fe4dd4878e34eac6b8 Mon Sep 17 00:00:00 2001 From: jakub Date: Tue, 31 May 2011 19:12:25 +0000 Subject: [PATCH] PR target/48688 * config/i386/i386.md (*lea_general_4): New define_insn_and_split. * gcc.target/i386/pr48688.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@174507 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 5 +++++ gcc/config/i386/i386.md | 34 +++++++++++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gcc.target/i386/pr48688.c | 24 +++++++++++++++++++++++ 4 files changed, 68 insertions(+) create mode 100644 gcc/testsuite/gcc.target/i386/pr48688.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2ddaf65493f..0c6454076d7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2011-05-31 Jakub Jelinek + + PR target/48688 + * config/i386/i386.md (*lea_general_4): New define_insn_and_split. + 2011-05-31 Uros Bizjak * config/i386/i386.md: Use SWI248x instead of X87MODEI, SWI24 instead diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 056d3c9686a..6032924d66a 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -6413,6 +6413,40 @@ } [(set_attr "type" "lea") (set_attr "mode" "SI")]) + +(define_insn_and_split "*lea_general_4" + [(set (match_operand:SWI 0 "register_operand" "=r") + (any_or:SWI (ashift:SWI (match_operand:SWI 1 "index_register_operand" "l") + (match_operand:SWI 2 "const_int_operand" "n")) + (match_operand 3 "const_int_operand" "n")))] + "(mode == DImode + || mode == SImode + || !TARGET_PARTIAL_REG_STALL + || optimize_function_for_size_p (cfun)) + && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) - 1 < 3 + && ((unsigned HOST_WIDE_INT) INTVAL (operands[3]) + <= ((unsigned HOST_WIDE_INT) 1 << INTVAL (operands[2])))" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rtx pat; + if (mode != DImode) + operands[0] = gen_lowpart (SImode, operands[0]); + operands[1] = gen_lowpart (Pmode, operands[1]); + operands[2] = GEN_INT (1 << INTVAL (operands[2])); + pat = plus_constant (gen_rtx_MULT (Pmode, operands[1], operands[2]), + INTVAL (operands[3])); + if (Pmode != SImode && mode != DImode) + pat = gen_rtx_SUBREG (SImode, pat, 0); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat)); + DONE; +} + [(set_attr "type" "lea") + (set (attr "mode") + (if_then_else (eq (symbol_ref "mode == DImode") (const_int 0)) + (const_string "SI") + (const_string "DI")))]) ;; Subtract instructions diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 10a41bd30d9..dea716252ed 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-05-31 Jakub Jelinek + + PR target/48688 + * gcc.target/i386/pr48688.c: New test. + 2010-11-15 Fabien ChĂȘne PR c++/48010 diff --git a/gcc/testsuite/gcc.target/i386/pr48688.c b/gcc/testsuite/gcc.target/i386/pr48688.c new file mode 100644 index 00000000000..f4d663a210b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr48688.c @@ -0,0 +1,24 @@ +/* PR target/48688 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int fn1 (int x) { return (x << 3) | 5; } +int fn2 (int x) { return (x * 8) | 5; } +int fn3 (int x) { return (x << 3) + 5; } +int fn4 (int x) { return (x * 8) + 5; } +int fn5 (int x) { return (x << 3) ^ 5; } +int fn6 (int x) { return (x * 8) ^ 5; } +long fn7 (long x) { return (x << 3) | 5; } +long fn8 (long x) { return (x * 8) | 5; } +long fn9 (long x) { return (x << 3) + 5; } +long fn10 (long x) { return (x * 8) + 5; } +long fn11 (long x) { return (x << 3) ^ 5; } +long fn12 (long x) { return (x * 8) ^ 5; } +long fn13 (unsigned x) { return (x << 3) | 5; } +long fn14 (unsigned x) { return (x * 8) | 5; } +long fn15 (unsigned x) { return (x << 3) + 5; } +long fn16 (unsigned x) { return (x * 8) + 5; } +long fn17 (unsigned x) { return (x << 3) ^ 5; } +long fn18 (unsigned x) { return (x * 8) ^ 5; } + +/* { dg-final { scan-assembler-not "\[ \t\]x?or\[bwlq\]\[ \t\]" } } */ -- 2.11.4.GIT