OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gnu-src/] [gcc-4.5.1/] [gcc-4.5.1-or32-1.0rc1/] [gcc/] [df-byte-scan.c] - Diff between revs 280 and 338

Only display areas with differences | Details | Blame | View Log

Rev 280 Rev 338
/* Scanning of rtl byte level scanning for dataflow analysis.
/* Scanning of rtl byte level scanning for dataflow analysis.
   Copyright (C) 2008  Free Software Foundation, Inc.
   Copyright (C) 2008  Free Software Foundation, Inc.
   Contributed by Kenneth Zadeck (zadeck@naturalbridge.com).
   Contributed by Kenneth Zadeck (zadeck@naturalbridge.com).
 
 
This file is part of GCC.
This file is part of GCC.
 
 
GCC is free software; you can redistribute it and/or modify it under
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
Software Foundation; either version 3, or (at your option) any later
version.
version.
 
 
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.
for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
<http://www.gnu.org/licenses/>.  */
 
 
#include "config.h"
#include "config.h"
#include "system.h"
#include "system.h"
#include "coretypes.h"
#include "coretypes.h"
#include "tm.h"
#include "tm.h"
#include "rtl.h"
#include "rtl.h"
#include "tm_p.h"
#include "tm_p.h"
#include "df.h"
#include "df.h"
#include "output.h"
#include "output.h"
#include "dbgcnt.h"
#include "dbgcnt.h"
 
 
/* The following suite of functions provides bytewise modeling of REFs
/* The following suite of functions provides bytewise modeling of REFs
   which are struct df_ref.  START_BYTE and LAST_BYTE are returned.
   which are struct df_ref.  START_BYTE and LAST_BYTE are returned.
   These can be used as indexes into bitmaps.  The indexes are
   These can be used as indexes into bitmaps.  The indexes are
   normalized so that 0 is the lowest numbered byte, of the inner
   normalized so that 0 is the lowest numbered byte, of the inner
   register according to the natural ordering of the machine.
   register according to the natural ordering of the machine.
 
 
   This code is designed to be used in backwards scans (which is, of
   This code is designed to be used in backwards scans (which is, of
   course, the way all dataflow scanning should really be done).  It
   course, the way all dataflow scanning should really be done).  It
   would require a lot of reworking of the api to make it work in a
   would require a lot of reworking of the api to make it work in a
   forwards scanning world.  */
   forwards scanning world.  */
 
 
 
 
/* Helper for df_compute_accessed_bytes.  Ref is some sort of extract.
/* Helper for df_compute_accessed_bytes.  Ref is some sort of extract.
   Return true if this effects the entire reg in REF.  Return false if
   Return true if this effects the entire reg in REF.  Return false if
   otherwise and set START_BYTE and LAST_BYTE.  See the description of
   otherwise and set START_BYTE and LAST_BYTE.  See the description of
   df_compute_accessed_bytes for a description of MM.  */
   df_compute_accessed_bytes for a description of MM.  */
 
 
static bool
static bool
df_compute_accessed_bytes_extract (df_ref ref,
df_compute_accessed_bytes_extract (df_ref ref,
                                   enum df_mm mm ,
                                   enum df_mm mm ,
                                   unsigned int *start_byte,
                                   unsigned int *start_byte,
                                   unsigned int *last_byte)
                                   unsigned int *last_byte)
{
{
  int start;
  int start;
  int last;
  int last;
  rtx reg = DF_REF_REG (ref);
  rtx reg = DF_REF_REG (ref);
  enum machine_mode m1;
  enum machine_mode m1;
  int m1_size;
  int m1_size;
  enum machine_mode m2;
  enum machine_mode m2;
  int m2_size;
  int m2_size;
 
 
  /* (*_extract:M1 (reg:M2 X) WIDTH POS)
  /* (*_extract:M1 (reg:M2 X) WIDTH POS)
     (*_extract:M1 (subreg:M1 (reg:M2 X N) WIDTH POS)
     (*_extract:M1 (subreg:M1 (reg:M2 X N) WIDTH POS)
 
 
     This is a bitfield extraction.  The assignment clobbers/extracts
     This is a bitfield extraction.  The assignment clobbers/extracts
     exactly the bits named by WIDTH and POS and does not affect the
     exactly the bits named by WIDTH and POS and does not affect the
     other bits in register X.  It is also technically possible that
     other bits in register X.  It is also technically possible that
     the bits asked for are longer than units per word.  */
     the bits asked for are longer than units per word.  */
 
 
  int offset = DF_REF_EXTRACT_OFFSET (ref);
  int offset = DF_REF_EXTRACT_OFFSET (ref);
  int width = DF_REF_EXTRACT_WIDTH (ref);
  int width = DF_REF_EXTRACT_WIDTH (ref);
 
 
  if (width == -1 || offset == -1)
  if (width == -1 || offset == -1)
    return true;
    return true;
 
 
  m1 = DF_REF_EXTRACT_MODE (ref);
  m1 = DF_REF_EXTRACT_MODE (ref);
  m1_size = GET_MODE_SIZE (m1);
  m1_size = GET_MODE_SIZE (m1);
 
 
  gcc_assert (m1_size <= UNITS_PER_WORD);
  gcc_assert (m1_size <= UNITS_PER_WORD);
 
 
  /* There is nothing to do if this is a pure big or small endian
  /* There is nothing to do if this is a pure big or small endian
     machine, but if the machine is a pastiche, we have to convert the
     machine, but if the machine is a pastiche, we have to convert the
     bit offsets into byte offsets.  This is only possible because we
     bit offsets into byte offsets.  This is only possible because we
     do not care about individual bits because this conversion may
     do not care about individual bits because this conversion may
     make the bits non-contiguous.  */
     make the bits non-contiguous.  */
  if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)
  if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)
    offset = GET_MODE_BITSIZE (m1_size) - (offset + width);
    offset = GET_MODE_BITSIZE (m1_size) - (offset + width);
 
 
  /* The offset is now in the same order as the subreg_byte.  */
  /* The offset is now in the same order as the subreg_byte.  */
  if (GET_CODE (reg) == SUBREG)
  if (GET_CODE (reg) == SUBREG)
    {
    {
      m2 = GET_MODE (SUBREG_REG (reg));
      m2 = GET_MODE (SUBREG_REG (reg));
      m2_size = GET_MODE_SIZE (m2);
      m2_size = GET_MODE_SIZE (m2);
      if (m1_size > m2_size)
      if (m1_size > m2_size)
        /* If it is paradoxical, subreg_byte will be zero.  */
        /* If it is paradoxical, subreg_byte will be zero.  */
        offset -= subreg_lowpart_offset (m2, m1) * BITS_PER_UNIT;
        offset -= subreg_lowpart_offset (m2, m1) * BITS_PER_UNIT;
      else
      else
        offset += SUBREG_BYTE (reg) * BITS_PER_UNIT;
        offset += SUBREG_BYTE (reg) * BITS_PER_UNIT;
    }
    }
  else
  else
    {
    {
      m2 = GET_MODE (reg);
      m2 = GET_MODE (reg);
      m2_size = GET_MODE_SIZE (m2);
      m2_size = GET_MODE_SIZE (m2);
    }
    }
 
 
  if (mm == DF_MM_MUST)
  if (mm == DF_MM_MUST)
    {
    {
      /* For defs (generally), count the byte only if the whole byte
      /* For defs (generally), count the byte only if the whole byte
         is touched.  */
         is touched.  */
      start = (offset + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
      start = (offset + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
      last = (width + offset) / BITS_PER_UNIT;
      last = (width + offset) / BITS_PER_UNIT;
 
 
      /* In the case where there is nothing, start may be one larger
      /* In the case where there is nothing, start may be one larger
         than last, we canonize this to return zeros.  This keeps
         than last, we canonize this to return zeros.  This keeps
         computations of length from being negative.  */
         computations of length from being negative.  */
      if (start >= last)
      if (start >= last)
        {
        {
          start = 0;
          start = 0;
          last = 0;
          last = 0;
        }
        }
    }
    }
  else
  else
    {
    {
      /* For uses (generally), count the byte if any part of the byte
      /* For uses (generally), count the byte if any part of the byte
         is touched.  */
         is touched.  */
      start = offset / BITS_PER_UNIT;
      start = offset / BITS_PER_UNIT;
      last = (width + offset + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
      last = (width + offset + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
    }
    }
 
 
  /* Paradoxical truncation.  */
  /* Paradoxical truncation.  */
  if (start < 0)
  if (start < 0)
    start = 0;
    start = 0;
  if (last > m2_size)
  if (last > m2_size)
    last = m2_size;
    last = m2_size;
 
 
  if (dump_file)
  if (dump_file)
    fprintf (dump_file, "    cpb extract regno=%d start=%d last=%d\n",
    fprintf (dump_file, "    cpb extract regno=%d start=%d last=%d\n",
             DF_REF_REGNO (ref), start, last);
             DF_REF_REGNO (ref), start, last);
 
 
  *start_byte = start;
  *start_byte = start;
  *last_byte = last;
  *last_byte = last;
  return false;
  return false;
}
}
 
 
 
 
/* Helper for df_compute_accessed_bytes.  Ref is a strict_low_part.
/* Helper for df_compute_accessed_bytes.  Ref is a strict_low_part.
   Return true if this effects the entire reg in REF. Return false if
   Return true if this effects the entire reg in REF. Return false if
   otherwise and set START_BYTE and LAST_BYTE.  */
   otherwise and set START_BYTE and LAST_BYTE.  */
 
 
static bool
static bool
df_compute_accessed_bytes_strict_low_part (df_ref ref,
df_compute_accessed_bytes_strict_low_part (df_ref ref,
                                           unsigned int *start_byte,
                                           unsigned int *start_byte,
                                           unsigned int *last_byte)
                                           unsigned int *last_byte)
{
{
  int start;
  int start;
  int last;
  int last;
  rtx reg = DF_REF_REG (ref);
  rtx reg = DF_REF_REG (ref);
  enum machine_mode m1;
  enum machine_mode m1;
  int m1_size;
  int m1_size;
  enum machine_mode m2;
  enum machine_mode m2;
  int m2_size;
  int m2_size;
  int offset;
  int offset;
 
 
  /* In order to accommodate multiword subregs of a hardreg, df_scan
  /* In order to accommodate multiword subregs of a hardreg, df_scan
     eats the subreg and it can only be found from the loc.  */
     eats the subreg and it can only be found from the loc.  */
  if (REG_P (reg))
  if (REG_P (reg))
    reg = *(DF_REF_LOC (ref));
    reg = *(DF_REF_LOC (ref));
 
 
  m1 = GET_MODE (reg);
  m1 = GET_MODE (reg);
  m1_size = GET_MODE_SIZE (m1);
  m1_size = GET_MODE_SIZE (m1);
  m2 = GET_MODE (SUBREG_REG (reg));
  m2 = GET_MODE (SUBREG_REG (reg));
  m2_size = GET_MODE_SIZE (m2);
  m2_size = GET_MODE_SIZE (m2);
  offset = SUBREG_BYTE (reg);
  offset = SUBREG_BYTE (reg);
 
 
  /* It does not seem to be meaningful to apply a strict_low_part of a
  /* It does not seem to be meaningful to apply a strict_low_part of a
     paradoxical register.  */
     paradoxical register.  */
  gcc_assert (m1_size <= m2_size);
  gcc_assert (m1_size <= m2_size);
 
 
  /* (set (strict_low_part (subreg:M1 (reg:M2 X) N)) ...)
  /* (set (strict_low_part (subreg:M1 (reg:M2 X) N)) ...)
 
 
  This is a bitfield insertion.  The assignment clobbers exactly the
  This is a bitfield insertion.  The assignment clobbers exactly the
  bits named by the subreg--the M1 bits at position N.  It is also
  bits named by the subreg--the M1 bits at position N.  It is also
  technically possible that the bits asked for are longer than units
  technically possible that the bits asked for are longer than units
  per word.  */
  per word.  */
 
 
  start = offset;
  start = offset;
  last = offset + m1_size;
  last = offset + m1_size;
 
 
  if (dump_file)
  if (dump_file)
    fprintf (dump_file, "    cpb strict low part regno=%d start=%d last=%d\n",
    fprintf (dump_file, "    cpb strict low part regno=%d start=%d last=%d\n",
             DF_REF_REGNO (ref), start, last);
             DF_REF_REGNO (ref), start, last);
 
 
  *start_byte = start;
  *start_byte = start;
  *last_byte = last;
  *last_byte = last;
  return false;
  return false;
}
}
 
 
/* Helper for df_compute_accessed_bytes.  Ref is a naked subreg.
/* Helper for df_compute_accessed_bytes.  Ref is a naked subreg.
   Return true if this effects the entire reg in REF. Return false if
   Return true if this effects the entire reg in REF. Return false if
   otherwise and set START_BYTE and LAST_BYTE.  */
   otherwise and set START_BYTE and LAST_BYTE.  */
 
 
static bool
static bool
df_compute_accessed_bytes_subreg (df_ref ref, unsigned int *start_byte,
df_compute_accessed_bytes_subreg (df_ref ref, unsigned int *start_byte,
                                  unsigned int *last_byte)
                                  unsigned int *last_byte)
 
 
{
{
  /* (subreg:M1 (reg:M2 X) N) */
  /* (subreg:M1 (reg:M2 X) N) */
  int start;
  int start;
  int last;
  int last;
  rtx reg = DF_REF_REG (ref);
  rtx reg = DF_REF_REG (ref);
 
 
  enum machine_mode m1;
  enum machine_mode m1;
  int m1_size;
  int m1_size;
  enum machine_mode m2;
  enum machine_mode m2;
  int m2_size;
  int m2_size;
 
 
  /* In order to accommodate multiword subregs of a hardreg, df_scan
  /* In order to accommodate multiword subregs of a hardreg, df_scan
     eats the subreg and it can only be found from the loc.  */
     eats the subreg and it can only be found from the loc.  */
  if (REG_P (reg))
  if (REG_P (reg))
    reg = *(DF_REF_LOC (ref));
    reg = *(DF_REF_LOC (ref));
 
 
  m1 = GET_MODE (reg);
  m1 = GET_MODE (reg);
  m1_size = GET_MODE_SIZE (m1);
  m1_size = GET_MODE_SIZE (m1);
  m2 = GET_MODE (SUBREG_REG (reg));
  m2 = GET_MODE (SUBREG_REG (reg));
  m2_size = GET_MODE_SIZE (m2);
  m2_size = GET_MODE_SIZE (m2);
 
 
  /* A simple paradoxical subreg just accesses the entire inner reg.  */
  /* A simple paradoxical subreg just accesses the entire inner reg.  */
  if (m1_size >= m2_size)
  if (m1_size >= m2_size)
    return true;
    return true;
 
 
  /* Defs and uses are different in the amount of the reg that touch.  */
  /* Defs and uses are different in the amount of the reg that touch.  */
  if (DF_REF_REG_DEF_P (ref))
  if (DF_REF_REG_DEF_P (ref))
    {
    {
      /* This is an lvalue.  */
      /* This is an lvalue.  */
 
 
      if (m2_size > UNITS_PER_WORD)
      if (m2_size > UNITS_PER_WORD)
        {
        {
          /* The assignment clobbers UNITS_PER_WORD segments of X.
          /* The assignment clobbers UNITS_PER_WORD segments of X.
             Look at the bytes named by the subreg, and expand it to
             Look at the bytes named by the subreg, and expand it to
             cover a UNITS_PER_WORD part of register X.  That part of
             cover a UNITS_PER_WORD part of register X.  That part of
             register X is clobbered, the rest is not.
             register X is clobbered, the rest is not.
 
 
             E.g., (subreg:SI (reg:DI X) 0), where UNITS_PER_WORD is the
             E.g., (subreg:SI (reg:DI X) 0), where UNITS_PER_WORD is the
             size of SImode, clobbers the first SImode part of X, and does
             size of SImode, clobbers the first SImode part of X, and does
             not affect the second SImode part.
             not affect the second SImode part.
 
 
             E.g., (subreg:QI (reg:DI X) 0), where UNITS_PER_WORD is the
             E.g., (subreg:QI (reg:DI X) 0), where UNITS_PER_WORD is the
             size of SImode, clobbers the first SImode part of X, and does
             size of SImode, clobbers the first SImode part of X, and does
             not affect the second SImode part.  Here the QImode byte is
             not affect the second SImode part.  Here the QImode byte is
             expanded to a UNITS_PER_WORD portion of the register for
             expanded to a UNITS_PER_WORD portion of the register for
             purposes of determining what is clobbered.
             purposes of determining what is clobbered.
 
 
             If this is an rvalue, then it touches just the bytes that it
             If this is an rvalue, then it touches just the bytes that it
             talks about.  */
             talks about.  */
          int offset = SUBREG_BYTE (reg);
          int offset = SUBREG_BYTE (reg);
 
 
          start = offset & ~(UNITS_PER_WORD - 1);
          start = offset & ~(UNITS_PER_WORD - 1);
          last = (offset + m1_size + UNITS_PER_WORD - 1)
          last = (offset + m1_size + UNITS_PER_WORD - 1)
            & ~(UNITS_PER_WORD - 1);
            & ~(UNITS_PER_WORD - 1);
        }
        }
      else
      else
        /* Whole register size M2 equal to or smaller than
        /* Whole register size M2 equal to or smaller than
           UNITS_PER_WORD The assignment clobbers the entire register
           UNITS_PER_WORD The assignment clobbers the entire register
           X.  */
           X.  */
        return true;
        return true;
    }
    }
  else
  else
    {
    {
      /* This is an rvalue. It touches just the bytes they explicitly
      /* This is an rvalue. It touches just the bytes they explicitly
         mentioned.  */
         mentioned.  */
      int offset = SUBREG_BYTE (reg);
      int offset = SUBREG_BYTE (reg);
      start = offset;
      start = offset;
      last = start + m1_size;
      last = start + m1_size;
    }
    }
 
 
  if (dump_file)
  if (dump_file)
    fprintf (dump_file, "    cpb subreg regno=%d start=%d last=%d\n",
    fprintf (dump_file, "    cpb subreg regno=%d start=%d last=%d\n",
             DF_REF_REGNO (ref), start, last);
             DF_REF_REGNO (ref), start, last);
 
 
  *start_byte = start;
  *start_byte = start;
  *last_byte = last;
  *last_byte = last;
  return false;
  return false;
}
}
 
 
 
 
/* Compute the set of affected bytes by a store to a pseudo to REF.
/* Compute the set of affected bytes by a store to a pseudo to REF.
   MM is either DF_MM_MAY or DF_MM_MUST.  This is only relevant for
   MM is either DF_MM_MAY or DF_MM_MUST.  This is only relevant for
   the extracts which are not aligned to byte boundaries.  The
   the extracts which are not aligned to byte boundaries.  The
   DF_MM_MAY returns all of the bytes that any bit is set in and the
   DF_MM_MAY returns all of the bytes that any bit is set in and the
   DF_MM_MUST returns only the bytes that are completely covered.  In
   DF_MM_MUST returns only the bytes that are completely covered.  In
   general DF_MM_MAY is used for uses and DF_MM_MUST is used for defs,
   general DF_MM_MAY is used for uses and DF_MM_MUST is used for defs,
   but there are exceptions such as the inner loop of the byte level
   but there are exceptions such as the inner loop of the byte level
   dead code eliminator which needs DF_MM_MAY for the defs to see if
   dead code eliminator which needs DF_MM_MAY for the defs to see if
   it any possible bit could be used.
   it any possible bit could be used.
 
 
   If the store is to the whole register, just return TRUE, if it is
   If the store is to the whole register, just return TRUE, if it is
   to part of the register, return FALSE and set START_BYTE and
   to part of the register, return FALSE and set START_BYTE and
   LAST_BYTE properly.  In the case where fabricated uses are passed
   LAST_BYTE properly.  In the case where fabricated uses are passed
   in, START_BYTE and LAST_BYTE are set to 0 and false is returned.
   in, START_BYTE and LAST_BYTE are set to 0 and false is returned.
   This means that this use can be ignored.  */
   This means that this use can be ignored.  */
 
 
bool
bool
df_compute_accessed_bytes (df_ref ref, enum df_mm mm,
df_compute_accessed_bytes (df_ref ref, enum df_mm mm,
                           unsigned int *start_byte,
                           unsigned int *start_byte,
                           unsigned int *last_byte)
                           unsigned int *last_byte)
{
{
  if (!dbg_cnt (df_byte_scan))
  if (!dbg_cnt (df_byte_scan))
    return true;
    return true;
 
 
  if (!DF_REF_REG_DEF_P (ref)
  if (!DF_REF_REG_DEF_P (ref)
      && DF_REF_FLAGS_IS_SET (ref, DF_REF_READ_WRITE))
      && DF_REF_FLAGS_IS_SET (ref, DF_REF_READ_WRITE))
    {
    {
      if (DF_REF_FLAGS_IS_SET (ref, DF_REF_PRE_POST_MODIFY))
      if (DF_REF_FLAGS_IS_SET (ref, DF_REF_PRE_POST_MODIFY))
        /* Pre/post modify/inc/dec always read and write the entire
        /* Pre/post modify/inc/dec always read and write the entire
           reg.  */
           reg.  */
        return true;
        return true;
      else
      else
        {
        {
          /* DF_REF_READ_WRITE on a use (except for the
          /* DF_REF_READ_WRITE on a use (except for the
             DF_REF_PRE_POST_MODIFY) means that this use is fabricated
             DF_REF_PRE_POST_MODIFY) means that this use is fabricated
             from a def that is a partial set to a multiword reg.
             from a def that is a partial set to a multiword reg.
             Here, we only model those cases precisely so the only one
             Here, we only model those cases precisely so the only one
             to consider is the use put on a auto inc and dec
             to consider is the use put on a auto inc and dec
             insns.  */
             insns.  */
          *start_byte = 0;
          *start_byte = 0;
          *last_byte = 0;
          *last_byte = 0;
          return false;
          return false;
        }
        }
    }
    }
 
 
  if (DF_REF_FLAGS_IS_SET (ref, DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
  if (DF_REF_FLAGS_IS_SET (ref, DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT))
    return df_compute_accessed_bytes_extract (ref, mm, start_byte, last_byte);
    return df_compute_accessed_bytes_extract (ref, mm, start_byte, last_byte);
  else if (DF_REF_FLAGS_IS_SET (ref, DF_REF_STRICT_LOW_PART))
  else if (DF_REF_FLAGS_IS_SET (ref, DF_REF_STRICT_LOW_PART))
    return df_compute_accessed_bytes_strict_low_part (ref,
    return df_compute_accessed_bytes_strict_low_part (ref,
                                                      start_byte, last_byte);
                                                      start_byte, last_byte);
  else if (GET_CODE (DF_REF_REG (ref)) == SUBREG)
  else if (GET_CODE (DF_REF_REG (ref)) == SUBREG)
    return df_compute_accessed_bytes_subreg (ref, start_byte, last_byte);
    return df_compute_accessed_bytes_subreg (ref, start_byte, last_byte);
  return true;
  return true;
}
}
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.