| From 1383012ae409ed91903b2b76ee15137bc1f89900 Mon Sep 17 00:00:00 2001 |
| From: shorne <shorne@138bc75d-0d04-0410-961f-82ee72b054a4> |
| Date: Sat, 31 Aug 2019 06:00:56 +0000 |
| Subject: [PATCH] or1k: Fix issue with set_got clobbering LR (r9) |
| |
| When compiling glibc we found that the GOT register was being allocated |
| r9 when the instruction was still set_got_tmp. That is a problem |
| because r9 is the Link Register (LR) in OpenRISC which is used/clobbered |
| in set_got. We cannot use r9 as the GOT register. Also, we cannot |
| simply say set_got_tmp clobbers r9 as this is the reason for having the |
| temporary set_got_tmp. |
| |
| Fix by using a register class constraint that does not allow r9 during |
| register allocation. |
| |
| gcc/ChangeLog: |
| |
| * config/or1k/constraints.md (t): New constraint. |
| * config/or1k/or1k.h (GOT_REGS): New register class. |
| * config/or1k/or1k.md (set_got_tmp, set_got): Use t contraint. |
| |
| git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@275242 138bc75d-0d04-0410-961f-82ee72b054a4 |
| (cherry picked from commit 5b9471ffca25d39635680516ba2ff85295480fc3) |
| Signed-off-by: Romain Naour <romain.naour@gmail.com> |
| --- |
| gcc/config/or1k/constraints.md | 4 ++++ |
| gcc/config/or1k/or1k.h | 3 +++ |
| gcc/config/or1k/or1k.md | 4 ++-- |
| 3 files changed, 9 insertions(+), 2 deletions(-) |
| |
| diff --git a/gcc/config/or1k/constraints.md b/gcc/config/or1k/constraints.md |
| index 93da8c058c6..a16b749008f 100644 |
| --- a/gcc/config/or1k/constraints.md |
| +++ b/gcc/config/or1k/constraints.md |
| @@ -24,6 +24,7 @@ |
| |
| ; We use: |
| ; c - sibcall registers |
| +; t - got address registers (excludes LR (r9) which is clobbered by set_got) |
| ; I - constant signed 16-bit |
| ; K - constant unsigned 16-bit |
| ; M - constant signed 16-bit shifted left 16-bits (l.movhi) |
| @@ -32,6 +33,9 @@ |
| (define_register_constraint "c" "SIBCALL_REGS" |
| "Registers which can hold a sibling call address") |
| |
| +(define_register_constraint "t" "GOT_REGS" |
| + "Registers which can be used to store the Global Offset Table (GOT) address.") |
| + |
| ;; Immediates |
| (define_constraint "I" |
| "A signed 16-bit immediate in the range -32768 to 32767." |
| diff --git a/gcc/config/or1k/or1k.h b/gcc/config/or1k/or1k.h |
| index 6dda230f217..feee702d89c 100644 |
| --- a/gcc/config/or1k/or1k.h |
| +++ b/gcc/config/or1k/or1k.h |
| @@ -189,6 +189,7 @@ enum reg_class |
| { |
| NO_REGS, |
| SIBCALL_REGS, |
| + GOT_REGS, |
| GENERAL_REGS, |
| FLAG_REGS, |
| ALL_REGS, |
| @@ -200,6 +201,7 @@ enum reg_class |
| #define REG_CLASS_NAMES { \ |
| "NO_REGS", \ |
| "SIBCALL_REGS", \ |
| + "GOT_REGS", \ |
| "GENERAL_REGS", \ |
| "FLAG_REGS", \ |
| "ALL_REGS" } |
| @@ -212,6 +214,7 @@ enum reg_class |
| #define REG_CLASS_CONTENTS \ |
| { { 0x00000000, 0x00000000 }, \ |
| { SIBCALL_REGS_MASK, 0 }, \ |
| + { 0xfffffdff, 0x00000000 }, \ |
| { 0xffffffff, 0x00000003 }, \ |
| { 0x00000000, 0x00000004 }, \ |
| { 0xffffffff, 0x00000007 } \ |
| diff --git a/gcc/config/or1k/or1k.md b/gcc/config/or1k/or1k.md |
| index 2dad51cd46b..88f3f02630f 100644 |
| --- a/gcc/config/or1k/or1k.md |
| +++ b/gcc/config/or1k/or1k.md |
| @@ -595,7 +595,7 @@ |
| ;; set_got pattern below. This works because the set_got_tmp insn is the |
| ;; first insn in the stream and that it isn't moved during RA. |
| (define_insn "set_got_tmp" |
| - [(set (match_operand:SI 0 "register_operand" "=r") |
| + [(set (match_operand:SI 0 "register_operand" "=t") |
| (unspec_volatile:SI [(const_int 0)] UNSPECV_SET_GOT))] |
| "" |
| { |
| @@ -604,7 +604,7 @@ |
| |
| ;; The insn to initialize the GOT. |
| (define_insn "set_got" |
| - [(set (match_operand:SI 0 "register_operand" "=r") |
| + [(set (match_operand:SI 0 "register_operand" "=t") |
| (unspec:SI [(const_int 0)] UNSPEC_SET_GOT)) |
| (clobber (reg:SI LR_REGNUM))] |
| "" |
| -- |
| 2.24.1 |
| |