Index: config/rs6000/rs6000-protos.h =================================================================== --- config/rs6000/rs6000-protos.h (revision 143571) +++ config/rs6000/rs6000-protos.h (working copy) @@ -42,6 +42,7 @@ extern void validate_condition_mode (enu 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); Index: config/rs6000/rs6000.opt =================================================================== --- config/rs6000/rs6000.opt (revision 143571) +++ config/rs6000/rs6000.opt (working copy) @@ -119,6 +119,10 @@ mupdate Target Report RejectNegative InverseMask(NO_UPDATE, UPDATE) Generate load/store with update instructions +mavoid-xform +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 Index: config/rs6000/rs6000.c =================================================================== --- config/rs6000/rs6000.c (revision 143571) +++ config/rs6000/rs6000.c (working copy) @@ -1987,6 +1987,13 @@ rs6000_override_options (const char *def 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 (); } @@ -3704,6 +3711,14 @@ legitimate_indexed_address_p (rtx x, int && 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) { @@ -3830,6 +3845,7 @@ rs6000_legitimize_address (rtx x, rtx ol || ((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) @@ -4441,6 +4457,7 @@ rs6000_legitimate_address (enum machine_ || (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 @@ -4459,7 +4476,8 @@ rs6000_legitimate_address (enum machine_ && 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)) Index: config/rs6000/rs6000.md =================================================================== --- config/rs6000/rs6000.md (revision 143571) +++ config/rs6000/rs6000.md (working copy) @@ -10055,7 +10055,8 @@ (define_insn "*movdi_update1" (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)" @@ -10067,7 +10068,9 @@ (define_insn "movdi__update" (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)" @@ -10079,7 +10082,8 @@ (define_insn "*movsi_update1" (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" + "TARGET_UPDATE + && (!avoiding_indexed_address_p(SImode) || !gpc_reg_operand (operands[2], SImode))" "@ {lux|lwzux} %3,%0,%2 {lu|lwzu} %3,%2(%0)" @@ -10092,7 +10096,8 @@ (define_insn "*movsi_update2" (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")]) @@ -10102,7 +10107,9 @@ (define_insn "movsi_update" (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" + "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)" @@ -10114,7 +10121,8 @@ (define_insn "*movhi_update1" (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" + "TARGET_UPDATE + && (!avoiding_indexed_address_p(SImode) || !gpc_reg_operand (operands[2], SImode))" "@ lhzux %3,%0,%2 lhzu %3,%2(%0)" @@ -10127,7 +10135,8 @@ (define_insn "*movhi_update2" (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" + "TARGET_UPDATE + && (!avoiding_indexed_address_p(SImode) || !gpc_reg_operand (operands[2], SImode))" "@ lhzux %3,%0,%2 lhzu %3,%2(%0)" @@ -10140,7 +10149,8 @@ (define_insn "*movhi_update3" (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)" @@ -10152,7 +10162,8 @@ (define_insn "*movhi_update4" (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" + "TARGET_UPDATE + && (!avoiding_indexed_address_p(SImode) || !gpc_reg_operand (operands[2], SImode))" "@ sthux %3,%0,%2 sthu %3,%2(%0)" @@ -10164,7 +10175,8 @@ (define_insn "*movqi_update1" (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" + "TARGET_UPDATE + && (!avoiding_indexed_address_p(SImode) || !gpc_reg_operand (operands[2], SImode))" "@ lbzux %3,%0,%2 lbzu %3,%2(%0)" @@ -10177,7 +10189,8 @@ (define_insn "*movqi_update2" (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" + "TARGET_UPDATE + && (!avoiding_indexed_address_p(SImode) || !gpc_reg_operand (operands[2], SImode))" "@ lbzux %3,%0,%2 lbzu %3,%2(%0)" @@ -10189,7 +10202,8 @@ (define_insn "*movqi_update3" (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" + "TARGET_UPDATE + && (!avoiding_indexed_address_p(SImode) || !gpc_reg_operand (operands[2], SImode))" "@ stbux %3,%0,%2 stbu %3,%2(%0)" @@ -10201,7 +10215,8 @@ (define_insn "*movsf_update1" (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)" @@ -10213,7 +10228,8 @@ (define_insn "*movsf_update2" (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)" @@ -10225,7 +10241,8 @@ (define_insn "*movsf_update3" (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)" @@ -10237,7 +10254,8 @@ (define_insn "*movsf_update4" (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)" @@ -10249,7 +10267,8 @@ (define_insn "*movdf_update1" (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)" @@ -10261,7 +10280,8 @@ (define_insn "*movdf_update2" (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)"