Commit e800d6dc by Bill Schmidt Committed by William Schmidt

rs6000.c (rs6000_call_template_1): Handle pcrel calls here...

[gcc]

2019-05-29  Bill Schmidt  <wschmidt@linux.ibm.com>
	    Alan Modra  <amodra@gmail.com>

	* config/rs6000/rs6000.c (rs6000_call_template_1): Handle pcrel
	calls here...
	(rs6000_indirect_call_template_1): ...and here.
	(rs6000_pltseq_template): Handle plt_pcrel34.  Rework tocsave,
	plt16_ha, plt16_lo, mtctr indirect calls.  Use
	rs6000_pltseq_enum.
	(rs6000_decl_ok_for_sibcall): New function.
	(rs6000_function_ok_for_sibcall): Refactor.
	(rs6000_longcall_ref): Use UNSPEC_PLT_PCREL when pcrel.
	(rs6000_call_aix): Don't emit toc restore rtl for indirect calls
	when pcrel.  Reorganize.
	(rs6000_sibcall_aix): Don't add r2 to function usage when pcrel.
	* rs6000.h (rs6000_pltseq_enum): New enum.
	* rs6000.md (UNSPEC_PLT_PCREL): New unspec.
	(*pltseq_tocsave): Use rs6000_pltseq_enum.
	(*pltseq_plt16_ha): Likewise.
	(*pltseq_plt16_lo): Likewise.
	(*pltseq_mtctr): Likewise.
	(*pltseq_plt_pcrel): New insn.
	(*call_local_aix): Handle @notoc calls.
	(*call_value_local_aix): Likewise.
	(*call_nonlocal_aix): Adjust lengths for pcrel calls.
	(*call_value_nonlocal_aix): Likewise.
	(*call_indirect_pcrel): New insn.
	(*call_value_indirect_pcrel): Likewise.


[gcc/testsuite]

2019-05-29  Bill Schmidt  <wschmidt@linux.ibm.com>

	* gcc.target/powerpc/notoc-direct-1.c: New.
	* gcc.target/powerpc/pcrel-sibcall-1.c: New.


Co-Authored-By: Alan Modra <amodra@gmail.com>

From-SVN: r271753
parent 874f88c4
2019-05-29 Bill Schmidt <wschmidt@linux.ibm.com>
Alan Modra <amodra@gmail.com>
* config/rs6000/rs6000.c (rs6000_call_template_1): Handle pcrel
calls here...
(rs6000_indirect_call_template_1): ...and here.
(rs6000_pltseq_template): Handle plt_pcrel34. Rework tocsave,
plt16_ha, plt16_lo, mtctr indirect calls. Use
rs6000_pltseq_enum.
(rs6000_decl_ok_for_sibcall): New function.
(rs6000_function_ok_for_sibcall): Refactor.
(rs6000_longcall_ref): Use UNSPEC_PLT_PCREL when pcrel.
(rs6000_call_aix): Don't emit toc restore rtl for indirect calls
when pcrel. Reorganize.
(rs6000_sibcall_aix): Don't add r2 to function usage when pcrel.
* rs6000.h (rs6000_pltseq_enum): New enum.
* rs6000.md (UNSPEC_PLT_PCREL): New unspec.
(*pltseq_tocsave): Use rs6000_pltseq_enum.
(*pltseq_plt16_ha): Likewise.
(*pltseq_plt16_lo): Likewise.
(*pltseq_mtctr): Likewise.
(*pltseq_plt_pcrel): New insn.
(*call_local_aix): Handle @notoc calls.
(*call_value_local_aix): Likewise.
(*call_nonlocal_aix): Adjust lengths for pcrel calls.
(*call_value_nonlocal_aix): Likewise.
(*call_indirect_pcrel): New insn.
(*call_value_indirect_pcrel): Likewise.
2019-05-29 Uroš Bizjak <ubizjak@gmail.com>
* config/i386/sse.md (*save_multiple<mode>): Rename from
......
......@@ -1490,6 +1490,15 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
#define CALL_LONG 0x00000008 /* always call indirect */
#define CALL_LIBCALL 0x00000010 /* libcall */
/* Identify PLT sequence for rs6000_pltseq_template. */
enum rs6000_pltseq_enum {
RS6000_PLTSEQ_TOCSAVE,
RS6000_PLTSEQ_PLT16_HA,
RS6000_PLTSEQ_PLT16_LO,
RS6000_PLTSEQ_MTCTR,
RS6000_PLTSEQ_PLT_PCREL34
};
#define IS_V4_FP_ARGS(OP) \
((INTVAL (OP) & (CALL_V4_CLEAR_FP_ARGS | CALL_V4_SET_FP_ARGS)) != 0)
......
......@@ -147,6 +147,7 @@
UNSPEC_PLTSEQ
UNSPEC_PLT16_HA
UNSPEC_PLT16_LO
UNSPEC_PLT_PCREL
])
;;
......@@ -10231,7 +10232,7 @@
"TARGET_PLTSEQ
&& DEFAULT_ABI == ABI_ELFv2"
{
return rs6000_pltseq_template (operands, 0);
return rs6000_pltseq_template (operands, RS6000_PLTSEQ_TOCSAVE);
})
(define_insn "*pltseq_plt16_ha_<mode>"
......@@ -10242,7 +10243,7 @@
UNSPEC_PLT16_HA))]
"TARGET_PLTSEQ"
{
return rs6000_pltseq_template (operands, 1);
return rs6000_pltseq_template (operands, RS6000_PLTSEQ_PLT16_HA);
})
(define_insn "*pltseq_plt16_lo_<mode>"
......@@ -10253,7 +10254,7 @@
UNSPEC_PLT16_LO))]
"TARGET_PLTSEQ"
{
return rs6000_pltseq_template (operands, 2);
return rs6000_pltseq_template (operands, RS6000_PLTSEQ_PLT16_LO);
}
[(set_attr "type" "load")])
......@@ -10265,8 +10266,22 @@
UNSPEC_PLTSEQ))]
"TARGET_PLTSEQ"
{
return rs6000_pltseq_template (operands, 3);
return rs6000_pltseq_template (operands, RS6000_PLTSEQ_MTCTR);
})
(define_insn "*pltseq_plt_pcrel<mode>"
[(set (match_operand:P 0 "gpc_reg_operand" "=r")
(unspec:P [(match_operand:P 1 "" "")
(match_operand:P 2 "symbol_ref_operand" "s")
(match_operand:P 3 "" "")]
UNSPEC_PLT_PCREL))]
"HAVE_AS_PLTSEQ && TARGET_TLS_MARKERS
&& rs6000_pcrel_p (cfun)"
{
return rs6000_pltseq_template (operands, RS6000_PLTSEQ_PLT_PCREL34);
}
[(set_attr "type" "load")
(set_attr "length" "12")])
;; Call and call_value insns
;; For the purposes of expanding calls, Darwin is very similar to SYSV.
......@@ -10582,7 +10597,11 @@
(match_operand 1))
(clobber (reg:P LR_REGNO))]
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
"bl %z0"
{
if (rs6000_pcrel_p (cfun))
return "bl %z0@notoc";
return "bl %z0";
}
[(set_attr "type" "branch")])
(define_insn "*call_value_local_aix<mode>"
......@@ -10592,7 +10611,11 @@
(clobber (reg:P LR_REGNO))]
"(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
&& !IS_NOMARK_TLSGETADDR (operands[2])"
"bl %z1"
{
if (rs6000_pcrel_p (cfun))
return "bl %z1@notoc";
return "bl %z1";
}
[(set_attr "type" "branch")])
;; Call to AIX abi function which may be in another module.
......@@ -10607,7 +10630,10 @@
return rs6000_call_template (operands, 0);
}
[(set_attr "type" "branch")
(set_attr "length" "8")])
(set (attr "length")
(if_then_else (match_test "rs6000_pcrel_p (cfun)")
(const_int 4)
(const_int 8)))])
(define_insn "*call_value_nonlocal_aix<mode>"
[(set (match_operand 0 "" "")
......@@ -10623,11 +10649,14 @@
}
[(set_attr "type" "branch")
(set (attr "length")
(if_then_else (match_test "IS_NOMARK_TLSGETADDR (operands[2])")
(if_then_else (match_test "TARGET_CMODEL != CMODEL_SMALL")
(const_int 16)
(const_int 12))
(const_int 8)))])
(plus (if_then_else (match_test "IS_NOMARK_TLSGETADDR (operands[2])")
(if_then_else (match_test "TARGET_CMODEL != CMODEL_SMALL")
(const_int 8)
(const_int 4))
(const_int 0))
(if_then_else (match_test "rs6000_pcrel_p (cfun)")
(const_int 4)
(const_int 8))))])
;; Call to indirect functions with the AIX abi using a 3 word descriptor.
;; Operand0 is the addresss of the function to call
......@@ -10700,6 +10729,21 @@
(const_string "12")
(const_string "8")))])
(define_insn "*call_indirect_pcrel<mode>"
[(call (mem:SI (match_operand:P 0 "indirect_call_operand" "c,*l,X"))
(match_operand 1))
(clobber (reg:P LR_REGNO))]
"rs6000_pcrel_p (cfun)"
{
return rs6000_indirect_call_template (operands, 0);
}
[(set_attr "type" "jmpreg")
(set (attr "length")
(if_then_else (and (match_test "!rs6000_speculate_indirect_jumps")
(match_test "which_alternative != 1"))
(const_string "8")
(const_string "4")))])
(define_insn "*call_value_indirect_elfv2<mode>"
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:P 1 "indirect_call_operand" "c,*l,X"))
......@@ -10728,6 +10772,31 @@
(const_string "12")
(const_string "8"))))])
(define_insn "*call_value_indirect_pcrel<mode>"
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:P 1 "indirect_call_operand" "c,*l,X"))
(match_operand:P 2 "unspec_tls" "")))
(clobber (reg:P LR_REGNO))]
"rs6000_pcrel_p (cfun)"
{
if (IS_NOMARK_TLSGETADDR (operands[2]))
rs6000_output_tlsargs (operands);
return rs6000_indirect_call_template (operands, 1);
}
[(set_attr "type" "jmpreg")
(set (attr "length")
(plus
(if_then_else (match_test "IS_NOMARK_TLSGETADDR (operands[2])")
(if_then_else (match_test "TARGET_CMODEL != CMODEL_SMALL")
(const_int 8)
(const_int 4))
(const_int 0))
(if_then_else (and (match_test "!rs6000_speculate_indirect_jumps")
(match_test "which_alternative != 1"))
(const_string "8")
(const_string "4"))))])
;; Call subroutine returning any type.
(define_expand "untyped_call"
[(parallel [(call (match_operand 0 "")
......
2019-05-29 Bill Schmidt <wschmidt@linux.ibm.com>
* gcc.target/powerpc/notoc-direct-1.c: New.
* gcc.target/powerpc/pcrel-sibcall-1.c: New.
2019-05-29 Jakub Jelinek <jakub@redhat.com>
PR c++/90598
......
/* { dg-do compile } */
/* { dg-options "-mdejagnu-cpu=future -O2" } */
/* { dg-require-effective-target powerpc_elfv2 } */
/* Test that calls generated from PC-relative code are
annotated with @notoc. */
extern int yy0 (int);
extern void yy1 (int);
int zz0 (void) __attribute__((noinline));
void zz1 (int) __attribute__((noinline));
int xx (void)
{
yy1 (7);
return yy0 (5);
}
int zz0 ()
{
asm ("");
return 16;
};
void zz1 (int a __attribute__((__unused__)))
{
asm ("");
};
int ww (void)
{
zz1 (zz0 ());
return 4;
}
/* { dg-final { scan-assembler {yy1@notoc} } } */
/* { dg-final { scan-assembler {yy0@notoc} } } */
/* { dg-final { scan-assembler {zz1@notoc} } } */
/* { dg-final { scan-assembler {zz0@notoc} } } */
/* { dg-do compile } */
/* { dg-options "-mdejagnu-cpu=future -O2" } */
/* { dg-require-effective-target powerpc_elfv2 } */
/* Test that potential sibcalls are not generated when the caller preserves
the TOC and the callee doesn't, or vice versa. */
int x (void) __attribute__((noinline));
int y (void) __attribute__((noinline));
int xx (void) __attribute__((noinline));
int x (void)
{
return 1;
}
int y (void)
{
return 2;
}
int sib_call (void)
{
return x ();
}
#pragma GCC target ("cpu=power9")
int normal_call (void)
{
return y ();
}
int xx (void)
{
return 1;
}
#pragma GCC target ("cpu=future")
int notoc_call (void)
{
return xx ();
}
/* { dg-final { scan-assembler {\mb x@notoc\M} } } */
/* { dg-final { scan-assembler {\mbl y\M} } } */
/* { dg-final { scan-assembler {\mbl xx@notoc\M} } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment