[PATCH] Run life analysis after optimize_mode_switching pass.

Uros Bizjak ubizjak@gmail.com
Tue Jul 12 13:29:00 GMT 2005


Hello!

If optimize_mode_switching pass inserts instructions that change
global registers, they change global register life info at boundaries
of basic blocks. To avoid the mess, global register life data should
be updated just after optimize_mode_switching pass.

Additionally, a global variable mode_switching_completed was added.
This variable is nonzero after mode_switching pass ends (no kidding
:-).  This variable can be used in ix86_epilogue_uses (),
ix86_call_insn_uses () and ix86_call_insn_sets () functions, that need
correct emms/efpu insn already  inserted to maintain correct register
life data.

By using this flag, these functions are "activated" in just added
register life analysis after mode switching pass, so correct global
register life info is supplied to register allocator.

Without this patch, global register info in loops is wrong for x87/MMX
switching pass, so reload1.c ICEs with 'unable to spill...' message.

Patch was regtested and bootstrapped (with changes to i386.c shown
below) on i686-pc-linux-gnu.

BTW: These problems were found with a follow-up patch to MMX/x87
switching that enables vector operations on MMX registers (with emms
insn placed correctly). With attached patch, I was able to compile
(for example):

#define N 16

int ia[N];
int ic[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45};
int ib[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45};


int test () {
	int i;

	for (i = 0; i < 4; i++)
		ia[i] = ib[i] + ic[i];

	return 0;
}

with 'gcc -O2 -ftree-vectorize -mmmx' into:

test:
	pushl	%ebp
	xorl	%eax, %eax
	movl	%esp, %ebp
	.p2align 4,,15
.L2:
	movq	ib(,%eax,8), %mm0
	paddd	ic(,%eax,8), %mm0
	movq	%mm0, ia(,%eax,8)
	incl	%eax
	cmpl	$2, %eax
	jne	.L2
	emms
	xorl	%eax, %eax
	popl	%ebp
	ret

The relevant part of i386.c should be changed to include
mode_switching_completed flag:

--cut here--
/* Return true to prevent register allocator from allocating registers
   from the unit that is not active.  */

bool
ix86_epilogue_uses (int regno)
{
  int mode;

  if (! mode_switching_completed)
    return false;

  mode = ix86_mode_exit (I387_FPU_MODE);

  if (mode == FPU_MODE_MMX)
    return TARGET_80387 && FP_REGNO_P (regno);
  else
    return TARGET_MMX && MMX_REGNO_P (regno);
}

/* Return RTX code of additional register that CALL_INSN uses.
   This function is used to maintain correct register life
   information before CALL_INSN in case of MMX/x87 switching.  */

rtx
ix86_call_insn_uses (rtx insn)
{
  int mode;

  if (! mode_switching_completed)
    return NULL_RTX;

  gcc_assert (CALL_P (insn));

  mode = ix86_mode_needed (I387_FPU_MODE, insn);
  if (mode == FPU_MODE_MMX)
    {
      if (TARGET_80387)
	return gen_rtx_REG (ALLREGSmode, FIRST_FLOAT_REG);
    }
  else
    {
      if (TARGET_MMX)
	return gen_rtx_REG (ALLREGSmode, FIRST_MMX_REG);
    }

  return NULL_RTX;
}

/* Return RTX code of additional register that CALL_INSN sets.
   This function is used to maintain correct register life
   information after CALL_INSN in case of MMX/x87 switching.  */

rtx
ix86_call_insn_sets (rtx insn)
{
  int mode;

  if (! mode_switching_completed)
    return NULL_RTX;

  gcc_assert (CALL_P (insn));

  /* Note that current mode in call to ix86_mode_after
     is arbitrary for CALL_INSNs.  */
  mode = ix86_mode_after (I387_FPU_MODE, 0, insn);
  if (mode == FPU_MODE_MMX)
    {
      if (TARGET_80387)
	return gen_rtx_REG (ALLREGSmode, FIRST_FLOAT_REG);
    }
  else
    {
      if (TARGET_MMX)
	return gen_rtx_REG (ALLREGSmode, FIRST_MMX_REG);
    }

  return NULL_RTX;
}

--cut here--

2005-07-12  Uros Bizjak  <uros@kss-loka.si>

	* rtl.h (extern int mode_switching_completed): New.
	* mode-switching.c (mode_switching_completed): New global variable.
	(rest_of_handle_mode_switching): Set mode_switching_compleded
	after optimize_mode_switching pass. Perform life analysis after
	optimize_mode_switching pass.

Uros.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: opmode.diff
Type: application/octet-stream
Size: 1360 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20050712/57b6873d/attachment.obj>


More information about the Gcc-patches mailing list