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...@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...@arm.com>

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

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" } } */

Reply via email to