This fixes a regression present on the 7 and 6 branches in the form of an ICE
on an unrecognizable insn generated for a jump table in PIC mode. It occurs
because the index of the table is folded to a constant at RTL expansion time
and not at the GIMPLE level (this pessimization is fixed on the mainline).
Tested on SPARC64/Linux, applied on all active branches.
2018-04-06 Eric Botcazou <ebotca...@adacore.com>
PR target/85196
* config/sparc/sparc.c (sparc_expand_move): Deal with symbolic operands
based on LABEL_REF. Remove useless assertion.
(pic_address_needs_scratch): Fix formatting.
(sparc_legitimize_pic_address): Minor tweaks.
(sparc_delegitimize_address): Adjust assertion accordingly.
* config/sparc/sparc.md (movsi_pic_label_ref): Change label_ref_operand
into symbolic_operand.
(movsi_high_pic_label_ref): Likewise.
(movsi_lo_sum_pic_label_ref): Likewise.
(movdi_pic_label_ref): Likewise.
(movdi_high_pic_label_ref): Likewise.
(movdi_lo_sum_pic_label_ref): Likewise.
2018-04-06 Eric Botcazou <ebotca...@adacore.com>
* g++.dg/opt/pr85196.C: New test.
--
Eric Botcazou
Index: config/sparc/sparc.c
===================================================================
--- config/sparc/sparc.c (revision 259025)
+++ config/sparc/sparc.c (working copy)
@@ -2236,7 +2236,7 @@ sparc_expand_move (machine_mode mode, rt
}
}
- /* Fixup TLS cases. */
+ /* Fix up TLS cases. */
if (TARGET_HAVE_TLS
&& CONSTANT_P (operands[1])
&& sparc_tls_referenced_p (operands [1]))
@@ -2245,15 +2245,20 @@ sparc_expand_move (machine_mode mode, rt
return false;
}
- /* Fixup PIC cases. */
+ /* Fix up PIC cases. */
if (flag_pic && CONSTANT_P (operands[1]))
{
if (pic_address_needs_scratch (operands[1]))
operands[1] = sparc_legitimize_pic_address (operands[1], NULL_RTX);
/* We cannot use the mov{si,di}_pic_label_ref patterns in all cases. */
- if (GET_CODE (operands[1]) == LABEL_REF
- && can_use_mov_pic_label_ref (operands[1]))
+ if ((GET_CODE (operands[1]) == LABEL_REF
+ && can_use_mov_pic_label_ref (operands[1]))
+ || (GET_CODE (operands[1]) == CONST
+ && GET_CODE (XEXP (operands[1], 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT
+ && can_use_mov_pic_label_ref (XEXP (XEXP (operands[1], 0), 0))))
{
if (mode == SImode)
{
@@ -2263,7 +2268,6 @@ sparc_expand_move (machine_mode mode, rt
if (mode == DImode)
{
- gcc_assert (TARGET_ARCH64);
emit_insn (gen_movdi_pic_label_ref (operands[0], operands[1]));
return true;
}
@@ -4280,10 +4284,11 @@ int
pic_address_needs_scratch (rtx x)
{
/* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
- if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
+ if (GET_CODE (x) == CONST
+ && GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
- && ! SMALL_INT (XEXP (XEXP (x, 0), 1)))
+ && !SMALL_INT (XEXP (XEXP (x, 0), 1)))
return 1;
return 0;
@@ -4750,16 +4755,15 @@ sparc_legitimize_tls_address (rtx addr)
static rtx
sparc_legitimize_pic_address (rtx orig, rtx reg)
{
- bool gotdata_op = false;
-
if (GET_CODE (orig) == SYMBOL_REF
/* See the comment in sparc_expand_move. */
|| (GET_CODE (orig) == LABEL_REF && !can_use_mov_pic_label_ref (orig)))
{
+ bool gotdata_op = false;
rtx pic_ref, address;
rtx_insn *insn;
- if (reg == 0)
+ if (!reg)
{
gcc_assert (can_create_pseudo_p ());
reg = gen_reg_rtx (Pmode);
@@ -4770,8 +4774,7 @@ sparc_legitimize_pic_address (rtx orig,
/* If not during reload, allocate another temp reg here for loading
in the address, so that these instructions can be optimized
properly. */
- rtx temp_reg = (! can_create_pseudo_p ()
- ? reg : gen_reg_rtx (Pmode));
+ rtx temp_reg = can_create_pseudo_p () ? gen_reg_rtx (Pmode) : reg;
/* Must put the SYMBOL_REF inside an UNSPEC here so that cse
won't get confused into thinking that these two instructions
@@ -4787,6 +4790,7 @@ sparc_legitimize_pic_address (rtx orig,
emit_insn (gen_movsi_high_pic (temp_reg, orig));
emit_insn (gen_movsi_lo_sum_pic (temp_reg, temp_reg, orig));
}
+
address = temp_reg;
gotdata_op = true;
}
@@ -4827,7 +4831,7 @@ sparc_legitimize_pic_address (rtx orig,
&& sparc_pic_register_p (XEXP (XEXP (orig, 0), 0)))
return orig;
- if (reg == 0)
+ if (!reg)
{
gcc_assert (can_create_pseudo_p ());
reg = gen_reg_rtx (Pmode);
@@ -4935,7 +4939,11 @@ sparc_delegitimize_address (rtx x)
&& XINT (XEXP (XEXP (x, 1), 1), 1) == UNSPEC_MOVE_PIC_LABEL)
{
x = XVECEXP (XEXP (XEXP (x, 1), 1), 0, 0);
- gcc_assert (GET_CODE (x) == LABEL_REF);
+ gcc_assert (GET_CODE (x) == LABEL_REF
+ || (GET_CODE (x) == CONST
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT));
}
return x;
Index: config/sparc/sparc.md
===================================================================
--- config/sparc/sparc.md (revision 259025)
+++ config/sparc/sparc.md (working copy)
@@ -1758,7 +1758,7 @@ (define_insn "movsi_pic_gotdata_op"
(define_expand "movsi_pic_label_ref"
[(set (match_dup 3) (high:SI
- (unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
+ (unspec:SI [(match_operand:SI 1 "symbolic_operand" "")
(match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
(set (match_dup 4) (lo_sum:SI (match_dup 3)
(unspec:SI [(match_dup 1) (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
@@ -1784,7 +1784,7 @@ (define_expand "movsi_pic_label_ref"
(define_insn "*movsi_high_pic_label_ref"
[(set (match_operand:SI 0 "register_operand" "=r")
(high:SI
- (unspec:SI [(match_operand:SI 1 "label_ref_operand" "")
+ (unspec:SI [(match_operand:SI 1 "symbolic_operand" "")
(match_operand:SI 2 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
"flag_pic"
"sethi\t%%hi(%a2-(%a1-.)), %0")
@@ -1792,7 +1792,7 @@ (define_insn "*movsi_high_pic_label_ref"
(define_insn "*movsi_lo_sum_pic_label_ref"
[(set (match_operand:SI 0 "register_operand" "=r")
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
- (unspec:SI [(match_operand:SI 2 "label_ref_operand" "")
+ (unspec:SI [(match_operand:SI 2 "symbolic_operand" "")
(match_operand:SI 3 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
"flag_pic"
"or\t%1, %%lo(%a3-(%a2-.)), %0")
@@ -1896,7 +1896,7 @@ (define_insn "*movdi_insn_sp64"
(define_expand "movdi_pic_label_ref"
[(set (match_dup 3) (high:DI
- (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")
(match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
(set (match_dup 4) (lo_sum:DI (match_dup 3)
(unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_MOVE_PIC_LABEL)))
@@ -1922,7 +1922,7 @@ (define_expand "movdi_pic_label_ref"
(define_insn "*movdi_high_pic_label_ref"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI
- (unspec:DI [(match_operand:DI 1 "label_ref_operand" "")
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")
(match_operand:DI 2 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
"TARGET_ARCH64 && flag_pic"
"sethi\t%%hi(%a2-(%a1-.)), %0")
@@ -1930,7 +1930,7 @@ (define_insn "*movdi_high_pic_label_ref"
(define_insn "*movdi_lo_sum_pic_label_ref"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
- (unspec:DI [(match_operand:DI 2 "label_ref_operand" "")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")
(match_operand:DI 3 "" "")] UNSPEC_MOVE_PIC_LABEL)))]
"TARGET_ARCH64 && flag_pic"
"or\t%1, %%lo(%a3-(%a2-.)), %0")
// PR target/85196
// Testcase by Rainer Orth <r...@gcc.gnu.org>
// { dg-do compile }
// { dg-options "-O -fpermissive -w" }
// { dg-additional-options "-fPIC" { target fpic } }
class a;
template <typename> class b;
template <typename k> class d : public b<k> {};
class e {};
void f(int);
template <class> class g {
public:
h();
a i();
};
template <> class b<e> : public g<e> {};
typedef (*j)(d<e>);
template <class k> class l {
public:
k operator->() { return 0; }
};
enum m { n, aa, o, ab, q, p };
inline s(m ac) {
switch (ac) {
case n:
case aa:
case p:
return 1;
case o:
case ab:
return 2;
}
}
class D {
int ad;
public:
*ae() { return &ad; }
};
class a {
l<D *> af;
public:
*r() { return af->ae(); }
t(int *c) {
int *w = af->ae();
return w == c;
}
};
class F : a {
public:
static int ah[];
static e v(F *);
unsigned long ai() const;
};
inline unsigned long F::ai() const {
m aj = r() - &ah[0];
return s(aj);
}
inline e F::v(F *ak) {
long al = ak->ai();
f(al);
}
template <typename> am() { return q; }
class an : F {
public:
static ao(d<e> u) {
int *ap;
m aq = am<unsigned>();
ap = &ah[aq];
return u.h() && u.i().t(ap);
}
template <e ar(F *)> static as() {
F at;
ar(&at);
}
template <e ar(F *)> static au(int *, unsigned, e *) {
j av = ao;
d<e> aw;
if (av(aw))
as<ar>();
}
};
int *ax;
int ay;
e az;
ba() { an::au<an::v>(ax, ay, &az); }