For MEM, rtx_cost iterates each subrtx, and adds up the costs, so for MEM (reg) and MEM (reg + 4), the former costs 5, the latter costs 9, it is not accurate for x86. Ideally address_cost should be used, but it reduce cost too much. So current solution is make constant disp as cheap as possible.
Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}. Ok for trunk? gcc/ChangeLog: PR target/67325 * config/i386/i386.cc (ix86_rtx_costs): Reduce cost of MEM (A + imm) to "cost of MEM (A)" + 1. gcc/testsuite/ChangeLog: * gcc.target/i386/pr67325.c: New test. --- gcc/config/i386/i386.cc | 19 ++++++++++++++++++- gcc/testsuite/gcc.target/i386/pr67325.c | 7 +++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr67325.c diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 3e2a3a194f1..3936223bd20 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -22194,7 +22194,24 @@ ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno, /* An insn that accesses memory is slightly more expensive than one that does not. */ if (speed) - *total += 1; + { + *total += 1; + rtx addr = XEXP (x, 0); + /* For MEM, rtx_cost iterates each subrtx, and adds up the costs, + so for MEM (reg) and MEM (reg + 4), the former costs 5, + the latter costs 9, it is not accurate for x86. Ideally + address_cost should be used, but it reduce cost too much. + So current solution is make constant disp as cheap as possible. */ + if (GET_CODE (addr) == PLUS + && CONST_INT_P (XEXP (addr, 1)) + && x86_64_immediate_operand (XEXP (addr, 1), Pmode)) + { + *total += 1; + *total += rtx_cost (XEXP (addr, 0), Pmode, PLUS, 0, speed); + return true; + } + } + return false; case ZERO_EXTRACT: diff --git a/gcc/testsuite/gcc.target/i386/pr67325.c b/gcc/testsuite/gcc.target/i386/pr67325.c new file mode 100644 index 00000000000..c3c1e4c5b4d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr67325.c @@ -0,0 +1,7 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler-not "(?:sar|shr)" } } */ + +int f(long*l){ + return *l>>32; +} -- 2.31.1