* config/rs6000/rs6000-protos.h (avoiding_indexed_address_p): Declare.
* config/rs6000/rs6000.opt (avoid-indexed-addresses): New option.
* config/rs6000/rs6000.c (rs6000_override_options): Default
avoid-indexed-addresses on for Power6, off for everything else.
(avoiding_indexed_address_p): New function.
(rs6000_legitimize_address): Use it.
(rs6000_legitimate_address): Likewise.
* config/rs6000/rs6000.md (movXX_updateX): Likewise
* gcc.target/powerpc/avoid-indexed-addresses.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@143742
138bc75d-0d04-0410-961f-
82ee72b054a4
+2009-01-28 Pat Haugen <pthaugen@us.ibm.com>
+
+ * doc/invoke.texi (avoid-indexed-addresses): Document new option.
+ * config/rs6000/rs6000-protos.h (avoiding_indexed_address_p): Declare.
+ * config/rs6000/rs6000.opt (avoid-indexed-addresses): New option.
+ * config/rs6000/rs6000.c (rs6000_override_options): Default
+ avoid-indexed-addresses on for Power6, off for everything else.
+ (avoiding_indexed_address_p): New function.
+ (rs6000_legitimize_address): Use it.
+ (rs6000_legitimate_address): Likewise.
+ * config/rs6000/rs6000.md (movXX_updateX): Likewise
+
2009-01-28 Kazu Hirata <kazu@codesourcery.com>
PR tree-optimization/38997
2009-01-28 Kazu Hirata <kazu@codesourcery.com>
PR tree-optimization/38997
extern bool legitimate_constant_pool_address_p (rtx);
extern bool legitimate_indirect_address_p (rtx, int);
extern bool legitimate_indexed_address_p (rtx, int);
extern bool legitimate_constant_pool_address_p (rtx);
extern bool legitimate_indirect_address_p (rtx, int);
extern bool legitimate_indexed_address_p (rtx, int);
+extern bool avoiding_indexed_address_p (enum machine_mode);
extern rtx rs6000_got_register (rtx);
extern rtx find_addr_reg (rtx);
extern rtx rs6000_got_register (rtx);
extern rtx find_addr_reg (rtx);
rs6000_single_float = rs6000_double_float = 1;
}
rs6000_single_float = rs6000_double_float = 1;
}
+ /* If not explicitly specified via option, decide whether to generate indexed
+ load/store instructions. */
+ if (TARGET_AVOID_XFORM == -1)
+ /* Avoid indexed addressing when targeting Power6 in order to avoid
+ the DERAT mispredict penalty. */
+ TARGET_AVOID_XFORM = (rs6000_cpu == PROCESSOR_POWER6 && TARGET_CMPB);
+
rs6000_init_hard_regno_mode_ok ();
}
rs6000_init_hard_regno_mode_ok ();
}
&& INT_REG_OK_FOR_INDEX_P (op0, strict))));
}
&& INT_REG_OK_FOR_INDEX_P (op0, strict))));
}
+bool
+avoiding_indexed_address_p (enum machine_mode mode)
+{
+ /* Avoid indexed addressing for modes that have non-indexed
+ load/store instruction forms. */
+ return TARGET_AVOID_XFORM && !ALTIVEC_VECTOR_MODE (mode);
+}
+
inline bool
legitimate_indirect_address_p (rtx x, int strict)
{
inline bool
legitimate_indirect_address_p (rtx x, int strict)
{
|| ((mode != DImode && mode != DFmode && mode != DDmode)
|| (TARGET_E500_DOUBLE && mode != DDmode)))
&& (TARGET_POWERPC64 || mode != DImode)
|| ((mode != DImode && mode != DFmode && mode != DDmode)
|| (TARGET_E500_DOUBLE && mode != DDmode)))
&& (TARGET_POWERPC64 || mode != DImode)
+ && !avoiding_indexed_address_p (mode)
&& mode != TImode
&& mode != TFmode
&& mode != TDmode)
&& mode != TImode
&& mode != TFmode
&& mode != TDmode)
|| (mode != DFmode && mode != DDmode)
|| (TARGET_E500_DOUBLE && mode != DDmode))
&& (TARGET_POWERPC64 || mode != DImode)
|| (mode != DFmode && mode != DDmode)
|| (TARGET_E500_DOUBLE && mode != DDmode))
&& (TARGET_POWERPC64 || mode != DImode)
+ && !avoiding_indexed_address_p (mode)
&& legitimate_indexed_address_p (x, reg_ok_strict))
return 1;
if (GET_CODE (x) == PRE_MODIFY
&& legitimate_indexed_address_p (x, reg_ok_strict))
return 1;
if (GET_CODE (x) == PRE_MODIFY
&& TARGET_UPDATE
&& legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict)
&& (rs6000_legitimate_offset_address_p (mode, XEXP (x, 1), reg_ok_strict)
&& TARGET_UPDATE
&& legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict)
&& (rs6000_legitimate_offset_address_p (mode, XEXP (x, 1), reg_ok_strict)
- || legitimate_indexed_address_p (XEXP (x, 1), reg_ok_strict))
+ || (!avoiding_indexed_address_p (mode)
+ && legitimate_indexed_address_p (XEXP (x, 1), reg_ok_strict)))
&& rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
return 1;
if (legitimate_lo_sum_address_p (mode, x, reg_ok_strict))
&& rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
return 1;
if (legitimate_lo_sum_address_p (mode, x, reg_ok_strict))
(match_operand:DI 2 "reg_or_aligned_short_operand" "r,I"))))
(set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
(plus:DI (match_dup 1) (match_dup 2)))]
(match_operand:DI 2 "reg_or_aligned_short_operand" "r,I"))))
(set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
(plus:DI (match_dup 1) (match_dup 2)))]
- "TARGET_POWERPC64 && TARGET_UPDATE"
+ "TARGET_POWERPC64 && TARGET_UPDATE
+ && (!avoiding_indexed_address_p (DImode)
+ || !gpc_reg_operand (operands[2], DImode))"
"@
ldux %3,%0,%2
ldu %3,%2(%0)"
"@
ldux %3,%0,%2
ldu %3,%2(%0)"
(match_operand:DI 3 "gpc_reg_operand" "r,r"))
(set (match_operand:P 0 "gpc_reg_operand" "=b,b")
(plus:P (match_dup 1) (match_dup 2)))]
(match_operand:DI 3 "gpc_reg_operand" "r,r"))
(set (match_operand:P 0 "gpc_reg_operand" "=b,b")
(plus:P (match_dup 1) (match_dup 2)))]
- "TARGET_POWERPC64 && TARGET_UPDATE"
+ "TARGET_POWERPC64 && TARGET_UPDATE
+ && (!avoiding_indexed_address_p (Pmode)
+ || !gpc_reg_operand (operands[2], Pmode)
+ || (REG_P (operands[0])
+ && REGNO (operands[0]) == STACK_POINTER_REGNUM))"
"@
stdux %3,%0,%2
stdu %3,%2(%0)"
"@
stdux %3,%0,%2
stdu %3,%2(%0)"
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_UPDATE
+ && (!avoiding_indexed_address_p (SImode)
+ || !gpc_reg_operand (operands[2], SImode))"
"@
{lux|lwzux} %3,%0,%2
{lu|lwzu} %3,%2(%0)"
"@
{lux|lwzux} %3,%0,%2
{lu|lwzu} %3,%2(%0)"
(match_operand:DI 2 "gpc_reg_operand" "r")))))
(set (match_operand:DI 0 "gpc_reg_operand" "=b")
(plus:DI (match_dup 1) (match_dup 2)))]
(match_operand:DI 2 "gpc_reg_operand" "r")))))
(set (match_operand:DI 0 "gpc_reg_operand" "=b")
(plus:DI (match_dup 1) (match_dup 2)))]
- "TARGET_POWERPC64 && rs6000_gen_cell_microcode"
+ "TARGET_POWERPC64 && rs6000_gen_cell_microcode
+ && !avoiding_indexed_address_p (DImode)"
"lwaux %3,%0,%2"
[(set_attr "type" "load_ext_ux")])
"lwaux %3,%0,%2"
[(set_attr "type" "load_ext_ux")])
(match_operand:SI 3 "gpc_reg_operand" "r,r"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
(match_operand:SI 3 "gpc_reg_operand" "r,r"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_UPDATE
+ && (!avoiding_indexed_address_p (SImode)
+ || !gpc_reg_operand (operands[2], SImode)
+ || (REG_P (operands[0])
+ && REGNO (operands[0]) == STACK_POINTER_REGNUM))"
"@
{stux|stwux} %3,%0,%2
{stu|stwu} %3,%2(%0)"
"@
{stux|stwux} %3,%0,%2
{stu|stwu} %3,%2(%0)"
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_UPDATE
+ && (!avoiding_indexed_address_p (SImode)
+ || !gpc_reg_operand (operands[2], SImode))"
"@
lhzux %3,%0,%2
lhzu %3,%2(%0)"
"@
lhzux %3,%0,%2
lhzu %3,%2(%0)"
(match_operand:SI 2 "reg_or_short_operand" "r,I")))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
(match_operand:SI 2 "reg_or_short_operand" "r,I")))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_UPDATE
+ && (!avoiding_indexed_address_p (SImode)
+ || !gpc_reg_operand (operands[2], SImode))"
"@
lhzux %3,%0,%2
lhzu %3,%2(%0)"
"@
lhzux %3,%0,%2
lhzu %3,%2(%0)"
(match_operand:SI 2 "reg_or_short_operand" "r,I")))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
(match_operand:SI 2 "reg_or_short_operand" "r,I")))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_UPDATE && rs6000_gen_cell_microcode"
+ "TARGET_UPDATE && rs6000_gen_cell_microcode
+ && (!avoiding_indexed_address_p (SImode)
+ || !gpc_reg_operand (operands[2], SImode))"
"@
lhaux %3,%0,%2
lhau %3,%2(%0)"
"@
lhaux %3,%0,%2
lhau %3,%2(%0)"
(match_operand:HI 3 "gpc_reg_operand" "r,r"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
(match_operand:HI 3 "gpc_reg_operand" "r,r"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_UPDATE
+ && (!avoiding_indexed_address_p (SImode)
+ || !gpc_reg_operand (operands[2], SImode))"
"@
sthux %3,%0,%2
sthu %3,%2(%0)"
"@
sthux %3,%0,%2
sthu %3,%2(%0)"
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_UPDATE
+ && (!avoiding_indexed_address_p (SImode)
+ || !gpc_reg_operand (operands[2], SImode))"
"@
lbzux %3,%0,%2
lbzu %3,%2(%0)"
"@
lbzux %3,%0,%2
lbzu %3,%2(%0)"
(match_operand:SI 2 "reg_or_short_operand" "r,I")))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
(match_operand:SI 2 "reg_or_short_operand" "r,I")))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_UPDATE
+ && (!avoiding_indexed_address_p (SImode)
+ || !gpc_reg_operand (operands[2], SImode))"
"@
lbzux %3,%0,%2
lbzu %3,%2(%0)"
"@
lbzux %3,%0,%2
lbzu %3,%2(%0)"
(match_operand:QI 3 "gpc_reg_operand" "r,r"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
(match_operand:QI 3 "gpc_reg_operand" "r,r"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_UPDATE
+ && (!avoiding_indexed_address_p (SImode)
+ || !gpc_reg_operand (operands[2], SImode))"
"@
stbux %3,%0,%2
stbu %3,%2(%0)"
"@
stbux %3,%0,%2
stbu %3,%2(%0)"
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT && TARGET_UPDATE"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT && TARGET_UPDATE
+ && (!avoiding_indexed_address_p (SImode)
+ || !gpc_reg_operand (operands[2], SImode))"
"@
lfsux %3,%0,%2
lfsu %3,%2(%0)"
"@
lfsux %3,%0,%2
lfsu %3,%2(%0)"
(match_operand:SF 3 "gpc_reg_operand" "f,f"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
(match_operand:SF 3 "gpc_reg_operand" "f,f"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT && TARGET_UPDATE"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT && TARGET_UPDATE
+ && (!avoiding_indexed_address_p (SImode)
+ || !gpc_reg_operand (operands[2], SImode))"
"@
stfsux %3,%0,%2
stfsu %3,%2(%0)"
"@
stfsux %3,%0,%2
stfsu %3,%2(%0)"
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- "(TARGET_SOFT_FLOAT || !TARGET_FPRS) && TARGET_UPDATE"
+ "(TARGET_SOFT_FLOAT || !TARGET_FPRS) && TARGET_UPDATE
+ && (!avoiding_indexed_address_p (SImode)
+ || !gpc_reg_operand (operands[2], SImode))"
"@
{lux|lwzux} %3,%0,%2
{lu|lwzu} %3,%2(%0)"
"@
{lux|lwzux} %3,%0,%2
{lu|lwzu} %3,%2(%0)"
(match_operand:SF 3 "gpc_reg_operand" "r,r"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
(match_operand:SF 3 "gpc_reg_operand" "r,r"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- "(TARGET_SOFT_FLOAT || !TARGET_FPRS) && TARGET_UPDATE"
+ "(TARGET_SOFT_FLOAT || !TARGET_FPRS) && TARGET_UPDATE
+ && (!avoiding_indexed_address_p (SImode)
+ || !gpc_reg_operand (operands[2], SImode))"
"@
{stux|stwux} %3,%0,%2
{stu|stwu} %3,%2(%0)"
"@
{stux|stwux} %3,%0,%2
{stu|stwu} %3,%2(%0)"
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
(match_operand:SI 2 "reg_or_short_operand" "r,I"))))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_UPDATE"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_UPDATE
+ && (!avoiding_indexed_address_p (SImode)
+ || !gpc_reg_operand (operands[2], SImode))"
"@
lfdux %3,%0,%2
lfdu %3,%2(%0)"
"@
lfdux %3,%0,%2
lfdu %3,%2(%0)"
(match_operand:DF 3 "gpc_reg_operand" "f,f"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
(match_operand:DF 3 "gpc_reg_operand" "f,f"))
(set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_UPDATE"
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_UPDATE
+ && (!avoiding_indexed_address_p (SImode)
+ || !gpc_reg_operand (operands[2], SImode))"
"@
stfdux %3,%0,%2
stfdu %3,%2(%0)"
"@
stfdux %3,%0,%2
stfdu %3,%2(%0)"
Target Report RejectNegative InverseMask(NO_UPDATE, UPDATE)
Generate load/store with update instructions
Target Report RejectNegative InverseMask(NO_UPDATE, UPDATE)
Generate load/store with update instructions
+mavoid-indexed-addresses
+Target Report Var(TARGET_AVOID_XFORM) Init(-1)
+Avoid generation of indexed load/store instructions when possible
+
mno-fused-madd
Target Report RejectNegative Mask(NO_FUSED_MADD)
Do not generate fused multiply/add instructions
mno-fused-madd
Target Report RejectNegative Mask(NO_FUSED_MADD)
Do not generate fused multiply/add instructions
-msoft-float -mhard-float -mmultiple -mno-multiple @gol
-msingle-float -mdouble-float -msimple-fpu @gol
-mstring -mno-string -mupdate -mno-update @gol
-msoft-float -mhard-float -mmultiple -mno-multiple @gol
-msingle-float -mdouble-float -msimple-fpu @gol
-mstring -mno-string -mupdate -mno-update @gol
+-mavoid-indexed-addresses -mno-avoid-indexed-addresses @gol
-mfused-madd -mno-fused-madd -mbit-align -mno-bit-align @gol
-mstrict-align -mno-strict-align -mrelocatable @gol
-mno-relocatable -mrelocatable-lib -mno-relocatable-lib @gol
-mfused-madd -mno-fused-madd -mbit-align -mno-bit-align @gol
-mstrict-align -mno-strict-align -mrelocatable @gol
-mno-relocatable -mrelocatable-lib -mno-relocatable-lib @gol
stored, which means code that walks the stack frame across interrupts or
signals may get corrupted data.
stored, which means code that walks the stack frame across interrupts or
signals may get corrupted data.
+@item -mavoid-indexed-addresses
+@item -mno-avoid-indexed-addresses
+@opindex mavoid-indexed-addresses
+@opindex mno-avoid-indexed-addresses
+Generate code that tries to avoid (not avoid) the use of indexed load
+or store instructions. These instructions can incur a performance
+penalty on Power6 processors in certain situations, such as when
+stepping through large arrays that cross a 16M boundary. This option
+is enabled by default when targetting Power6 and disabled otherwise.
+
@item -mfused-madd
@itemx -mno-fused-madd
@opindex mfused-madd
@item -mfused-madd
@itemx -mno-fused-madd
@opindex mfused-madd
+2009-01-28 Pat Haugen <pthaugen@us.ibm.com>
+
+ * gcc.target/powerpc/avoid-indexed-addresses.c: New test.
+
2009-01-28 Kazu Hirata <kazu@codesourcery.com>
PR tree-optimization/38997
2009-01-28 Kazu Hirata <kazu@codesourcery.com>
PR tree-optimization/38997
--- /dev/null
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-options "-O2 -mavoid-indexed-addresses" } */
+
+/* { dg-final { scan-assembler-not "lbzx" } }
+
+/* Ensure that an indexed load is not generated with
+ -mavoid-indexed-addresses. */
+
+char
+do_one (char *base, unsigned long offset)
+{
+ return base[offset];
+}
+