diff options
author | Christophe Lyon <christophe.lyon@linaro.org> | 2020-11-02 07:31:22 +0000 |
---|---|---|
committer | Christophe Lyon <christophe.lyon@linaro.org> | 2020-11-02 07:31:22 +0000 |
commit | 4d9af90d6a216822fe117337fb9836ba656dc3af (patch) | |
tree | ba0dcb7edd4d81c1746dd136ae4e85e1e13c582d | |
parent | 590febb5f6624f78b36402a7c9a9c318978f1efa (diff) | |
download | gcc-4d9af90d6a216822fe117337fb9836ba656dc3af.zip gcc-4d9af90d6a216822fe117337fb9836ba656dc3af.tar.gz gcc-4d9af90d6a216822fe117337fb9836ba656dc3af.tar.bz2 |
arm: Avoid indirection with -mpure-code on v6m (PR96967)
With -mpure-code on v6m (thumb-1), to avoid a useless indirection when
building the address of a symbol, we want to consider SYMBOL_REF as a
legitimate constant. This way, we build the address using a series of
upper/lower relocations instead of loading the address from memory.
This patch also fixes a missing "clob" conds attribute for
thumb1_movsi_insn, needed because that alternative clobbers the flags.
2020-11-02 Christophe Lyon <christophe.lyon@linaro.org>
gcc/
PR target/96967
* config/arm/arm.c (thumb_legitimate_constant_p): Add support for
disabled literal pool in thumb-1.
* config/arm/thumb1.md (thumb1_movsi_symbol_ref): Remove.
(*thumb1_movsi_insn): Add support for SYMBOL_REF with -mpure-code.
gcc/testsuite
PR target/96967
* gcc.target/arm/pure-code/pr96767.c: New test.
-rw-r--r-- | gcc/config/arm/arm.c | 6 | ||||
-rw-r--r-- | gcc/config/arm/thumb1.md | 102 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arm/pure-code/pr96767.c | 10 |
3 files changed, 63 insertions, 55 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index dfadaca..d2387c3 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -9500,6 +9500,12 @@ thumb_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x) || CONST_DOUBLE_P (x) || CONSTANT_ADDRESS_P (x) || (TARGET_HAVE_MOVT && GET_CODE (x) == SYMBOL_REF) + /* On Thumb-1 without MOVT/MOVW and literal pool disabled, + we build the symbol address with upper/lower + relocations. */ + || (TARGET_THUMB1 + && GET_CODE (x) == SYMBOL_REF + && arm_disable_literal_pool) || flag_pic); } diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md index b5377a3..4bf73bf 100644 --- a/gcc/config/arm/thumb1.md +++ b/gcc/config/arm/thumb1.md @@ -43,27 +43,6 @@ -(define_insn "thumb1_movsi_symbol_ref" - [(set (match_operand:SI 0 "register_operand" "=l") - (match_operand:SI 1 "general_operand" "")) - ] - "TARGET_THUMB1 - && arm_disable_literal_pool - && GET_CODE (operands[1]) == SYMBOL_REF" - "* - output_asm_insn (\"movs\\t%0, #:upper8_15:%1\", operands); - output_asm_insn (\"lsls\\t%0, #8\", operands); - output_asm_insn (\"adds\\t%0, #:upper0_7:%1\", operands); - output_asm_insn (\"lsls\\t%0, #8\", operands); - output_asm_insn (\"adds\\t%0, #:lower8_15:%1\", operands); - output_asm_insn (\"lsls\\t%0, #8\", operands); - output_asm_insn (\"adds\\t%0, #:lower0_7:%1\", operands); - return \"\"; - " - [(set_attr "length" "14") - (set_attr "conds" "clob")] -) - (define_insn "*thumb1_adddi3" [(set (match_operand:DI 0 "register_operand" "=l") (plus:DI (match_operand:DI 1 "register_operand" "%0") @@ -696,40 +675,53 @@ case 7: /* pure-code alternative: build the constant byte by byte, instead of loading it from a constant pool. */ - { - int i; - HOST_WIDE_INT op1 = INTVAL (operands[1]); - bool mov_done_p = false; - rtx ops[2]; - ops[0] = operands[0]; - - /* Emit upper 3 bytes if needed. */ - for (i = 0; i < 3; i++) - { - int byte = (op1 >> (8 * (3 - i))) & 0xff; - - if (byte) - { - ops[1] = GEN_INT (byte); - if (mov_done_p) - output_asm_insn ("adds\t%0, %1", ops); - else - output_asm_insn ("movs\t%0, %1", ops); - mov_done_p = true; - } - - if (mov_done_p) - output_asm_insn ("lsls\t%0, #8", ops); - } + if (GET_CODE (operands[1]) == SYMBOL_REF) + { + output_asm_insn (\"movs\\t%0, #:upper8_15:%1\", operands); + output_asm_insn (\"lsls\\t%0, #8\", operands); + output_asm_insn (\"adds\\t%0, #:upper0_7:%1\", operands); + output_asm_insn (\"lsls\\t%0, #8\", operands); + output_asm_insn (\"adds\\t%0, #:lower8_15:%1\", operands); + output_asm_insn (\"lsls\\t%0, #8\", operands); + output_asm_insn (\"adds\\t%0, #:lower0_7:%1\", operands); + return \"\"; + } + else + { + int i; + HOST_WIDE_INT op1 = INTVAL (operands[1]); + bool mov_done_p = false; + rtx ops[2]; + ops[0] = operands[0]; + + /* Emit upper 3 bytes if needed. */ + for (i = 0; i < 3; i++) + { + int byte = (op1 >> (8 * (3 - i))) & 0xff; + + if (byte) + { + ops[1] = GEN_INT (byte); + if (mov_done_p) + output_asm_insn ("adds\t%0, %1", ops); + else + output_asm_insn ("movs\t%0, %1", ops); + mov_done_p = true; + } + + if (mov_done_p) + output_asm_insn ("lsls\t%0, #8", ops); + } + + /* Emit lower byte if needed. */ + ops[1] = GEN_INT (op1 & 0xff); + if (!mov_done_p) + output_asm_insn ("movs\t%0, %1", ops); + else if (op1 & 0xff) + output_asm_insn ("adds\t%0, %1", ops); + return ""; + } - /* Emit lower byte if needed. */ - ops[1] = GEN_INT (op1 & 0xff); - if (!mov_done_p) - output_asm_insn ("movs\t%0, %1", ops); - else if (op1 & 0xff) - output_asm_insn ("adds\t%0, %1", ops); - return ""; - } case 8: return "ldr\t%0, %1"; case 9: return "str\t%1, %0"; case 10: return "mov\t%0, %1"; @@ -740,7 +732,7 @@ (set_attr "pool_range" "*,*,*,*,*,*,*, *,1018,*,*") (set_attr "arch" "t1,t1,v8mb,t1,t1,t1,t1,t1,t1,t1,t1") (set_attr "required_for_purecode" "no,no,no,no,no,no,no,yes,no,no,no") - (set_attr "conds" "set,clob,nocond,*,*,nocond,nocond,nocond,nocond,nocond,nocond")]) + (set_attr "conds" "set,clob,nocond,*,*,nocond,nocond,clob,nocond,nocond,nocond")]) ; Split the load of 64-bit constant into two loads for high and low 32-bit parts respectively ; to see if we can load them in fewer instructions or fewer cycles. diff --git a/gcc/testsuite/gcc.target/arm/pure-code/pr96767.c b/gcc/testsuite/gcc.target/arm/pure-code/pr96767.c new file mode 100644 index 0000000..cb3ee68 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pure-code/pr96767.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-mpure-code" } */ + +int x; +int f1 (void) { return x; } + +/* We expect only one indirect load like ldr r3, [r3]. In some + configurations there is an additional ldr rX, [sp], #4 which is not + related to what we check here, so make sure not to match it. */ +/* { dg-final { scan-assembler-times "ldr\tr\[0-9\]+, \\\[r\[0-9\]+\\\]" 1 } } */ |