Hello!
This patch merges 64-bit and 32-bit gotoff_operand code paths in
legitimize_pic_address. Also, the patch uses copy_to_suggested_reg,
which seems to be invented just for this purpose. Also,
expand_simple_binop will ouput to suggested target reg by itself, so
there is no need to emit separate move insn.
2016-05-10 Uros Bizjak <[email protected]>
* config/i386/i386.c (legitimize_pic_address): Merge 64-bit and 32-bit
gotoff_operand code paths. Use copy_to_suggested_regs and
expand_simple_binop where appropriate. Cleanup.
Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.
Committed to mainline SVN.
Uros.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 05476f3..3f02c8e 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -15375,46 +15375,18 @@ legitimize_pic_address (rtx orig, rtx reg)
if (TARGET_64BIT && legitimate_pic_address_disp_p (addr))
new_rtx = addr;
- else if (TARGET_64BIT && !TARGET_PECOFF
- && ix86_cmodel != CM_SMALL_PIC && gotoff_operand (addr, Pmode))
- {
- rtx tmpreg;
- /* This symbol may be referenced via a displacement from the PIC
- base address (@GOTOFF). */
- if (GET_CODE (addr) == CONST)
- addr = XEXP (addr, 0);
- if (GET_CODE (addr) == PLUS)
- {
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (addr, 0)),
- UNSPEC_GOTOFF);
- new_rtx = gen_rtx_PLUS (Pmode, new_rtx, XEXP (addr, 1));
- }
- else
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
- new_rtx = gen_rtx_CONST (Pmode, new_rtx);
- if (!reg)
- tmpreg = gen_reg_rtx (Pmode);
- else
- tmpreg = reg;
- emit_move_insn (tmpreg, new_rtx);
-
- if (reg != 0)
- {
- new_rtx = expand_simple_binop (Pmode, PLUS, reg, pic_offset_table_rtx,
- tmpreg, 1, OPTAB_DIRECT);
- new_rtx = reg;
- }
- else
- new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmpreg);
- }
- else if (!TARGET_64BIT && !TARGET_PECOFF && gotoff_operand (addr, Pmode))
+ else if ((!TARGET_64BIT
+ || /* TARGET_64BIT && */ ix86_cmodel != CM_SMALL_PIC)
+ && !TARGET_PECOFF
+ && gotoff_operand (addr, Pmode))
{
/* This symbol may be referenced via a displacement from the PIC
base address (@GOTOFF). */
if (GET_CODE (addr) == CONST)
addr = XEXP (addr, 0);
+
if (GET_CODE (addr) == PLUS)
{
new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (addr, 0)),
@@ -15423,14 +15395,20 @@ legitimize_pic_address (rtx orig, rtx reg)
}
else
new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
+
new_rtx = gen_rtx_CONST (Pmode, new_rtx);
- new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new_rtx);
+
+ if (TARGET_64BIT)
+ new_rtx = copy_to_suggested_reg (new_rtx, reg, Pmode);
if (reg != 0)
{
- emit_move_insn (reg, new_rtx);
- new_rtx = reg;
- }
+ gcc_assert (REG_P (reg));
+ new_rtx = expand_simple_binop (Pmode, PLUS, pic_offset_table_rtx,
+ new_rtx, reg, 1, OPTAB_DIRECT);
+ }
+ else
+ new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new_rtx);
}
else if ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (addr) == 0)
/* We can't use @GOTOFF for text labels on VxWorks;
@@ -15448,14 +15426,12 @@ legitimize_pic_address (rtx orig, rtx reg)
new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PCREL);
new_rtx = gen_rtx_CONST (Pmode, new_rtx);
- if (reg == 0)
- reg = gen_reg_rtx (Pmode);
- emit_move_insn (reg, new_rtx);
- new_rtx = reg;
+ new_rtx = copy_to_suggested_reg (new_rtx, reg, Pmode);
}
else if (TARGET_64BIT && ix86_cmodel != CM_LARGE_PIC)
{
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
UNSPEC_GOTPCREL);
+ new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
+ UNSPEC_GOTPCREL);
new_rtx = gen_rtx_CONST (Pmode, new_rtx);
new_rtx = gen_const_mem (Pmode, new_rtx);
set_mem_alias_set (new_rtx, ix86_GOT_alias_set ());
@@ -15481,25 +15457,15 @@ legitimize_pic_address (rtx orig, rtx reg)
new_rtx = gen_const_mem (Pmode, new_rtx);
set_mem_alias_set (new_rtx, ix86_GOT_alias_set ());
- if (reg == 0)
- reg = gen_reg_rtx (Pmode);
- emit_move_insn (reg, new_rtx);
- new_rtx = reg;
+ new_rtx = copy_to_suggested_reg (new_rtx, reg, Pmode);
}
}
else
{
if (CONST_INT_P (addr)
&& !x86_64_immediate_operand (addr, VOIDmode))
- {
- if (reg)
- {
- emit_move_insn (reg, addr);
- new_rtx = reg;
- }
- else
- new_rtx = force_reg (Pmode, addr);
- }
+ new_rtx = copy_to_suggested_reg (addr, reg, Pmode);
+
else if (GET_CODE (addr) == CONST)
{
addr = XEXP (addr, 0);
@@ -15513,13 +15479,15 @@ legitimize_pic_address (rtx orig, rtx reg)
return orig;
gcc_assert (GET_CODE (addr) == PLUS);
}
+
if (GET_CODE (addr) == PLUS)
{
rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
/* Check first to see if this is a constant offset from a @GOTOFF
symbol reference. */
- if (!TARGET_PECOFF && gotoff_operand (op0, Pmode)
+ if (!TARGET_PECOFF
+ && gotoff_operand (op0, Pmode)
&& CONST_INT_P (op1))
{
if (!TARGET_64BIT)
@@ -15528,13 +15496,18 @@ legitimize_pic_address (rtx orig, rtx reg)
UNSPEC_GOTOFF);
new_rtx = gen_rtx_PLUS (Pmode, new_rtx, op1);
new_rtx = gen_rtx_CONST (Pmode, new_rtx);
- new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new_rtx);
if (reg != 0)
{
- emit_move_insn (reg, new_rtx);
- new_rtx = reg;
+ gcc_assert (REG_P (reg));
+ new_rtx = expand_simple_binop (Pmode, PLUS,
+ pic_offset_table_rtx,
+ new_rtx, reg, 1,
+ OPTAB_DIRECT);
}
+ else
+ new_rtx
+ = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new_rtx);
}
else
{
@@ -15543,7 +15516,9 @@ legitimize_pic_address (rtx orig, rtx reg)
{
if (!x86_64_immediate_operand (op1, Pmode))
op1 = force_reg (Pmode, op1);
- new_rtx = gen_rtx_PLUS (Pmode, force_reg (Pmode, op0),
op1);
+
+ new_rtx
+ = gen_rtx_PLUS (Pmode, force_reg (Pmode, op0), op1);
}
}
}
@@ -15561,6 +15536,7 @@ legitimize_pic_address (rtx orig, rtx reg)
{
if (!x86_64_immediate_operand (new_rtx, mode))
new_rtx = force_reg (mode, new_rtx);
+
new_rtx
= gen_rtx_PLUS (mode, force_reg (mode, base), new_rtx);
}