Re: [PATCHv2/AARCH64 2/3] Fix TLS for ILP32.

2015-02-20 Thread Marcus Shawcroft
  case SYMBOL_SMALL_GOTTPREL:
{
 -   rtx tmp_reg = gen_reg_rtx (Pmode);
 +   /* In ILP32, the mode of dest can be either SImode or DImode,
 +  while the got entry is always of SImode size.  The mode of
 +  dest depends on how dest is used: if dest is assigned to a
 +  pointer (e.g. in the memory), it has SImode; it may have
 +  DImode if dest is dereferenced to access the memeory.
 +  This is why we have to handle three different tlsie_small
 +  patterns here (two patterns for ILP32).  */
 +   enum machine_mode mode = GET_MODE (dest);
 +   rtx tmp_reg = gen_reg_rtx (mode);
 rtx tp = aarch64_load_tp (NULL);
 -   emit_insn (gen_tlsie_small (tmp_reg, imm));
 -   emit_insn (gen_rtx_SET (Pmode, dest, gen_rtx_PLUS (Pmode, tp, 
 tmp_reg)));
 +
 +   if (mode == ptr_mode)
 + {
 +   if (mode == DImode)
 + emit_insn (gen_tlsie_small_di (tmp_reg, imm));
 +   else
 + {
 +   emit_insn (gen_tlsie_small_si (tmp_reg, imm));
 +   tp = gen_lowpart (mode, tp);
 + }
 + }
 +   else
 + {
 +   gcc_assert (mode == Pmode);
 +   emit_insn (gen_tlsie_small_sidi (tmp_reg, imm));
 + }


Andrew, do you recall the circumstance that trigger the mode == SImode
code path through the above code?  I've been trying to trigger this
while working on the equivalent tiny address mode code... with no
success.
/Marcus


Re: [PATCHv2/AARCH64 2/3] Fix TLS for ILP32.

2015-02-20 Thread Andrew Pinski
On Fri, Feb 20, 2015 at 5:35 AM, Marcus Shawcroft
marcus.shawcr...@gmail.com wrote:
  case SYMBOL_SMALL_GOTTPREL:
{
 -   rtx tmp_reg = gen_reg_rtx (Pmode);
 +   /* In ILP32, the mode of dest can be either SImode or DImode,
 +  while the got entry is always of SImode size.  The mode of
 +  dest depends on how dest is used: if dest is assigned to a
 +  pointer (e.g. in the memory), it has SImode; it may have
 +  DImode if dest is dereferenced to access the memeory.
 +  This is why we have to handle three different tlsie_small
 +  patterns here (two patterns for ILP32).  */
 +   enum machine_mode mode = GET_MODE (dest);
 +   rtx tmp_reg = gen_reg_rtx (mode);
 rtx tp = aarch64_load_tp (NULL);
 -   emit_insn (gen_tlsie_small (tmp_reg, imm));
 -   emit_insn (gen_rtx_SET (Pmode, dest, gen_rtx_PLUS (Pmode, tp, 
 tmp_reg)));
 +
 +   if (mode == ptr_mode)
 + {
 +   if (mode == DImode)
 + emit_insn (gen_tlsie_small_di (tmp_reg, imm));
 +   else
 + {
 +   emit_insn (gen_tlsie_small_si (tmp_reg, imm));
 +   tp = gen_lowpart (mode, tp);
 + }
 + }
 +   else
 + {
 +   gcc_assert (mode == Pmode);
 +   emit_insn (gen_tlsie_small_sidi (tmp_reg, imm));
 + }


 Andrew, do you recall the circumstance that trigger the mode == SImode
 code path through the above code?  I've been trying to trigger this
 while working on the equivalent tiny address mode code... with no
 success.

IIRC this happened during the compiling of glibc.  That is with -fPIC
and with initial-exec tls_model.  errno variable in fact.

Thanks,
Andrew Pinski



 /Marcus


Re: [PATCHv2/AARCH64 2/3] Fix TLS for ILP32.

2014-02-27 Thread Yufeng Zhang

Hi,

On 02/26/14 02:25, Andrew Pinski wrote:

Hi,
   With ILP32, some simple usage of TLS variables causes an unrecognizable
instruction due to needing to use SImode for loading pointers from memory.
This fixes the three (tlsie_small, tlsle_small, tlsdesc_small) patterns to
support SImode for pointers.  I modified them to be like what was done for
the GOT patterns.


The patch looks good to me (but I cannot approve).

There are some minor indentation issues though; see below.



OK?  Build and tested on aarch64-elf with no regressions.

Thanks,
Andrew Pinski

* config/aarch64/aarch64.c (aarch64_load_symref_appropriately):
Handle TLS for ILP32.
* config/aarch64/aarch64.md (tlsie_small): Rename to ...
(tlsie_small_mode): this and handle PTR.
(tlsie_small_sidi): New pattern.
(tlsle_small): Change to an expand to handle ILP32.
(tlsle_small_mode): New pattern.
(tlsdesc_small): Rename to ...
(tlsdesc_small_mode): this and handle PTR.
---
  gcc/ChangeLog |   12 +
  gcc/config/aarch64/aarch64.c  |   48 +++
  gcc/config/aarch64/aarch64.md |   54 +++-
  3 files changed, 96 insertions(+), 18 deletions(-)


[snip]


diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 99a6ac8..7d8a645 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -3581,35 +3581,65 @@
[(set_attr type call)
 (set_attr length 16)])

-(define_insn tlsie_small
-  [(set (match_operand:DI 0 register_operand =r)
-(unspec:DI [(match_operand:DI 1 aarch64_tls_ie_symref S)]
+(define_insn tlsie_small_mode
+  [(set (match_operand:PTR 0 register_operand =r)
+(unspec:PTR [(match_operand 1 aarch64_tls_ie_symref S)]
   UNSPEC_GOTSMALLTLS))]

-  adrp\\t%0, %A1\;ldr\\t%0, [%0, #%L1]
+  adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]
[(set_attr type load1)
 (set_attr length 8)]
  )

-(define_insn tlsle_small
+
+(define_insn tlsie_small_sidi
[(set (match_operand:DI 0 register_operand =r)
-(unspec:DI [(match_operand:DI 1 register_operand r)
-   (match_operand:DI 2 aarch64_tls_le_symref S)]
+   (zero_extend:DI
+  (unspec:SI [(match_operand 1 aarch64_tls_ie_symref S)]
+ UNSPEC_GOTSMALLTLS)))]
+  
+  adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]
+  [(set_attr type load1)
+   (set_attr length 8)]
+)
+
+
+(define_expand tlsle_small
+  [(set (match_operand 0 register_operand =r)
+(unspec [(match_operand 1 register_operand r)
+   (match_operand 2 aarch64_tls_le_symref S)]
+   UNSPEC_GOTSMALLTLS))]


The last two lines were not indented well.


+  
+{
+  enum machine_mode mode = GET_MODE (operands[0]);
+  emit_insn ((mode == DImode
+ ? gen_tlsle_small_di
+ : gen_tlsle_small_si) (operands[0],
+  operands[1],
+  operands[2]));


Likewise here.


Thanks,
Yufeng



+  DONE;
+
+})
+
+(define_insn tlsle_small_mode
+  [(set (match_operand:P 0 register_operand =r)
+(unspec:P [(match_operand:P 1 register_operand r)
+   (match_operand 2 aarch64_tls_le_symref S)]
   UNSPEC_GOTSMALLTLS))]

-  add\\t%0, %1, #%G2\;add\\t%0, %0, #%L2
+  add\\t%w0, %w1, #%G2\;add\\t%w0, %w0, #%L2
[(set_attr type alu_reg)
 (set_attr length 8)]
  )

-(define_insn tlsdesc_small
-  [(set (reg:DI R0_REGNUM)
-(unspec:DI [(match_operand:DI 0 aarch64_valid_symref S)]
+(define_insn tlsdesc_small_mode
+  [(set (reg:PTR R0_REGNUM)
+(unspec:PTR [(match_operand 0 aarch64_valid_symref S)]
   UNSPEC_TLSDESC))
 (clobber (reg:DI LR_REGNUM))
 (clobber (match_scratch:DI 1 =r))]
TARGET_TLS_DESC
-  adrp\\tx0, %A0\;ldr\\t%1, [x0, #%L0]\;add\\tx0, x0, 
%L0\;.tlsdesccall\\t%0\;blr\\t%1
+  adrp\\tx0, %A0\;ldr\\t%w1, [x0, #%L0]\;add\\tw0,w0, 
%L0\;.tlsdesccall\\t%0\;blr\\t%1
[(set_attr type call)
 (set_attr length 16)])





Re: [PATCHv2/AARCH64 2/3] Fix TLS for ILP32.

2014-02-27 Thread Marcus Shawcroft
On 26 February 2014 02:25, Andrew Pinski apin...@cavium.com wrote:
 Hi,
   With ILP32, some simple usage of TLS variables causes an unrecognizable
 instruction due to needing to use SImode for loading pointers from memory.
 This fixes the three (tlsie_small, tlsle_small, tlsdesc_small) patterns to
 support SImode for pointers.  I modified them to be like what was done for
 the GOT patterns.

 OK?  Build and tested on aarch64-elf with no regressions.

 Thanks,
 Andrew Pinski

 * config/aarch64/aarch64.c (aarch64_load_symref_appropriately):
 Handle TLS for ILP32.
 * config/aarch64/aarch64.md (tlsie_small): Rename to ...
 (tlsie_small_mode): this and handle PTR.
 (tlsie_small_sidi): New pattern.
 (tlsle_small): Change to an expand to handle ILP32.
 (tlsle_small_mode): New pattern.
 (tlsdesc_small): Rename to ...
 (tlsdesc_small_mode): this and handle PTR.

Thanks Andrew, this is OK for stage-1, but please fix Yufeng's layout nit.
/Marcus


[PATCHv2/AARCH64 2/3] Fix TLS for ILP32.

2014-02-25 Thread Andrew Pinski
Hi,
  With ILP32, some simple usage of TLS variables causes an unrecognizable
instruction due to needing to use SImode for loading pointers from memory.
This fixes the three (tlsie_small, tlsle_small, tlsdesc_small) patterns to
support SImode for pointers.  I modified them to be like what was done for
the GOT patterns.

OK?  Build and tested on aarch64-elf with no regressions.

Thanks,
Andrew Pinski

* config/aarch64/aarch64.c (aarch64_load_symref_appropriately):
Handle TLS for ILP32.
* config/aarch64/aarch64.md (tlsie_small): Rename to ...
(tlsie_small_mode): this and handle PTR.
(tlsie_small_sidi): New pattern.
(tlsle_small): Change to an expand to handle ILP32.
(tlsle_small_mode): New pattern.
(tlsdesc_small): Rename to ...
(tlsdesc_small_mode): this and handle PTR.
---
 gcc/ChangeLog |   12 +
 gcc/config/aarch64/aarch64.c  |   48 +++
 gcc/config/aarch64/aarch64.md |   54 +++-
 3 files changed, 96 insertions(+), 18 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fd2b6cd..155ce45 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,17 @@
 2014-02-25  Andrew Pinski  apin...@cavium.com
 
+   * config/aarch64/aarch64.c (aarch64_load_symref_appropriately):
+   Handle TLS for ILP32.
+   * config/aarch64/aarch64.md (tlsie_small): Rename to ...
+   (tlsie_small_mode): this and handle PTR.
+   (tlsie_small_sidi): New pattern.
+   (tlsle_small): Change to an expand to handle ILP32.
+   (tlsle_small_mode): New pattern.
+   (tlsdesc_small): Rename to ...
+   (tlsdesc_small_mode): this and handle PTR.
+
+2014-02-25  Andrew Pinski  apin...@cavium.com
+
* config/host-linux.c (TRY_EMPTY_VM_SPACE): Change aarch64 ilp32
definition.
 
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 901ad3d..e65c049 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -640,22 +640,58 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm,
 
 case SYMBOL_SMALL_TLSDESC:
   {
-   rtx x0 = gen_rtx_REG (Pmode, R0_REGNUM);
+   enum machine_mode mode = GET_MODE (dest);
+   rtx x0 = gen_rtx_REG (mode, R0_REGNUM);
rtx tp;
 
-   emit_insn (gen_tlsdesc_small (imm));
+   gcc_assert (mode == Pmode || mode == ptr_mode);
+
+   /* In ILP32, the got entry is always of SImode size.  Unlike
+  small GOT, the dest is fixed at reg 0.  */
+   if (TARGET_ILP32)
+ emit_insn (gen_tlsdesc_small_si (imm));
+   else
+ emit_insn (gen_tlsdesc_small_di (imm));
tp = aarch64_load_tp (NULL);
-   emit_insn (gen_rtx_SET (Pmode, dest, gen_rtx_PLUS (Pmode, tp, x0)));
+
+   if (mode != Pmode)
+ tp = gen_lowpart (mode, tp);
+
+   emit_insn (gen_rtx_SET (mode, dest, gen_rtx_PLUS (mode, tp, x0)));
set_unique_reg_note (get_last_insn (), REG_EQUIV, imm);
return;
   }
 
 case SYMBOL_SMALL_GOTTPREL:
   {
-   rtx tmp_reg = gen_reg_rtx (Pmode);
+   /* In ILP32, the mode of dest can be either SImode or DImode,
+  while the got entry is always of SImode size.  The mode of
+  dest depends on how dest is used: if dest is assigned to a
+  pointer (e.g. in the memory), it has SImode; it may have
+  DImode if dest is dereferenced to access the memeory.
+  This is why we have to handle three different tlsie_small
+  patterns here (two patterns for ILP32).  */
+   enum machine_mode mode = GET_MODE (dest);
+   rtx tmp_reg = gen_reg_rtx (mode);
rtx tp = aarch64_load_tp (NULL);
-   emit_insn (gen_tlsie_small (tmp_reg, imm));
-   emit_insn (gen_rtx_SET (Pmode, dest, gen_rtx_PLUS (Pmode, tp, 
tmp_reg)));
+
+   if (mode == ptr_mode)
+ {
+   if (mode == DImode)
+ emit_insn (gen_tlsie_small_di (tmp_reg, imm));
+   else
+ {
+   emit_insn (gen_tlsie_small_si (tmp_reg, imm));
+   tp = gen_lowpart (mode, tp);
+ }
+ }
+   else
+ {
+   gcc_assert (mode == Pmode);
+   emit_insn (gen_tlsie_small_sidi (tmp_reg, imm));
+ }
+
+   emit_insn (gen_rtx_SET (mode, dest, gen_rtx_PLUS (mode, tp, tmp_reg)));
set_unique_reg_note (get_last_insn (), REG_EQUIV, imm);
return;
   }
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 99a6ac8..7d8a645 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -3581,35 +3581,65 @@
   [(set_attr type call)
(set_attr length 16)])
 
-(define_insn tlsie_small
-  [(set (match_operand:DI 0 register_operand =r)
-(unspec:DI [(match_operand:DI 1 aarch64_tls_ie_symref S)]
+(define_insn tlsie_small_mode
+  [(set (match_operand:PTR 0 register_operand =r)
+(unspec:PTR