2010-04-08 Bernd Schmidt Issue #6952 gcc/ * ira-costs.c (record_reg_classes): Ignore alternatives that are not enabled. * config/arm/vfp.md (arm_movdi_vfp): Enable only when not tuning for Cortex-A8. (arm_movdi_vfp_cortexa8): New pattern. * config/arm/neon.md (adddi3_neon, subdi3_neon, anddi3_neon, iordi3_neon, xordi3_neon): Add alternatives to discourage Neon instructions when tuning for Cortex-A8. Set attribute "alt_tune". * config/arm/arm.md (define_attr "alt_tune", define_attr "enabled"): New. 2010-07-26 Julian Brown Merge from Sourcery G++ 4.4: 2010-04-07 Thomas Schwinge Daniel Jacobowitz === modified file 'gcc/config/arm/arm.md' --- old/gcc/config/arm/arm.md 2010-08-13 10:30:35 +0000 +++ new/gcc/config/arm/arm.md 2010-08-13 11:40:17 +0000 @@ -432,6 +432,20 @@ (const_string "yes") (const_string "no")))) +; Specifies which machine an alternative is tuned for. Used to compute +; attribute ENABLED. +(define_attr "alt_tune" "all,onlya8,nota8" (const_string "all")) + +(define_attr "enabled" "" + (cond [(and (eq_attr "alt_tune" "onlya8") + (not (eq_attr "tune" "cortexa8"))) + (const_int 0) + + (and (eq_attr "alt_tune" "nota8") + (eq_attr "tune" "cortexa8")) + (const_int 0)] + (const_int 1))) + (include "arm-generic.md") (include "arm926ejs.md") (include "arm1020e.md") === modified file 'gcc/config/arm/neon.md' --- old/gcc/config/arm/neon.md 2010-08-10 13:31:21 +0000 +++ new/gcc/config/arm/neon.md 2010-08-13 11:40:17 +0000 @@ -827,23 +827,25 @@ ) (define_insn "adddi3_neon" - [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r") - (plus:DI (match_operand:DI 1 "s_register_operand" "%w,0,0") - (match_operand:DI 2 "s_register_operand" "w,r,0"))) + [(set (match_operand:DI 0 "s_register_operand" "=w,?w,?&r,?&r") + (plus:DI (match_operand:DI 1 "s_register_operand" "%w,w,0,0") + (match_operand:DI 2 "s_register_operand" "w,w,r,0"))) (clobber (reg:CC CC_REGNUM))] "TARGET_NEON" { switch (which_alternative) { - case 0: return "vadd.i64\t%P0, %P1, %P2"; - case 1: return "#"; + case 0: /* fall through */ + case 1: return "vadd.i64\t%P0, %P1, %P2"; case 2: return "#"; + case 3: return "#"; default: gcc_unreachable (); } } - [(set_attr "neon_type" "neon_int_1,*,*") - (set_attr "conds" "*,clob,clob") - (set_attr "length" "*,8,8")] + [(set_attr "neon_type" "neon_int_1,neon_int_1,*,*") + (set_attr "conds" "*,*,clob,clob") + (set_attr "length" "*,*,8,8") + (set_attr "alt_tune" "nota8,onlya8,*,*")] ) (define_insn "*sub3_neon" @@ -861,24 +863,26 @@ ) (define_insn "subdi3_neon" - [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r,?&r") - (minus:DI (match_operand:DI 1 "s_register_operand" "w,0,r,0") - (match_operand:DI 2 "s_register_operand" "w,r,0,0"))) + [(set (match_operand:DI 0 "s_register_operand" "=w,?w,?&r,?&r,?&r") + (minus:DI (match_operand:DI 1 "s_register_operand" "w,w,0,r,0") + (match_operand:DI 2 "s_register_operand" "w,w,r,0,0"))) (clobber (reg:CC CC_REGNUM))] "TARGET_NEON" { switch (which_alternative) { - case 0: return "vsub.i64\t%P0, %P1, %P2"; - case 1: /* fall through */ - case 2: /* fall through */ - case 3: return "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"; + case 0: /* fall through */ + case 1: return "vsub.i64\t%P0, %P1, %P2"; + case 2: /* fall through */ + case 3: /* fall through */ + case 4: return "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"; default: gcc_unreachable (); } } - [(set_attr "neon_type" "neon_int_2,*,*,*") - (set_attr "conds" "*,clob,clob,clob") - (set_attr "length" "*,8,8,8")] + [(set_attr "neon_type" "neon_int_2,neon_int_2,*,*,*") + (set_attr "conds" "*,*,clob,clob,clob") + (set_attr "length" "*,*,8,8,8") + (set_attr "alt_tune" "nota8,onlya8,*,*,*")] ) (define_insn "*mul3_neon" @@ -964,23 +968,26 @@ ) (define_insn "iordi3_neon" - [(set (match_operand:DI 0 "s_register_operand" "=w,w,?&r,?&r") - (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0,0,r") - (match_operand:DI 2 "neon_logic_op2" "w,Dl,r,r")))] + [(set (match_operand:DI 0 "s_register_operand" "=w,?w,w,?w,?&r,?&r") + (ior:DI (match_operand:DI 1 "s_register_operand" "%w,w,0,0,0,r") + (match_operand:DI 2 "neon_logic_op2" "w,w,Dl,Dl,r,r")))] "TARGET_NEON" { switch (which_alternative) { - case 0: return "vorr\t%P0, %P1, %P2"; - case 1: return neon_output_logic_immediate ("vorr", &operands[2], + case 0: /* fall through */ + case 1: return "vorr\t%P0, %P1, %P2"; + case 2: /* fall through */ + case 3: return neon_output_logic_immediate ("vorr", &operands[2], DImode, 0, VALID_NEON_QREG_MODE (DImode)); - case 2: return "#"; - case 3: return "#"; + case 4: return "#"; + case 5: return "#"; default: gcc_unreachable (); } } - [(set_attr "neon_type" "neon_int_1,neon_int_1,*,*") - (set_attr "length" "*,*,8,8")] + [(set_attr "neon_type" "neon_int_1,neon_int_1,neon_int_1,neon_int_1,*,*") + (set_attr "length" "*,*,*,*,8,8") + (set_attr "alt_tune" "nota8,onlya8,nota8,onlya8,*,*")] ) ;; The concrete forms of the Neon immediate-logic instructions are vbic and @@ -1006,23 +1013,26 @@ ) (define_insn "anddi3_neon" - [(set (match_operand:DI 0 "s_register_operand" "=w,w,?&r,?&r") - (and:DI (match_operand:DI 1 "s_register_operand" "%w,0,0,r") - (match_operand:DI 2 "neon_inv_logic_op2" "w,DL,r,r")))] + [(set (match_operand:DI 0 "s_register_operand" "=w,?w,w,?w,?&r,?&r") + (and:DI (match_operand:DI 1 "s_register_operand" "%w,w,0,0,0,r") + (match_operand:DI 2 "neon_inv_logic_op2" "w,w,DL,DL,r,r")))] "TARGET_NEON" { switch (which_alternative) { - case 0: return "vand\t%P0, %P1, %P2"; - case 1: return neon_output_logic_immediate ("vand", &operands[2], + case 0: /* fall through */ + case 1: return "vand\t%P0, %P1, %P2"; + case 2: /* fall through */ + case 3: return neon_output_logic_immediate ("vand", &operands[2], DImode, 1, VALID_NEON_QREG_MODE (DImode)); - case 2: return "#"; - case 3: return "#"; + case 4: return "#"; + case 5: return "#"; default: gcc_unreachable (); } } - [(set_attr "neon_type" "neon_int_1,neon_int_1,*,*") - (set_attr "length" "*,*,8,8")] + [(set_attr "neon_type" "neon_int_1,neon_int_1,neon_int_1,neon_int_1,*,*") + (set_attr "length" "*,*,*,*,8,8") + (set_attr "alt_tune" "nota8,onlya8,nota8,onlya8,*,*")] ) (define_insn "orn3_neon" @@ -1080,16 +1090,18 @@ ) (define_insn "xordi3_neon" - [(set (match_operand:DI 0 "s_register_operand" "=w,?&r,?&r") - (xor:DI (match_operand:DI 1 "s_register_operand" "%w,0,r") - (match_operand:DI 2 "s_register_operand" "w,r,r")))] + [(set (match_operand:DI 0 "s_register_operand" "=w,?w,?&r,?&r") + (xor:DI (match_operand:DI 1 "s_register_operand" "%w,w,0,r") + (match_operand:DI 2 "s_register_operand" "w,w,r,r")))] "TARGET_NEON" "@ veor\t%P0, %P1, %P2 + veor\t%P0, %P1, %P2 # #" - [(set_attr "neon_type" "neon_int_1,*,*") - (set_attr "length" "*,8,8")] + [(set_attr "neon_type" "neon_int_1,neon_int_1,*,*") + (set_attr "length" "*,*,8,8") + (set_attr "alt_tune" "nota8,onlya8,*,*")] ) (define_insn "one_cmpl2" === modified file 'gcc/config/arm/vfp.md' --- old/gcc/config/arm/vfp.md 2010-08-13 10:59:06 +0000 +++ new/gcc/config/arm/vfp.md 2010-08-13 11:40:17 +0000 @@ -133,9 +133,51 @@ ;; DImode moves (define_insn "*arm_movdi_vfp" - [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r,m,w,r,w,w, Uv") - (match_operand:DI 1 "di_operand" "rIK,mi,r,r,w,w,Uvi,w"))] - "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP + [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, m,w,r,w,w, Uv") + (match_operand:DI 1 "di_operand" "rIK,mi,r,r,w,w,Uvi,w"))] + "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP && arm_tune != cortexa8 + && ( register_operand (operands[0], DImode) + || register_operand (operands[1], DImode))" + "* + switch (which_alternative) + { + case 0: + return \"#\"; + case 1: + case 2: + return output_move_double (operands); + case 3: + return \"fmdrr%?\\t%P0, %Q1, %R1\\t%@ int\"; + case 4: + return \"fmrrd%?\\t%Q0, %R0, %P1\\t%@ int\"; + case 5: + if (TARGET_VFP_SINGLE) + return \"fcpys%?\\t%0, %1\\t%@ int\;fcpys%?\\t%p0, %p1\\t%@ int\"; + else + return \"fcpyd%?\\t%P0, %P1\\t%@ int\"; + case 6: case 7: + return output_move_vfp (operands); + default: + gcc_unreachable (); + } + " + [(set_attr "type" "*,load2,store2,r_2_f,f_2_r,ffarithd,f_loadd,f_stored") + (set_attr "neon_type" "*,*,*,neon_mcr_2_mcrr,neon_mrrc,neon_vmov,*,*") + (set (attr "length") (cond [(eq_attr "alternative" "0,1,2") (const_int 8) + (eq_attr "alternative" "5") + (if_then_else + (eq (symbol_ref "TARGET_VFP_SINGLE") (const_int 1)) + (const_int 8) + (const_int 4))] + (const_int 4))) + (set_attr "pool_range" "*,1020,*,*,*,*,1020,*") + (set_attr "neg_pool_range" "*,1008,*,*,*,*,1008,*")] +) + +(define_insn "*arm_movdi_vfp_cortexa8" + [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r,m,w,!r,w,w, Uv") + (match_operand:DI 1 "di_operand" "rIK,mi,r,r,w,w,Uvi,w"))] + "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP && arm_tune == cortexa8 && ( register_operand (operands[0], DImode) || register_operand (operands[1], DImode))" "* === modified file 'gcc/ira-costs.c' --- old/gcc/ira-costs.c 2009-11-25 10:55:54 +0000 +++ new/gcc/ira-costs.c 2010-08-13 11:40:17 +0000 @@ -224,6 +224,14 @@ int alt_fail = 0; int alt_cost = 0, op_cost_add; + if (!recog_data.alternative_enabled_p[alt]) + { + for (i = 0; i < recog_data.n_operands; i++) + constraints[i] = skip_alternative (constraints[i]); + + continue; + } + for (i = 0; i < n_ops; i++) { unsigned char c;