diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index ccad548..b514757 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -21271,7 +21271,15 @@ arm_print_condition (FILE *stream) } -/* If CODE is 'd', then the X is a condition operand and the instruction +/* Globally reserved letters: acln + Puncutation letters currently used: @_|?().!# + Lower case letters currently used: bcdefhimpqtvwxyz + Upper case letters currently used: ABCDFGHJKLMNOPQRSTU + Letters previously used, but now deprecated/obsolete: sVWXYZ. + + Note that the global reservation for 'c' is only for CONSTANT_ADDRESS_P. + + If CODE is 'd', then the X is a condition operand and the instruction should only be executed if the condition is true. if CODE is 'D', then the X is a condition operand and the instruction should only be executed if the condition is false: however, if the mode @@ -21411,6 +21419,19 @@ arm_print_operand (FILE *stream, rtx x, int code) } return; + case 'b': + /* Print the log2 of a CONST_INT. */ + { + HOST_WIDE_INT val; + + if (!CONST_INT_P (x) + || (val = exact_log2 (INTVAL (x) & 0xffffffff)) < 0) + output_operand_lossage ("Unsupported operand for code '%c'", code); + else + fprintf (stream, "#" HOST_WIDE_INT_PRINT_DEC, val); + } + return; + case 'L': /* The low 16 bits of an immediate constant. */ fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL(x) & 0xffff); diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 348a89c..cd7495f 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -200,17 +200,9 @@ (const_string "yes")] (const_string "no"))) -; Allows an insn to disable certain alternatives for reasons other than -; arch support. -(define_attr "insn_enabled" "no,yes" - (const_string "yes")) - ; Enable all alternatives that are both arch_enabled and insn_enabled. (define_attr "enabled" "no,yes" - (cond [(eq_attr "insn_enabled" "no") - (const_string "no") - - (and (eq_attr "predicable_short_it" "no") + (cond [(and (eq_attr "predicable_short_it" "no") (and (eq_attr "predicated" "yes") (match_test "arm_restrict_it"))) (const_string "no") @@ -9876,38 +9868,34 @@ ;; Patterns to allow combination of arithmetic, cond code and shifts -(define_insn "*arith_shiftsi" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r") - (match_operator:SI 1 "shiftable_operator" - [(match_operator:SI 3 "shift_operator" - [(match_operand:SI 4 "s_register_operand" "r,r,r,r") - (match_operand:SI 5 "shift_amount_operand" "M,M,M,r")]) - (match_operand:SI 2 "s_register_operand" "rk,rk,r,rk")]))] +(define_insn "*_multsi" + [(set (match_operand:SI 0 "s_register_operand" "=r,r") + (shiftable_ops:SI + (mult:SI (match_operand:SI 2 "s_register_operand" "r,r") + (match_operand:SI 3 "power_of_two_operand" "")) + (match_operand:SI 1 "s_register_operand" "rk,")))] "TARGET_32BIT" - "%i1%?\\t%0, %2, %4%S3" + "%?\\t%0, %1, %2, lsl %b3" + [(set_attr "predicable" "yes") + (set_attr "predicable_short_it" "no") + (set_attr "shift" "4") + (set_attr "arch" "a,t2") + (set_attr "type" "alu_shift_imm")]) + +(define_insn "*_shiftsi" + [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") + (shiftable_ops:SI + (match_operator:SI 2 "shift_nomul_operator" + [(match_operand:SI 3 "s_register_operand" "r,r,r") + (match_operand:SI 4 "shift_amount_operand" "M,M,r")]) + (match_operand:SI 1 "s_register_operand" "rk,,rk")))] + "TARGET_32BIT && GET_CODE (operands[3]) != MULT" + "%?\\t%0, %1, %3%S2" [(set_attr "predicable" "yes") (set_attr "predicable_short_it" "no") (set_attr "shift" "4") - (set_attr "arch" "a,t2,t2,a") - ;; Thumb2 doesn't allow the stack pointer to be used for - ;; operand1 for all operations other than add and sub. In this case - ;; the minus operation is a candidate for an rsub and hence needs - ;; to be disabled. - ;; We have to make sure to disable the fourth alternative if - ;; the shift_operator is MULT, since otherwise the insn will - ;; also match a multiply_accumulate pattern and validate_change - ;; will allow a replacement of the constant with a register - ;; despite the checks done in shift_operator. - (set_attr_alternative "insn_enabled" - [(const_string "yes") - (if_then_else - (match_operand:SI 1 "add_operator" "") - (const_string "yes") (const_string "no")) - (const_string "yes") - (if_then_else - (match_operand:SI 3 "mult_operator" "") - (const_string "no") (const_string "yes"))]) - (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_imm,alu_shift_reg")]) + (set_attr "arch" "a,t2,a") + (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")]) (define_split [(set (match_operand:SI 0 "s_register_operand" "") diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index aebab93..1c41c6d 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -191,6 +191,20 @@ ;; Right shifts (define_code_iterator rshifts [ashiftrt lshiftrt]) +;; Binary operators whose second operand can be shifted. +(define_code_iterator shiftable_ops [plus minus ior xor and]) + +;; plus and minus are the only shiftable_ops for which Thumb2 allows +;; a stack pointer opoerand. The minus operation is a candidate for an rsub +;; and hence only plus is supported. +(define_code_attr t2_binop0 + [(plus "rk") (minus "r") (ior "r") (xor "r") (and "r")]) + +;; The instruction to use when a shiftable_ops has a shift operation as +;; its first operand. +(define_code_attr arith_shift_insn + [(plus "add") (minus "rsb") (ior "orr") (xor "eor") (and "and")]) + ;;---------------------------------------------------------------------------- ;; Int iterators ;;---------------------------------------------------------------------------- diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index d74fcb3..032808c 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -291,6 +291,15 @@ || ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1))) < 32"))) (match_test "mode == GET_MODE (op)"))) +(define_special_predicate "shift_nomul_operator" + (and (ior (and (match_code "rotate") + (match_test "CONST_INT_P (XEXP (op, 1)) + && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1))) < 32")) + (and (match_code "ashift,ashiftrt,lshiftrt,rotatert") + (match_test "!CONST_INT_P (XEXP (op, 1)) + || ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1))) < 32"))) + (match_test "mode == GET_MODE (op)"))) + ;; True for shift operators which can be used with saturation instructions. (define_special_predicate "sat_shift_operator" (and (ior (and (match_code "mult")