On Wed, Jun 29, 2016 at 9:59 AM, Virendra Pathak
<[email protected]> 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