On Wed, Jun 29, 2016 at 9:59 AM, Virendra Pathak
<virendra.pat...@broadcom.com> wrote:
> Hi gcc-patches group,
>
> I am working on adding vulcan.md (machine description) for vulcan cpu
> in the aarch64 port. However, before proposing the final patch, I would like
> the basic approach to be reviewed by you all (as changes are there in
> aarch64.md)
>
> In vulcan, a (load/store) instruction could be scheduled to cpu units in
> different way based on the addressing mode(e.g. load, or load+integer).
> So the requirement is to identify the addressing mode of (load/store)
> instruction's operand while scheduling.
>
> For this purpose, a new attribute "addr_type" has been added in the
> aarch64.md file. This helps in identifying which operands of (load/store)
> instruction should be considered for finding the addressing mode.
>
> vulcan.md, while scheduling, calls a new function aarch64_mem_type_p
> in the aarch64.c (via match_test) to decide the scheduling option based
> on the addressing mode.
>
> I have copied the code snippet below (complete patch is attached with
> this mail).
>
> Kindly review and give your feedback/comment.
> Also if you think there could be an better alternative way, kindly suggest.


Since this is only about post and pre increment being split into two
micro-ops.  I suspect something like what rs600 back-end does is
better:
;; Does this instruction use update addressing?
;; This is used for load and store insns.  See the comments for "indexed".
(define_attr "update" "no,yes"
  (if_then_else (ior (match_operand 0 "update_address_mem")
                     (match_operand 1 "update_address_mem"))
                (const_string "yes")
                (const_string "no")))

Where update_address_mem is defined as:
;; Return 1 if the operand is a MEM with an update-form address. This may
;; also include update-indexed form.
(define_special_predicate "update_address_mem"
  (match_test "(MEM_P (op)
                && (GET_CODE (XEXP (op, 0)) == PRE_INC
                    || GET_CODE (XEXP (op, 0)) == PRE_DEC
                    || GET_CODE (XEXP (op, 0)) == PRE_MODIFY))"))


Note you need to include the POST ones for AARCH64 but it should be
similar enough.
And then you just check the attr update.

Thanks,
Andrew

>
> Thanks in advance for your time.
>
> <Code Snippet>
>
> FILE - gcc/config/aarch64/aarch64-protos.h
>
> /* Mask bits to use for for aarch64_mem_type_p.  Unshifted/shifted index
>    register variants are separated for scheduling purposes because the
>    distinction matters on some cores.  */
> #define AARCH64_ADDR_REG_IMM           0x01
> #define AARCH64_ADDR_REG_WB            0x02
> #define AARCH64_ADDR_REG_REG           0x04
> #define AARCH64_ADDR_REG_SHIFT         0x08
> #define AARCH64_ADDR_REG_EXT           0x10
> #define AARCH64_ADDR_REG_SHIFT_EXT     0x20
> #define AARCH64_ADDR_LO_SUM            0x40
> #define AARCH64_ADDR_SYMBOLIC          0x80
>
>
>
>
> FILE - gcc/config/aarch64/aarch64.md
>
> (define_attr "addr_type" "none,op0,op1,op0addr,op1addr,lo_sum,wb"
>   (const_string "none"))
>
>
> (define_insn "*mov<mode>_aarch64"
>   [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r,
> *w,r,*w, m, m, r,*w,*w")
>         (match_operand:SHORT 1 "general_operand"      " r,M,D<hq>,m,
> m,rZ,*w,*w, r,*w"))]
>   "(register_operand (operands[0], <MODE>mode)
>     || aarch64_reg_or_zero (operands[1], <MODE>mode))"
>
> {
>    switch (which_alternative)
>      {
>      case 0:
>        return "mov\t%w0, %w1";
>      case 1:
>        return "mov\t%w0, %1";
>      case 2:
>        return aarch64_output_scalar_simd_mov_immediate (operands[1],
>                                                         <MODE>mode);
>      case 3:
>        return "ldr<size>\t%w0, %1";
>      case 4:
>        return "ldr\t%<size>0, %1";
>      case 5:
>        return "str<size>\t%w1, %0";
>      case 6:
>        return "str\t%<size>1, %0";
>      case 7:
>        return "umov\t%w0, %1.<v>[0]";
>      case 8:
>        return "dup\t%0.<Vallxd>, %w1";
>      case 9:
>        return "dup\t%<Vetype>0, %1.<v>[0]";
>      default:
>        gcc_unreachable ();
>      }
> }
>   [(set_attr "type" "mov_reg,mov_imm,neon_move,load1,load1,store1,store1,\
>                      neon_to_gp<q>,neon_from_gp<q>,neon_dup")
>    (set_attr "simd" "*,*,yes,*,*,*,*,yes,yes,yes")
>    (set_attr "addr_type" "*,*,*,op1,op1,op0,op0,*,*,*")]
> )
>
>
>
>
> FILE - gcc/config/aarch64/vulcan.md
> ;; Integer loads and stores.
>
> (define_insn_reservation "vulcan_load_basic" 4
>   (and (eq_attr "tune" "vulcan")
>        (eq_attr "type" "load1")
>        (match_test "aarch64_mem_type_p (insn, AARCH64_ADDR_SYMBOLIC
>                                               | AARCH64_ADDR_REG_IMM
>                                               | AARCH64_ADDR_LO_SUM)"))
>   "vulcan_ls01")
>
> (define_insn_reservation "vulcan_load_automod" 4
>   (and (eq_attr "tune" "vulcan")
>        (eq_attr "type" "load1")
>        (match_test "aarch64_mem_type_p (insn, AARCH64_ADDR_REG_WB)"))
>   "vulcan_ls01,vulcan_i012")
>
>
>
>
> FILE - gcc/config/aarch64/aarch64.c
>
> /* Return TRUE if INSN uses an address that satisfies any of the (non-strict)
>    addressing modes specified by MASK.  This is intended for use in scheduling
>    models that are sensitive to the form of address used by some particular
>    instruction.  */
>
> bool
> aarch64_mem_type_p (rtx_insn *insn, unsigned HOST_WIDE_INT mask)
> {
>   aarch64_address_info info;
>   bool valid;
>   attr_addr_type addr_type;
>   rtx mem, addr;
>   machine_mode mode;
>
>   addr_type = get_attr_addr_type (insn);
>
>   switch (addr_type)
>     {
>     case ADDR_TYPE_WB:
>       info.type = ADDRESS_REG_WB;
>       break;
>
>     case ADDR_TYPE_LO_SUM:
>       info.type = ADDRESS_LO_SUM;
>       break;
>
>     case ADDR_TYPE_OP0:
>     case ADDR_TYPE_OP1:
>       extract_insn_cached (insn);
>
>       mem = recog_data.operand[(addr_type == ADDR_TYPE_OP0) ? 0 : 1];
>
>       gcc_assert (MEM_P (mem));
>
>       addr = XEXP (mem, 0);
>       mode = GET_MODE (mem);
>
>     classify:
>       valid = aarch64_classify_address (&info, addr, mode, MEM, false);
>       if (!valid)
>        return false;
>
>       break;
>
>     case ADDR_TYPE_OP0ADDR:
>     case ADDR_TYPE_OP1ADDR:
>       extract_insn_cached (insn);
>
>       addr = recog_data.operand[(addr_type == ADDR_TYPE_OP0ADDR) ? 0 : 1];
>       mode = DImode;
>       goto classify;
>
>     case ADDR_TYPE_NONE:
>       return false;
>     }
>
>   switch (info.type)
>     {
>     case ADDRESS_REG_IMM:
>       return (mask & AARCH64_ADDR_REG_IMM) != 0;
>     case ADDRESS_REG_WB:
>       return (mask & AARCH64_ADDR_REG_WB) != 0;
>     case ADDRESS_REG_REG:
>       if (info.shift == 0)
>        return (mask & AARCH64_ADDR_REG_REG) != 0;
>       else
>         return (mask & AARCH64_ADDR_REG_SHIFT) != 0;
>     case ADDRESS_REG_UXTW:
>     case ADDRESS_REG_SXTW:
>       if (info.shift == 0)
>        return (mask & AARCH64_ADDR_REG_EXT) != 0;
>       else
>        return (mask & AARCH64_ADDR_REG_SHIFT_EXT) != 0;
>     case ADDRESS_LO_SUM:
>       return (mask & AARCH64_ADDR_LO_SUM) != 0;
>     case ADDRESS_SYMBOLIC:
>       return (mask & AARCH64_ADDR_SYMBOLIC) != 0;
>     default:
>       return false;
>     }
> }
>
>
> <END>
>
> with regards,
> Virendra Pathak

Reply via email to