diff mbox series

[AARCH64] Don't force symbols which referencing per-function literal pool into memory

Message ID 40e6abea-0220-ce7b-ff89-7c22fc2df00a@foss.arm.com
State New
Headers show
Series [AARCH64] Don't force symbols which referencing per-function literal pool into memory | expand

Commit Message

Renlin Li Oct. 16, 2018, 8:48 a.m. UTC
Hi all,

"-mcmodel=large" and "-mpc-relative-loads" are used to avoid adrp+add to address symbols.
When the combination is used, the original symbol is first forced into per-function literal pools.
And a local symbol is created to reference it.

In this case, the way to reference this local symbol is pc relative. According to the original logic,
the local symbol will be forced into memory, and another local symbol will be created again.

For example, during expand stage,

(insn 5 2 6 2 (set (reg/f:DI 92)
          (mem/u/c:DI (symbol_ref/u:DI ("*.LC1") [flags 0x2]) [0  S8 A64])) "imm.c":5 -1
       (expr_list:REG_EQUAL (symbol_ref/u:DI ("*.LC0") [flags 0x2])
          (nil)))
(insn 6 5 10 2 (set (reg:TI 90 [ <retval> ])
          (mem/u/c:TI (reg/f:DI 92) [0  S16 A128])) "imm.c":5 -1
       (expr_list:REG_EQUAL (const_wide_int 0x123456789abcdef0fedcba987654321)
          (nil)))

However, later, the CSE will replace memory load in insn 5 with its equivalent value (symbol_ref/u:DI ("*.LC0").
So there is no issue in the final code-generation.
However, if the CSE is not enabled, for example with -O0, a load will be generated.

The patch here simplifies the rtx in expand stage.
Instead of force the local symbol in the memory again, the symbol is classified as SYMBOL_TINY_ABSOLUTE.
The following rtx is generated directly.

(insn 5 2 6 2 (set (reg/f:DI 92)
          (symbol_ref/u:DI ("*.LC0") [flags 0x2])) "imm.c":5 -1
       (nil))
(insn 6 5 10 2 (set (reg:TI 90 [ <retval> ])
          (mem/u/c:TI (reg/f:DI 92) [0  S16 A128])) "imm.c":5 -1
       (expr_list:REG_EQUAL (const_wide_int 0x123456789abcdef0fedcba987654321)
          (nil)))

Similar change is added to handle literal pool referencing in small memory model when option
"-mpc-relative-loads" is present. The symbol is classified as SYMBOL_TINY_ABSOLUTE, instead of SYMBOL_SMALL_ABSOLUTE.
So that, in the final code-generation, a single ADR instruction could be used, instead of ADRP+ADD.

A test case is added, which should be applicable at O0 optimization level for all memory models (tiny, small and large).

Okay to commit?


gcc/ChangeLog:

2018-10-15  Renlin Li  <renlin.li@arm.com>

          * config/aarch64/aarch64.c (aarch64_classify_symbol): Direct address
          symbols referencing per function literl pool.

gcc/testsuite/ChangeLog:

2018-10-15  Renlin Li  <renlin.li@arm.com>

          * gcc.target/aarch64/pr79041-2.c: Skip when mcmodel is defined by
          dejagnu configuration.
          * gcc.target/aarch64/pr79041-3.c: New.
diff mbox series

Patch

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 2f98a21acf16297bdd7c4742cbcfc695cdc4e5f9..bd6369ca08707cca59809bf970830238b05fa2bc 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -11845,7 +11845,13 @@  aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset)
 	      || !IN_RANGE (offset, HOST_WIDE_INT_C (-4294967263),
 			    HOST_WIDE_INT_C (4294967264)))
 	    return SYMBOL_FORCE_TO_MEM;
-	  return SYMBOL_SMALL_ABSOLUTE;
+	  /* Use ADR when addressing per-function constant pool if
+	     pcrelative_literal_loads is enabled.  */
+	  else if (CONSTANT_POOL_ADDRESS_P (x)
+		   && aarch64_pcrelative_literal_loads)
+	    return SYMBOL_TINY_ABSOLUTE;
+	  else
+	    return SYMBOL_SMALL_ABSOLUTE;
 
 	case AARCH64_CMODEL_TINY_PIC:
 	  if (!aarch64_symbol_binds_local_p (x))
@@ -11857,14 +11863,24 @@  aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset)
 	  if (!aarch64_symbol_binds_local_p (x))
 	    return (aarch64_cmodel == AARCH64_CMODEL_SMALL_SPIC
 		    ?  SYMBOL_SMALL_GOT_28K : SYMBOL_SMALL_GOT_4G);
-	  return SYMBOL_SMALL_ABSOLUTE;
+	  /* Use ADR when addressing per-function constant pool if
+	     pcrelative_literal_loads is enabled.  */
+	  else if (CONSTANT_POOL_ADDRESS_P (x)
+		   && aarch64_pcrelative_literal_loads)
+	    return SYMBOL_TINY_ABSOLUTE;
+	  else
+	    return SYMBOL_SMALL_ABSOLUTE;
 
 	case AARCH64_CMODEL_LARGE:
-	  /* This is alright even in PIC code as the constant
-	     pool reference is always PC relative and within
-	     the same translation unit.  */
-	  if (!aarch64_pcrelative_literal_loads && CONSTANT_POOL_ADDRESS_P (x))
-	    return SYMBOL_SMALL_ABSOLUTE;
+	  if (CONSTANT_POOL_ADDRESS_P (x))
+	    {
+	      /* Use ADR when addressing per-function constant pool if
+		 pcrelative_literal_loads is enabled.  */
+	      if (aarch64_pcrelative_literal_loads)
+		return SYMBOL_TINY_ABSOLUTE;
+	      else
+		return SYMBOL_SMALL_ABSOLUTE;
+	    }
 	  else
 	    return SYMBOL_FORCE_TO_MEM;
 
diff --git a/gcc/testsuite/gcc.target/aarch64/pr79041-2.c b/gcc/testsuite/gcc.target/aarch64/pr79041-2.c
index 4695b5c1b2b7c9b515995e242dd38e0519a48a2b..42695be127db454934d2791474d5f97fc5667403 100644
--- a/gcc/testsuite/gcc.target/aarch64/pr79041-2.c
+++ b/gcc/testsuite/gcc.target/aarch64/pr79041-2.c
@@ -2,6 +2,7 @@ 
 /* { dg-options "-O2 -mcmodel=large -mpc-relative-literal-loads" } */
 /* { dg-require-effective-target lp64 } */
 /* { dg-skip-if "-mcmodel=large, no support for -fpic" { aarch64-*-* }  { "-fpic" } { "" } } */
+/* { dg-skip-if "Code model already defined" { aarch64_tiny || aarch64_small } } */
 
 __int128
 t (void)
diff --git a/gcc/testsuite/gcc.target/aarch64/pr79041-3.c b/gcc/testsuite/gcc.target/aarch64/pr79041-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..f4239713f962edca5d354cc62d0bea13c609ceec
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr79041-3.c
@@ -0,0 +1,13 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O0 -mpc-relative-literal-loads" } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-skip-if "-mcmodel=large, no support for -fpic" { aarch64-*-* }  { "-fpic" "-mcmodel=large" } { "" } } */
+
+__int128
+tiny_abs (void)
+{
+  return ((__int128)0x123456789abcdef << 64) | 0xfedcba987654321;
+}
+
+/* { dg-final { scan-assembler "adr" } } */
+/* { dg-final { scan-assembler-not "adrp" } } */