PATCH [5/n] X32: Supprot 32bit address
H.J. Lu
hongjiu.lu@intel.com
Sat Jul 9 22:46:00 GMT 2011
Hi,
TARGET_MEM_REF only works on ptr_mode. That means base and index parts
of x86 address operand in x32 mode may be in ptr_mode. This patch
supports 32bit base and index parts in x32 mode. OK for trunk?
Thanks.
H.J.
---
2011-07-09 H.J. Lu <hongjiu.lu@intel.com>
* config/i386/i386.c (ix86_simplify_base_index_disp): New.
(ix86_decompose_address): Support 32bit address in x32 mode.
(ix86_legitimate_address_p): Likewise.
(ix86_fixup_binary_operands): Likewise.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 04cb07d..c852719 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -10984,6 +11010,190 @@ ix86_live_on_entry (bitmap regs)
}
}
+/* For TARGET_X32, IRA may generate
+
+ (set (reg:SI 40 r11)
+ (plus:SI (plus:SI (mult:SI (reg:SI 1 dx)
+ (const_int 8))
+ (subreg:SI (plus:DI (reg/f:DI 7 sp)
+ (const_int CONST1)) 0))
+ (const_int CONST2)))
+
+ We translate it into
+
+ (set (reg:SI 40 r11)
+ (plus:SI (plus:SI (mult:SI (reg:SI 1 dx)
+ (const_int 8))
+ (reg/f:SI 7 sp))
+ (const_int [CONST1 + CONST2])))
+
+ We also translate
+
+ (plus:DI (zero_extend:DI (plus:SI (plus:SI (reg:SI 4 si [70])
+ (reg:SI 2 cx [86]))
+ (const_int CONST1)))
+ (const_int CONST2))
+
+ into
+
+ (plus:DI (zero_extend:DI (plus:SI (reg:SI 4 si [70])
+ (reg:SI 2 cx [86]))
+ (const_int [CONST1 + CONST2])))
+
+ We also translate
+
+ (plus:SI (plus:SI (plus:SI (reg:SI 4 si [70])
+ (reg:SI 2 cx [86]))
+ (symbol_ref:SI ("A.193.2210")))
+ (const_int CONST))
+
+ into
+
+ (plus:SI (plus:SI (reg:SI 4 si [70])
+ (reg:SI 2 cx [86]))
+ (const (plus:SI (symbol_ref:SI ("A.193.2210"))
+ (const_int CONST))))
+
+ We also translate
+
+ (plus:SI (reg:SI 0 ax [orig:74 D.4067 ] [74])
+ (subreg:SI (plus:DI (reg/f:DI 7 sp)
+ (const_int 64 [0x40])) 0))
+
+ into
+
+ (plus:SI (reg:SI 0 ax [orig:74 D.4067 ] [74])
+ (plus:SI (reg/f:SI 7 sp) (const_int 64 [0x40])))
+
+ If PLUS is true, we also translate
+
+ (set (reg:SI 40 r11)
+ (plus:SI (plus:SI (reg:SI 1 dx)
+ (subreg:SI (plus:DI (reg/f:DI 7 sp)
+ (const_int CONST1)) 0))
+ (const_int CONST2)))
+
+ into
+
+ (set (reg:SI 40 r11)
+ (plus:SI (plus:SI (reg:SI 1 dx)
+ (reg/f:SI 7 sp))
+ (const_int [CONST1 + CONST2])))
+
+ */
+
+static void
+ix86_simplify_base_index_disp (rtx *base_p, rtx *index_p, rtx *disp_p,
+ bool plus)
+{
+ rtx base = *base_p;
+ rtx disp, index, op0, op1;
+
+ if (!base || GET_MODE (base) != ptr_mode)
+ return;
+
+ disp = *disp_p;
+ if (disp != NULL_RTX
+ && disp != const0_rtx
+ && !CONST_INT_P (disp))
+ return;
+
+ if (GET_CODE (base) == SUBREG)
+ base = SUBREG_REG (base);
+
+ if (GET_CODE (base) == PLUS)
+ {
+ rtx addend;
+
+ op0 = XEXP (base, 0);
+ op1 = XEXP (base, 1);
+
+ if ((REG_P (op0)
+ || (!plus
+ && GET_CODE (op0) == PLUS
+ && GET_MODE (op0) == ptr_mode
+ && REG_P (XEXP (op0, 0))
+ && REG_P (XEXP (op0, 1))))
+ && (CONST_INT_P (op1)
+ || GET_CODE (op1) == SYMBOL_REF
+ || GET_CODE (op1) == LABEL_REF))
+ {
+ base = op0;
+ addend = op1;
+ }
+ else if (REG_P (op1)
+ && (CONST_INT_P (op0)
+ || GET_CODE (op0) == SYMBOL_REF
+ || GET_CODE (op0) == LABEL_REF))
+ {
+ base = op1;
+ addend = op0;
+ }
+ else if (plus
+ && GET_CODE (op1) == SUBREG
+ && GET_MODE (op1) == ptr_mode)
+ {
+ op1 = SUBREG_REG (op1);
+ if (GET_CODE (op1) == PLUS)
+ {
+ addend = XEXP (op1, 1);
+ op1 = XEXP (op1, 0);
+ if (REG_P (op1) && CONST_INT_P (addend))
+ {
+ op1 = gen_rtx_REG (ptr_mode, REGNO (op1));
+ *base_p = gen_rtx_PLUS (ptr_mode, op0, op1);
+ }
+ else
+ return;
+ }
+ else
+ return;
+ }
+ else
+ return;
+
+ if (disp == NULL_RTX || disp == const0_rtx)
+ *disp_p = addend;
+ else
+ {
+ if (CONST_INT_P (addend))
+ *disp_p = GEN_INT (INTVAL (disp) + INTVAL (addend));
+ else
+ {
+ disp = gen_rtx_PLUS (ptr_mode, addend, disp);
+ *disp_p = gen_rtx_CONST (ptr_mode, disp);
+ }
+ }
+
+ if (!plus)
+ {
+ if (REG_P (base))
+ *base_p = gen_rtx_REG (ptr_mode, REGNO (base));
+ else
+ *base_p = base;
+ }
+ }
+ else if (!plus
+ && (disp == NULL_RTX || disp == const0_rtx)
+ && index_p
+ && (index = *index_p) != NULL_RTX
+ && GET_CODE (index) == SUBREG
+ && GET_MODE (index) == ptr_mode)
+ {
+ index = SUBREG_REG (index);
+ if (GET_CODE (index) == PLUS && GET_MODE (index) == Pmode)
+ {
+ op0 = XEXP (index, 0);
+ op1 = XEXP (index, 1);
+ if (REG_P (op0) && CONST_INT_P (op1))
+ {
+ *index_p = gen_rtx_REG (ptr_mode, REGNO (op0));
+ *disp_p = op1;
+ }
+ }
+ }
+}
+
/* Extract the parts of an RTL expression that is a valid memory address
for an instruction. Return 0 if the structure of the address is
grossly off. Return -1 if the address contains ASHIFT, so it is not
@@ -11000,6 +11210,13 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
int retval = 1;
enum ix86_address_seg seg = SEG_DEFAULT;
+ /* Support 32bit address in x32 mode. */
+ if (TARGET_X32
+ && GET_CODE (addr) == ZERO_EXTEND
+ && GET_MODE (addr) == Pmode
+ && GET_CODE (XEXP (addr, 0)) == PLUS)
+ addr = XEXP (addr, 0);
+
if (REG_P (addr) || GET_CODE (addr) == SUBREG)
base = addr;
else if (GET_CODE (addr) == PLUS)
@@ -11014,6 +11231,24 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
return 0;
addends[n++] = XEXP (op, 1);
op = XEXP (op, 0);
+ /* Support 32bit address in x32 mode. */
+ if (TARGET_X32 && reload_completed)
+ {
+ if (GET_CODE (op) == ZERO_EXTEND
+ && GET_MODE (op) == Pmode
+ && GET_CODE (XEXP (op, 0)) == PLUS)
+ {
+ op = XEXP (op, 0);
+ if (n == 1)
+ ix86_simplify_base_index_disp (&op, NULL,
+ &addends[0], false);
+ }
+ else if (n == 1
+ && GET_CODE (op) == PLUS
+ && GET_MODE (op) == ptr_mode)
+ ix86_simplify_base_index_disp (&op, NULL, &addends[0],
+ true);
+ }
}
while (GET_CODE (op) == PLUS);
if (n >= 4)
@@ -11107,13 +11342,17 @@ 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;
+ if (TARGET_X32 && reload_completed)
+ ix86_simplify_base_index_disp (&base, &index, &disp, false);
/* Avoid useless 0 displacement. */
if (disp == const0_rtx && (base || index))
disp = NULL_RTX;
+ index_reg = index && GET_CODE (index) == SUBREG ? SUBREG_REG (index) : index;
+
+ base_reg = base && GET_CODE (base) == SUBREG ? SUBREG_REG (base) : base;
+
/* Allow arg pointer and stack pointer as index if there is not scaling. */
if (base_reg && index_reg && scale == 1
&& (index_reg == arg_pointer_rtx
@@ -11522,6 +11761,7 @@ ix86_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
struct ix86_address parts;
rtx base, index, disp;
HOST_WIDE_INT scale;
+ enum machine_mode base_mode;
if (ix86_decompose_address (addr, &parts) <= 0)
/* Decomposition failed. */
@@ -11553,8 +11793,11 @@ ix86_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
/* Base is not a register. */
return false;
- if (GET_MODE (base) != Pmode)
- /* Base is not in Pmode. */
+ base_mode = GET_MODE (base);
+ if (base_mode != Pmode
+ && !(TARGET_X32
+ && base_mode == ptr_mode))
+ /* Base is not in Pmode nor ptr_mode. */
return false;
if ((strict && ! REG_OK_FOR_BASE_STRICT_P (reg))
@@ -11562,6 +11805,8 @@ ix86_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
/* Base is not valid. */
return false;
}
+ else
+ base_mode = VOIDmode;
/* Validate index register.
@@ -11570,6 +11815,7 @@ ix86_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
if (index)
{
rtx reg;
+ enum machine_mode index_mode;
if (REG_P (index))
reg = index;
@@ -11582,8 +11828,13 @@ ix86_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
/* Index is not a register. */
return false;
- if (GET_MODE (index) != Pmode)
- /* Index is not in Pmode. */
+ index_mode = GET_MODE (index);
+ if ((base_mode != VOIDmode
+ && base_mode != index_mode)
+ || (index_mode != Pmode
+ && !(TARGET_X32
+ && index_mode == ptr_mode)))
+ /* Index is not in Pmode nor ptr_mode. */
return false;
if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (reg))
@@ -15461,6 +15757,16 @@ ix86_fixup_binary_operands (enum rtx_code code, enum machine_mode mode,
else
src2 = force_reg (mode, src2);
}
+ else
+ {
+ /* Support 32bit address in x32 mode. */
+ if (TARGET_X32
+ && code == PLUS
+ && !MEM_P (dst)
+ && !MEM_P (src1)
+ && MEM_P (src2) )
+ src2 = force_reg (mode, src2);
+ }
/* If the destination is memory, and we do not have matching source
operands, do things in registers. */
More information about the Gcc-patches
mailing list