aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <bonzini@gnu.org>2005-04-01 07:58:44 +0000
committerPaolo Bonzini <bonzini@gcc.gnu.org>2005-04-01 07:58:44 +0000
commit7c93c2cc4dd591cfc88bd058611befae64c6238a (patch)
tree1bff3f6a8b4f1bf49c00a449469810462a27c491
parenta288c5cd8c7b0201e0cfbbaba19193c7782969b4 (diff)
downloadgcc-7c93c2cc4dd591cfc88bd058611befae64c6238a.zip
gcc-7c93c2cc4dd591cfc88bd058611befae64c6238a.tar.gz
gcc-7c93c2cc4dd591cfc88bd058611befae64c6238a.tar.bz2
i386.c (ix86_decompose_address): Look inside SUBREGs to fix addresses involving EBP and ESP.
2005-04-01 Paolo Bonzini <bonzini@gnu.org> Jan Hubicka <jh@suse.cz> * config/i386/i386.c (ix86_decompose_address): Look inside SUBREGs to fix addresses involving EBP and ESP. (aligned_operand, legitimate_address_p, ix86_address_cost): Be prepared for SUBREGed registers. (legitimate_address_p): Accept SUBREGed registers. Co-Authored-By: Jan Hubicka <jh@suse.cz> From-SVN: r97376
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/i386/i386.c86
2 files changed, 65 insertions, 30 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e390255..ab5c35f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2005-04-01 Paolo Bonzini <bonzini@gnu.org>
+ Jan Hubicka <jh@suse.cz>
+
+ * config/i386/i386.c (ix86_decompose_address): Look inside SUBREGs
+ to fix addresses involving EBP and ESP.
+ (aligned_operand, legitimate_address_p, ix86_address_cost): Be prepared
+ for SUBREGed registers.
+ (legitimate_address_p): Accept SUBREGed registers.
+
2005-04-01 Jakub Jelinek <jakub@redhat.com>
PR c++/19406
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 80f4b0c..8021035 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -4663,9 +4663,8 @@ ix86_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
int
ix86_decompose_address (rtx addr, struct ix86_address *out)
{
- rtx base = NULL_RTX;
- rtx index = NULL_RTX;
- rtx disp = NULL_RTX;
+ rtx base = NULL_RTX, index = NULL_RTX, disp = NULL_RTX;
+ rtx base_reg, index_reg;
HOST_WIDE_INT scale = 1;
rtx scale_rtx = NULL_RTX;
int retval = 1;
@@ -4767,34 +4766,37 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
scale = INTVAL (scale_rtx);
}
+ base_reg = base && GET_CODE (base) == SUBREG ? SUBREG_REG (base) : base;
+ index_reg = index && GET_CODE (index) == SUBREG ? SUBREG_REG (index) : index;
+
/* Allow arg pointer and stack pointer as index if there is not scaling. */
- if (base && index && scale == 1
- && (index == arg_pointer_rtx
- || index == frame_pointer_rtx
- || (REG_P (index) && REGNO (index) == STACK_POINTER_REGNUM)))
+ if (base_reg && index_reg && scale == 1
+ && (index_reg == arg_pointer_rtx
+ || index_reg == frame_pointer_rtx
+ || (REG_P (index_reg) && REGNO (index_reg) == STACK_POINTER_REGNUM)))
{
- rtx tmp = base;
- base = index;
- index = tmp;
+ rtx tmp;
+ tmp = base, base = index, index = tmp;
+ tmp = base_reg, base_reg = index_reg, index_reg = tmp;
}
/* Special case: %ebp cannot be encoded as a base without a displacement. */
- if ((base == hard_frame_pointer_rtx
- || base == frame_pointer_rtx
- || base == arg_pointer_rtx) && !disp)
+ if ((base_reg == hard_frame_pointer_rtx
+ || base_reg == frame_pointer_rtx
+ || base_reg == arg_pointer_rtx) && !disp)
disp = const0_rtx;
/* Special case: on K6, [%esi] makes the instruction vector decoded.
Avoid this by transforming to [%esi+0]. */
if (ix86_tune == PROCESSOR_K6 && !optimize_size
- && base && !index && !disp
- && REG_P (base)
- && REGNO_REG_CLASS (REGNO (base)) == SIREG)
+ && base_reg && !index_reg && !disp
+ && REG_P (base_reg)
+ && REGNO_REG_CLASS (REGNO (base_reg)) == SIREG)
disp = const0_rtx;
/* Special case: encode reg+reg instead of reg*2. */
if (!base && index && scale && scale == 2)
- base = index, scale = 1;
+ base = index, base_reg = index_reg, scale = 1;
/* Special case: scaling cannot be encoded without base or displacement. */
if (!base && !disp && index && scale != 1)
@@ -4823,6 +4825,11 @@ ix86_address_cost (rtx x)
if (!ix86_decompose_address (x, &parts))
abort ();
+ if (parts.base && GET_CODE (parts.base) == SUBREG)
+ parts.base = SUBREG_REG (parts.base);
+ if (parts.index && GET_CODE (parts.index) == SUBREG)
+ parts.index = SUBREG_REG (parts.index);
+
/* More complex memory references are better. */
if (parts.disp && parts.disp != const0_rtx)
cost--;
@@ -5172,15 +5179,23 @@ legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
/* Validate base register.
- Don't allow SUBREG's here, it can lead to spill failures when the base
- is one word out of a two word structure, which is represented internally
- as a DImode int. */
+ Don't allow SUBREG's that span more than a word here. It can lead to spill
+ failures when the base is one word out of a two word structure, which is
+ represented internally as a DImode int. */
if (base)
{
+ rtx reg;
reason_rtx = base;
-
- if (GET_CODE (base) != REG)
+
+ if (REG_P (base))
+ reg = base;
+ else if (GET_CODE (base) == SUBREG
+ && REG_P (SUBREG_REG (base))
+ && GET_MODE_SIZE (GET_MODE (SUBREG_REG (base)))
+ <= UNITS_PER_WORD)
+ reg = SUBREG_REG (base);
+ else
{
reason = "base is not a register";
goto report_error;
@@ -5192,8 +5207,8 @@ legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
goto report_error;
}
- if ((strict && ! REG_OK_FOR_BASE_STRICT_P (base))
- || (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (base)))
+ if ((strict && ! REG_OK_FOR_BASE_STRICT_P (reg))
+ || (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (reg)))
{
reason = "base is not valid";
goto report_error;
@@ -5202,15 +5217,21 @@ legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
/* Validate index register.
- Don't allow SUBREG's here, it can lead to spill failures when the index
- is one word out of a two word structure, which is represented internally
- as a DImode int. */
+ Don't allow SUBREG's that span more than a word here -- same as above. */
if (index)
{
+ rtx reg;
reason_rtx = index;
- if (GET_CODE (index) != REG)
+ if (REG_P (index))
+ reg = index;
+ else if (GET_CODE (index) == SUBREG
+ && REG_P (SUBREG_REG (index))
+ && GET_MODE_SIZE (GET_MODE (SUBREG_REG (index)))
+ <= UNITS_PER_WORD)
+ reg = SUBREG_REG (index);
+ else
{
reason = "index is not a register";
goto report_error;
@@ -5222,8 +5243,8 @@ legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
goto report_error;
}
- if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (index))
- || (! strict && ! REG_OK_FOR_INDEX_NONSTRICT_P (index)))
+ if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (reg))
+ || (! strict && ! REG_OK_FOR_INDEX_NONSTRICT_P (reg)))
{
reason = "index is not valid";
goto report_error;
@@ -11834,6 +11855,11 @@ memory_address_length (rtx addr)
if (! ix86_decompose_address (addr, &parts))
abort ();
+ if (parts.base && GET_CODE (parts.base) == SUBREG)
+ parts.base = SUBREG_REG (parts.base);
+ if (parts.index && GET_CODE (parts.index) == SUBREG)
+ parts.index = SUBREG_REG (parts.index);
+
base = parts.base;
index = parts.index;
disp = parts.disp;