Hi This is the third part of the fixing for
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47855 This patch contains the length computation/refinement for insn patterns "*thumb2_movsi_insn", "*thumb2_cbz" and "*thumb2_cbnz". At the same time this patch revealed two bugs. The first is the maximum offset of cbz/cbnz, it should be 126, but it is 128 in patterns "*thumb2_cbz" and "*thumb2_cbnz". The second is that only 2-register form of shift instructions can be 16 bit, but 3-register form is allowed in "*thumb2_shiftsi3_short" and related peephole2. The fix is also contained in this patch. The patch has been tested on arm qemu. thanks Carrot 2011-05-05 Guozhi Wei <car...@google.com> PR target/47855 * config/arm/thumb2.md (thumb2_movsi_insn): Add length addtribute. (thumb2_shiftsi3_short and peephole2): Remove 3-register case. (thumb2_cbz): Refine length computation. (thumb2_cbnz): Likewise. Index: config/arm/thumb2.md =================================================================== --- config/arm/thumb2.md (revision 173350) +++ config/arm/thumb2.md (working copy) @@ -165,25 +165,49 @@ ;; regs. The high register alternatives are not taken into account when ;; choosing register preferences in order to reflect their expense. (define_insn "*thumb2_movsi_insn" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,l ,*hk,m,*m") - (match_operand:SI 1 "general_operand" "rk ,I,K,j,mi,*mi,l,*hk"))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=l,rk,r,r,r,l ,*rk,Uu,*m") + (match_operand:SI 1 "general_operand" "l ,rk,I,K,j,Uu,*mi,l ,*rk"))] "TARGET_THUMB2 && ! TARGET_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_VFP) && ( register_operand (operands[0], SImode) || register_operand (operands[1], SImode))" - "@ - mov%?\\t%0, %1 - mov%?\\t%0, %1 - mvn%?\\t%0, #%B1 - movw%?\\t%0, %1 - ldr%?\\t%0, %1 - ldr%?\\t%0, %1 - str%?\\t%1, %0 - str%?\\t%1, %0" - [(set_attr "type" "*,*,*,*,load1,load1,store1,store1") + "* + switch (which_alternative) + { + case 0: return \"mov%?\\t%0, %1\"; + case 1: return \"mov%?\\t%0, %1\"; + case 2: return \"mov%?\\t%0, %1\"; + case 3: return \"mvn%?\\t%0, #%B1\"; + case 4: return \"movw%?\\t%0, %1\"; + + case 5: + if (GET_CODE (XEXP (operands[1], 0)) == POST_INC) + { + operands[1] = XEXP (XEXP (operands[1], 0), 0); + return \"ldm%(ia%)\t%1!, {%0}\"; + } + else + return \"ldr%?\\t%0, %1\"; + + case 6: return \"ldr%?\\t%0, %1\"; + + case 7: + if (GET_CODE (XEXP (operands[0], 0)) == POST_INC) + { + operands[0] = XEXP (XEXP (operands[0], 0), 0); + return \"stm%(ia%)\t%0!, {%1}\"; + } + else + return \"str%?\\t%1, %0\"; + + case 8: return \"str%?\\t%1, %0\"; + default: gcc_unreachable (); + }" + [(set_attr "type" "*,*,*,*,*,load1,load1,store1,store1") (set_attr "predicable" "yes") - (set_attr "pool_range" "*,*,*,*,1020,4096,*,*") - (set_attr "neg_pool_range" "*,*,*,*,0,0,*,*")] + (set_attr "length" "2,4,4,4,4,2,4,2,4") + (set_attr "pool_range" "*,*,*,*,*,1020,4096,*,*") + (set_attr "neg_pool_range" "*,*,*,*,*,0,0,*,*")] ) (define_insn "tls_load_dot_plus_four" @@ -685,7 +709,8 @@ "TARGET_THUMB2 && peep2_regno_dead_p(0, CC_REGNUM) && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT) - || REG_P(operands[2]))" + || REG_P(operands[2])) + && (CONSTANT_P (operands[2]) || (operands[0] == operands[1]))" [(parallel [(set (match_dup 0) (match_op_dup 3 @@ -696,10 +721,10 @@ ) (define_insn "*thumb2_shiftsi3_short" - [(set (match_operand:SI 0 "low_register_operand" "=l") + [(set (match_operand:SI 0 "low_register_operand" "=l,l") (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "low_register_operand" "l") - (match_operand:SI 2 "low_reg_or_int_operand" "lM")])) + [(match_operand:SI 1 "low_register_operand" "0,l") + (match_operand:SI 2 "low_reg_or_int_operand" "l,M")])) (clobber (reg:CC CC_REGNUM))] "TARGET_THUMB2 && reload_completed && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT) @@ -707,7 +732,7 @@ "* return arm_output_shift(operands, 2);" [(set_attr "predicable" "yes") (set_attr "shift" "1") - (set_attr "length" "2") + (set_attr "length" "2,2") (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") (const_string "alu_shift") (const_string "alu_shift_reg")))] @@ -965,13 +990,23 @@ else return \"cmp\\t%0, #0\;beq\\t%l1\"; " - [(set (attr "length") - (if_then_else - (and (ge (minus (match_dup 1) (pc)) (const_int 2)) - (le (minus (match_dup 1) (pc)) (const_int 128)) - (eq (symbol_ref ("which_alternative")) (const_int 0))) - (const_int 2) - (const_int 8)))] + [(set (attr "length") + (if_then_else + (eq (symbol_ref ("which_alternative")) (const_int 0)) + (if_then_else + (and (ge (minus (match_dup 1) (pc)) (const_int 2)) + (le (minus (match_dup 1) (pc)) (const_int 126))) + (const_int 2) + (if_then_else + (and (ge (minus (match_dup 1) (pc)) (const_int -256)) + (le (minus (match_dup 1) (pc)) (const_int 254))) + (const_int 4) + (const_int 6))) + (if_then_else + (and (ge (minus (match_dup 1) (pc)) (const_int -256)) + (le (minus (match_dup 1) (pc)) (const_int 254))) + (const_int 6) + (const_int 8))))] ) (define_insn "*thumb2_cbnz" @@ -988,13 +1023,23 @@ else return \"cmp\\t%0, #0\;bne\\t%l1\"; " - [(set (attr "length") - (if_then_else - (and (ge (minus (match_dup 1) (pc)) (const_int 2)) - (le (minus (match_dup 1) (pc)) (const_int 128)) - (eq (symbol_ref ("which_alternative")) (const_int 0))) - (const_int 2) - (const_int 8)))] + [(set (attr "length") + (if_then_else + (eq (symbol_ref ("which_alternative")) (const_int 0)) + (if_then_else + (and (ge (minus (match_dup 1) (pc)) (const_int 2)) + (le (minus (match_dup 1) (pc)) (const_int 126))) + (const_int 2) + (if_then_else + (and (ge (minus (match_dup 1) (pc)) (const_int -256)) + (le (minus (match_dup 1) (pc)) (const_int 254))) + (const_int 4) + (const_int 6))) + (if_then_else + (and (ge (minus (match_dup 1) (pc)) (const_int -256)) + (le (minus (match_dup 1) (pc)) (const_int 254))) + (const_int 6) + (const_int 8))))] ) ;; 16-bit complement -- This patch is available for review at http://codereview.appspot.com/4475042