This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] S/390: Enable literal pool handling to deal with hot/cold sections
Hi Uli,
I've applied the attached including your proposed changes after
re-testing on s390 and s390x.
Bye,
-Andreas-
2008-02-13 Andreas Krebbel <krebbel1@de.ibm.com>
* config/s390/s390.c (struct constant_pool): New field
emit_pool_after added.
(s390_mainpool_start): Set the emit_pool_after flag according
to the section switch notes.
(s390_mainpool_finish): Consider emit_pool_after when emitting
the literal pool at the end of the function.
(s390_chunkify_start): Force literal pool splits at section
switch notes.
Index: gcc/config/s390/s390.c
===================================================================
*** gcc/config/s390/s390.c.orig 2008-02-13 10:08:54.000000000 +0100
--- gcc/config/s390/s390.c 2008-02-13 16:55:36.000000000 +0100
*************** struct constant_pool
*** 5325,5330 ****
--- 5325,5331 ----
rtx first_insn;
rtx pool_insn;
bitmap insns;
+ rtx emit_pool_after;
struct constant *constants[NR_C_MODES];
struct constant *execute;
*************** s390_alloc_pool (void)
*** 5351,5356 ****
--- 5352,5358 ----
pool->pool_insn = NULL_RTX;
pool->insns = BITMAP_ALLOC (NULL);
pool->size = 0;
+ pool->emit_pool_after = NULL_RTX;
return pool;
}
*************** s390_mainpool_start (void)
*** 5681,5686 ****
--- 5683,5689 ----
{
struct constant_pool *pool;
rtx insn;
+ bool in_pool_section_p = false;
pool = s390_alloc_pool ();
*************** s390_mainpool_start (void)
*** 5693,5698 ****
--- 5696,5702 ----
{
gcc_assert (!pool->pool_insn);
pool->pool_insn = insn;
+ in_pool_section_p = true;
}
if (!TARGET_CPU_ZARCH && s390_execute_label (insn))
*************** s390_mainpool_start (void)
*** 5710,5715 ****
--- 5714,5733 ----
s390_add_constant (pool, constant, mode);
}
}
+
+ /* If hot/cold partitioning is enabled we have to make sure that
+ the literal pool is emitted in the same section where the
+ initialization of the literal pool base pointer takes place.
+ emit_pool_after is only used in the non-overflow case on non
+ Z cpus where we can emit the literal pool at the end of the
+ function body within the text section. */
+ if (NOTE_P (insn)
+ && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
+ {
+ if (in_pool_section_p)
+ pool->emit_pool_after = PREV_INSN (insn);
+ in_pool_section_p = !in_pool_section_p;
+ }
}
gcc_assert (pool->pool_insn || pool->size == 0);
*************** s390_mainpool_start (void)
*** 5724,5729 ****
--- 5742,5752 ----
pool = NULL;
}
+ /* If the functions ends with the section where the literal pool
+ should be emitted set the marker to its end. */
+ if (pool && in_pool_section_p)
+ pool->emit_pool_after = get_last_insn ();
+
return pool;
}
*************** s390_mainpool_finish (struct constant_po
*** 5771,5777 ****
/* On S/390, if the total size of the function's code plus literal pool
does not exceed 4096 bytes, we use BASR to set up a function base
pointer, and emit the literal pool at the end of the function. */
! else if (INSN_ADDRESSES (INSN_UID (get_last_insn ()))
+ pool->size + 8 /* alignment slop */ < 4096)
{
insn = gen_main_base_31_small (base_reg, pool->label);
--- 5794,5800 ----
/* On S/390, if the total size of the function's code plus literal pool
does not exceed 4096 bytes, we use BASR to set up a function base
pointer, and emit the literal pool at the end of the function. */
! else if (INSN_ADDRESSES (INSN_UID (pool->emit_pool_after))
+ pool->size + 8 /* alignment slop */ < 4096)
{
insn = gen_main_base_31_small (base_reg, pool->label);
*************** s390_mainpool_finish (struct constant_po
*** 5782,5788 ****
insn = emit_label_after (pool->label, insn);
INSN_ADDRESSES_NEW (insn, -1);
! insn = get_last_insn ();
pool->pool_insn = emit_insn_after (gen_pool (const0_rtx), insn);
INSN_ADDRESSES_NEW (pool->pool_insn, -1);
--- 5805,5815 ----
insn = emit_label_after (pool->label, insn);
INSN_ADDRESSES_NEW (insn, -1);
! /* emit_pool_after will be set by s390_mainpool_start to the
! last insn of the section where the literal pool should be
! emitted. */
! insn = pool->emit_pool_after;
!
pool->pool_insn = emit_insn_after (gen_pool (const0_rtx), insn);
INSN_ADDRESSES_NEW (pool->pool_insn, -1);
*************** s390_chunkify_start (void)
*** 5881,5886 ****
--- 5908,5915 ----
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
+ bool section_switch_p = false;
+
/* Check for pending LTREL_BASE. */
if (INSN_P (insn))
{
*************** s390_chunkify_start (void)
*** 5935,5940 ****
--- 5964,5972 ----
gcc_assert (!pending_ltrel);
}
+ if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
+ section_switch_p = true;
+
if (!curr_pool
|| INSN_ADDRESSES_SIZE () <= (size_t) INSN_UID (insn)
|| INSN_ADDRESSES (INSN_UID (insn)) == -1)
*************** s390_chunkify_start (void)
*** 5962,5968 ****
extra_size += 6;
if (chunk_size < S390_POOL_CHUNK_MIN
! && curr_pool->size < S390_POOL_CHUNK_MIN)
continue;
/* Pool chunks can only be inserted after BARRIERs ... */
--- 5994,6001 ----
extra_size += 6;
if (chunk_size < S390_POOL_CHUNK_MIN
! && curr_pool->size < S390_POOL_CHUNK_MIN
! && !section_switch_p)
continue;
/* Pool chunks can only be inserted after BARRIERs ... */
*************** s390_chunkify_start (void)
*** 5974,5994 ****
}
/* ... so if we don't find one in time, create one. */
! else if ((chunk_size > S390_POOL_CHUNK_MAX
! || curr_pool->size > S390_POOL_CHUNK_MAX))
{
rtx label, jump, barrier;
! /* We can insert the barrier only after a 'real' insn. */
! if (GET_CODE (insn) != INSN && GET_CODE (insn) != CALL_INSN)
! continue;
! if (get_attr_length (insn) == 0)
! continue;
!
! /* Don't separate LTREL_BASE from the corresponding
LTREL_OFFSET load. */
! if (pending_ltrel)
! continue;
label = gen_label_rtx ();
jump = emit_jump_insn_after (gen_jump (label), insn);
--- 6007,6039 ----
}
/* ... so if we don't find one in time, create one. */
! else if (chunk_size > S390_POOL_CHUNK_MAX
! || curr_pool->size > S390_POOL_CHUNK_MAX
! || section_switch_p)
{
rtx label, jump, barrier;
! if (!section_switch_p)
! {
! /* We can insert the barrier only after a 'real' insn. */
! if (GET_CODE (insn) != INSN && GET_CODE (insn) != CALL_INSN)
! continue;
! if (get_attr_length (insn) == 0)
! continue;
! /* Don't separate LTREL_BASE from the corresponding
LTREL_OFFSET load. */
! if (pending_ltrel)
! continue;
! }
! else
! {
! gcc_assert (!pending_ltrel);
!
! /* The old pool has to end before the section switch
! note in order to make it part of the current
! section. */
! insn = PREV_INSN (insn);
! }
label = gen_label_rtx ();
jump = emit_jump_insn_after (gen_jump (label), insn);