aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Lyon <christophe.lyon@linaro.org>2020-11-02 07:31:22 +0000
committerChristophe Lyon <christophe.lyon@linaro.org>2020-11-02 07:31:22 +0000
commit4d9af90d6a216822fe117337fb9836ba656dc3af (patch)
treeba0dcb7edd4d81c1746dd136ae4e85e1e13c582d
parent590febb5f6624f78b36402a7c9a9c318978f1efa (diff)
downloadgcc-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.c6
-rw-r--r--gcc/config/arm/thumb1.md102
-rw-r--r--gcc/testsuite/gcc.target/arm/pure-code/pr96767.c10
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 } } */