Skip to content

Commit d31ead3

Browse files
committed
refs #206: further shift improvements
1 parent d1cc3ac commit d31ead3

File tree

2 files changed

+322
-65
lines changed

2 files changed

+322
-65
lines changed

gcc/bbb-opts.c

Lines changed: 196 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -958,22 +958,8 @@ class insn_info
958958

959959
/** mark usage here as 32 bit. */
960960
inline void
961-
mark_myuse (int regno)
961+
mark_myuse (int regno, int sz)
962962
{
963-
myuse8 |= 1 << regno;
964-
myuse16 |= 1 << regno;
965-
myuse32 |= 1 << regno;
966-
use8 |= 1 << regno;
967-
use16 |= 1 << regno;
968-
use32 |= 1 << regno;
969-
}
970-
971-
/** mark usage here as 32 bit. */
972-
inline void
973-
mark_myuse (rtx reg)
974-
{
975-
int regno = REGNO(reg);
976-
int sz = GET_MODE_SIZE(GET_MODE(reg));
977963
myuse8 |= 1 << regno;
978964
use8 |= 1 << regno;
979965
if (sz > 1)
@@ -988,6 +974,15 @@ class insn_info
988974
}
989975
}
990976

977+
/** mark usage here as 32 bit. */
978+
inline void
979+
mark_myuse (rtx reg)
980+
{
981+
int regno = REGNO(reg);
982+
int sz = GET_MODE_SIZE(GET_MODE(reg));
983+
mark_myuse(regno, sz);
984+
}
985+
991986
/** mark usage as 32 bit. */
992987
inline void
993988
mark_use (int regno)
@@ -1526,11 +1521,11 @@ insn_info::scan ()
15261521
if (sz && sz <= 64)
15271522
{
15281523
mark_hard (0);
1529-
mark_myuse (0);
1524+
mark_myuse (0, sz/8);
15301525
if (sz > 32)
15311526
{
15321527
mark_hard (1);
1533-
mark_myuse (1);
1528+
mark_myuse (1, 4);
15341529
}
15351530
}
15361531
}
@@ -1545,13 +1540,13 @@ insn_info::scan ()
15451540
{
15461541
if (REG_NREGS(reg) > 1)
15471542
for (unsigned r = REGNO(reg); r < END_REGNO (reg); ++r)
1548-
mark_myuse (r);
1543+
mark_myuse (r, 4);
15491544
else
15501545
mark_myuse (reg);
15511546
}
15521547
}
15531548
/* mark stack pointer used. there could be parameters on stack*/
1554-
mark_myuse (15);
1549+
mark_myuse (15, 4);
15551550
/* mark scratch registers. */
15561551
mark_def (0);
15571552
mark_def (1);
@@ -1568,7 +1563,7 @@ insn_info::scan ()
15681563
if (global_regs[i])
15691564
{
15701565
mark_hard (i);
1571-
mark_myuse(i);
1566+
mark_myuse(i, 4);
15721567
}
15731568
}
15741569
scan_rtx (pattern);
@@ -1583,38 +1578,23 @@ insn_info::scan_rtx (rtx x)
15831578
if (!REG_P(x))
15841579
x = XEXP(x, 0);
15851580

1586-
int msize = GET_MODE_SIZE(GET_MODE(x));
15871581
int n0 = REG_NREGS(x);
15881582
if (n0 > 1)
15891583
{
15901584
for (int n = n0, r = REGNO(x); n > 0; --n, ++r)
15911585
{
1592-
mark_myuse (r);
1586+
mark_myuse (r, 4);
15931587
multi_reg |= 1<<r;
15941588
}
15951589
}
15961590
else
1597-
{
1598-
unsigned regno = REGNO(x);
1599-
myuse8 |= 1 << regno;
1600-
use8 |= 1 << regno;
1601-
if (msize > 1)
1602-
{
1603-
myuse16 |= 1 << regno;
1604-
use16 |= 1 << regno;
1605-
if (msize > 2)
1606-
{
1607-
myuse32 |= 1 << regno;
1608-
use32 |= 1 << regno;
1609-
}
1610-
}
1611-
}
1591+
mark_myuse(x);
16121592
return;
16131593
}
16141594

16151595
if (x == cc0_rtx)
16161596
{
1617-
mark_myuse (FIRST_PSEUDO_REGISTER);
1597+
mark_myuse (FIRST_PSEUDO_REGISTER, 4);
16181598
return;
16191599
}
16201600

@@ -2145,7 +2125,7 @@ insn_info::absolute2base (unsigned regno, unsigned base, rtx with_symbol)
21452125
SET_INSN_DELETED(insn);
21462126
insn = emit_insn_after (pattern, insn);
21472127

2148-
mark_myuse (regno);
2128+
mark_myuse (regno, 4);
21492129

21502130
insn2info->insert (std::make_pair (insn, this));
21512131
}
@@ -3572,7 +3552,6 @@ opt_const_cmp_to_sub (void)
35723552
for (unsigned index = infos->size () - 2; index > 0; --index)
35733553
{
35743554
insn_info & i1 = (*infos)[index];
3575-
35763555
/* we wan't a compare or tst insn, */
35773556
if (!i1.is_compare ())
35783557
continue;
@@ -5860,6 +5839,179 @@ void print_inline_info()
58605839
printf(":bbb: inline weight = %4d\t%s\n", count, get_current_function_name ());
58615840
}
58625841

5842+
static unsigned
5843+
opt_shift (void)
5844+
{
5845+
unsigned change_count = 0;
5846+
for (int index = infos->size () - 2; index > 0; --index)
5847+
{
5848+
insn_info & ii = (*infos)[index];
5849+
// it's a shift ?
5850+
if (ii.get_mode() != SImode || !ii.get_dst_reg() || !(ii.get_src_op() == ASHIFT || ii.get_src_op() == ASHIFTRT || ii.get_src_op() == LSHIFTRT))
5851+
continue;
5852+
5853+
int dy = ii.get_dst_regno();
5854+
5855+
// check the next insn if only a word/byte is used.
5856+
insn_info & next = (*infos)[index + 1];
5857+
int usedSize = next.getX(dy);
5858+
if (usedSize >= 4)
5859+
continue;
5860+
5861+
// debug(ii.get_insn());
5862+
machine_mode mode = usedSize == 1 ? QImode : HImode;
5863+
int srcop = ii.get_src_op(); // can be changed
5864+
5865+
// are there insns like move.l dx,dy in front of that can be changed too?
5866+
bool reduce = false;
5867+
for (int jndex = index - 1; jndex > 0; --jndex)
5868+
{
5869+
insn_info * jj = &(*infos)[jndex];
5870+
if (jj->is_label())
5871+
break;
5872+
5873+
// skip unrelated insns
5874+
if (!jj->is_def(dy) && !jj->is_myuse(dy))
5875+
continue;
5876+
5877+
// we want sign_extend or set
5878+
if (!jj->is_def(dy))
5879+
break;
5880+
5881+
// debug(jj->get_insn());
5882+
5883+
// there might be the use of a temp register:
5884+
// moveq #0,dx
5885+
// move.w dy,dx
5886+
// move.l dx,dy <--- this one
5887+
if (jj->get_mode() == SImode && !jj->get_src_op() && jj->get_src_reg())
5888+
{
5889+
int dx = jj->get_src_regno();
5890+
// search the assignment for dx
5891+
5892+
for (int kndex = jndex - 1; kndex > 0; --kndex)
5893+
{
5894+
insn_info * kk = &(*infos)[kndex];
5895+
if (kk->is_label())
5896+
break;
5897+
5898+
// skip unrelated insns
5899+
if (!kk->is_def(dx) && !kk->is_myuse(dx))
5900+
continue;
5901+
5902+
// we want sign_extend or set
5903+
if (!kk->is_def(dx))
5904+
break;
5905+
5906+
if (kk->get_mode() == mode && !kk->get_src_op())
5907+
{
5908+
if (srcop == ASHIFTRT)
5909+
{
5910+
// we need a clr.l dx
5911+
insn_info * ll = &(*infos)[kndex - 1];
5912+
if (ll->get_dst_reg() && ll->get_dst_regno() == dx && ll->get_mode() == SImode
5913+
&& !ll->get_src_op() && !ll->is_src_mem()
5914+
&& ll->get_src_intval() == 0)
5915+
{
5916+
srcop = LSHIFTRT;
5917+
reduce = true;
5918+
}
5919+
}
5920+
else
5921+
reduce = true;
5922+
5923+
// if dx is dead after assignment to dy
5924+
if (reduce && is_reg_dead(dx, jndex))
5925+
{
5926+
// assign src to dy unless src == dy
5927+
if (!kk->get_src_reg() || kk->get_src_regno() != dy)
5928+
{
5929+
rtx set = single_set(kk->get_insn());
5930+
rtx x = gen_rtx_SET(gen_rtx_REG (mode, dy), SET_SRC (set));
5931+
rtx notes = REG_NOTES (ii.get_insn());
5932+
rtx_insn * neu = emit_insn_before (x, kk->get_insn ());
5933+
REG_NOTES(neu) = notes;
5934+
}
5935+
SET_INSN_DELETED(kk->get_insn());
5936+
SET_INSN_DELETED(jj->get_insn());
5937+
}
5938+
}
5939+
break;
5940+
}
5941+
break;
5942+
}
5943+
// there might be one or two sign extends
5944+
// ext.w dy
5945+
// ext.l dy
5946+
else if (jj->get_mode() == SImode && jj->get_src_op() == SIGN_EXTEND)
5947+
{
5948+
if (GET_MODE(jj->get_src_reg()) == mode)
5949+
{
5950+
SET_INSN_DELETED(jj->get_insn());
5951+
reduce = true;
5952+
}
5953+
else if (mode == QImode && GET_MODE(jj->get_src_reg()) == HImode)
5954+
{
5955+
// check previous insn for 2nd SIGN_EXTEND
5956+
insn_info * ll = &(*infos)[jndex - 1];
5957+
if (ll->get_dst_reg() && ll->get_dst_regno() == dy
5958+
&& ll->get_src_op() == SIGN_EXTEND
5959+
&& GET_MODE(ll->get_src_reg()) == QImode)
5960+
{
5961+
SET_INSN_DELETED(ll->get_insn());
5962+
SET_INSN_DELETED(jj->get_insn());
5963+
reduce = true;
5964+
}
5965+
}
5966+
}
5967+
// move.b ..,dy or move.w ...,dy
5968+
else if (jj->get_mode() == mode)
5969+
{
5970+
if (srcop == ASHIFT)
5971+
reduce = true;
5972+
else if (srcop == ASHIFTRT)
5973+
{
5974+
// we need a clr.l dy
5975+
insn_info * ll = &(*infos)[jndex - 1];
5976+
if (ll->get_dst_reg() && ll->get_dst_regno() == dy && ll->get_mode() == SImode
5977+
&& !ll->get_src_op() && !ll->is_src_mem()
5978+
&& ll->get_src_intval() == 0)
5979+
{
5980+
srcop = LSHIFTRT;
5981+
reduce = true;
5982+
}
5983+
}
5984+
}
5985+
5986+
break;
5987+
}
5988+
5989+
if (reduce)
5990+
{
5991+
rtx op1 = XEXP(SET_SRC(PATTERN(ii.get_insn())), 1);
5992+
rtx r = gen_rtx_REG (mode, dy);
5993+
rtx shift;
5994+
if (srcop == ASHIFT)
5995+
shift = gen_rtx_ASHIFT (mode, r, op1);
5996+
else if (srcop == ASHIFTRT)
5997+
shift = gen_rtx_ASHIFTRT (mode, r, op1);
5998+
else
5999+
shift = gen_rtx_LSHIFTRT (mode, r, op1);
6000+
rtx x = gen_rtx_SET(r, shift);
6001+
rtx notes = REG_NOTES (ii.get_insn());
6002+
SET_INSN_DELETED(ii.get_insn());
6003+
6004+
rtx_insn * neu = emit_insn_before (x, ii.get_insn ());
6005+
REG_NOTES(neu) = notes;
6006+
++change_count;
6007+
6008+
log ("(h) long shift replaced with shorter variant for %s\n", reg_names[ii.get_dst_regno ()]);
6009+
}
6010+
}
6011+
return change_count;
6012+
}
6013+
6014+
58636015
namespace
58646016
{
58656017

@@ -5943,6 +6095,7 @@ namespace
59436095
bool do_const_cmp_to_sub = strchr (string_bbb_opts, 'c') || strchr (string_bbb_opts, '+');
59446096
bool do_elim_dead_assign = strchr (string_bbb_opts, 'e') || strchr (string_bbb_opts, '+');
59456097
bool do_shrink_stack_frame = strchr (string_bbb_opts, 'f') || strchr (string_bbb_opts, '+');
6098+
bool do_handle_shift = strchr (string_bbb_opts, 'h') || strchr (string_bbb_opts, '+');
59466099
bool do_autoinc = strchr (string_bbb_opts, 'i') || strchr (string_bbb_opts, '+');
59476100
bool do_lea_mem = strchr (string_bbb_opts, 'l') || strchr (string_bbb_opts, '+');
59486101
bool do_merge_add = strchr (string_bbb_opts, 'm') || strchr (string_bbb_opts, '+');
@@ -5959,6 +6112,9 @@ namespace
59596112
unsigned r = update_insns ();
59606113
if (!r)
59616114
{
6115+
if (do_handle_shift && opt_shift())
6116+
update_insns ();
6117+
59626118
if (do_lea_mem && opt_lea_mem())
59636119
update_insns ();
59646120

0 commit comments

Comments
 (0)