diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index cc85b79..6e7e353 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -679,8 +679,8 @@ (define_expand "mov" ;; "movqi_insn" ;; "movqq_insn" "movuqq_insn" (define_insn "mov_insn" - [(set (match_operand:ALL1 0 "nonimmediate_operand" "=r ,d ,Qm ,r ,q,r,*r") - (match_operand:ALL1 1 "nox_general_operand" "r Y00,n Ynn,r Y00,Qm,r,q,i"))] + [(set (match_operand:ALL1 0 "movdst_operand" "=r ,d ,Qm ,r ,q,r,*r") + (match_operand:ALL1 1 "nox_general_operand" "r Y00,n Ynn,r Y00,Qm,r,q,i"))] "(register_operand (operands[0], mode) || reg_or_0_operand (operands[1], mode)) && /* skip if operands are out of lds/sts memory access range(0x40..0xbf) @@ -3086,6 +3086,20 @@ (define_peephole2 ; andi operands[1] = GEN_INT (INTVAL (operands[1]) & INTVAL (operands[2])); }) +; standard promotion can get us a 16 bit int where only an 8 bit value +; is required. combine-split extend-binop-store to binop-store. + +(define_split + [(set (match_operand:QI 0 "any_qi_mem_operand") + (match_operator 3 "avr_binary_operator" + [(match_operand 1 "nonmemory_operand") + (match_operand 2 "nonmemory_operand")])) + (clobber (match_operand:QI 4 "register_operand"))] + "" + [(set (match_dup 4) (match_dup 3)) + (set (match_dup 0) (match_dup 4))] + ""); + ;;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ;; ior diff --git a/gcc/config/avr/predicates.md b/gcc/config/avr/predicates.md index 4b456a5..ea8e095 100644 --- a/gcc/config/avr/predicates.md +++ b/gcc/config/avr/predicates.md @@ -69,6 +69,24 @@ (define_predicate "nop_general_operand" (and (match_operand 0 "general_operand") (match_test "!avr_mem_flash_p (op)"))) +; allow a QImode memory operand, including volatile / I/O. +(define_predicate "any_qi_mem_operand" + (and (match_code "mem") + (match_test "address_operand (XEXP (op, 0), Pmode)") + (match_test "mode == QImode"))) + +;; We also allow volatile memory here, so that the combiner can work with +;; stores for I/O accesses as combiner-splitter results. +;; As this is for a destination location, that should generally be safe +;; for combine, as we should he handling the last insn then, which stays +;; in place. +;; ??? Could this ever match for a two-destination combination? +;; ??? Should we make sure this predicate can't match I/O for transformations +;; with a wider scope, like store sinking? +(define_predicate "movdst_operand" + (ior (match_operand 0 "nonimmediate_operand") + (match_operand 0 "any_qi_mem_operand"))) + ;; Return 1 if OP is an "ordinary" general operand, i.e. a general ;; operand whose load is not handled by a libgcc call or ELPM. (define_predicate "nox_general_operand" @@ -180,6 +198,10 @@ (define_predicate "simple_comparison_operator" (and (match_operand 0 "comparison_operator") (not (match_code "gt,gtu,le,leu")))) +; A binary operator that the avr can perform in a single insn. +(define_predicate "avr_binary_operator" + (match_code "and,ior,xor,plus,minus")) + ;; Return true if OP is a valid call operand. (define_predicate "call_insn_operand" (and (match_code "mem")