@@ -609,31 +609,70 @@ th_memidx_classify_address_index (struct riscv_address_info *info, rtx x,
if (GET_CODE (x) != PLUS)
return false;
- rtx reg = XEXP (x, 0);
+ rtx op0 = XEXP (x, 0);
+ rtx op1 = XEXP (x, 1);
enum riscv_address_type type;
- rtx offset = XEXP (x, 1);
int shift;
+ rtx reg = op0;
+ rtx offset = op1;
if (!riscv_valid_base_register_p (reg, mode, strict_p))
- return false;
+ {
+ reg = op1;
+ offset = op0;
+ if (!riscv_valid_base_register_p (reg, mode, strict_p))
+ return false;
+ }
/* (reg:X) */
- if (REG_P (offset)
+ if ((REG_P (offset) || SUBREG_P (offset))
&& GET_MODE (offset) == Xmode)
{
type = ADDRESS_REG_REG;
shift = 0;
offset = offset;
}
- /* (zero_extend:DI (reg:SI)) */
- else if (GET_CODE (offset) == ZERO_EXTEND
+ /* (any_extend:DI (reg:SI)) */
+ else if (TARGET_64BIT
+ && (GET_CODE (offset) == SIGN_EXTEND
+ || GET_CODE (offset) == ZERO_EXTEND)
&& GET_MODE (offset) == DImode
&& GET_MODE (XEXP (offset, 0)) == SImode)
{
- type = ADDRESS_REG_UREG;
+ type = (GET_CODE (offset) == SIGN_EXTEND)
+ ? ADDRESS_REG_REG : ADDRESS_REG_UREG;
shift = 0;
offset = XEXP (offset, 0);
}
+ /* (mult:X (reg:X) (const_int scale)) */
+ else if (GET_CODE (offset) == MULT
+ && GET_MODE (offset) == Xmode
+ && REG_P (XEXP (offset, 0))
+ && GET_MODE (XEXP (offset, 0)) == Xmode
+ && CONST_INT_P (XEXP (offset, 1))
+ && pow2p_hwi (INTVAL (XEXP (offset, 1)))
+ && IN_RANGE (exact_log2 (INTVAL (XEXP (offset, 1))), 1, 3))
+ {
+ type = ADDRESS_REG_REG;
+ shift = exact_log2 (INTVAL (XEXP (offset, 1)));
+ offset = XEXP (offset, 0);
+ }
+ /* (mult:DI (any_extend:DI (reg:SI)) (const_int scale)) */
+ else if (TARGET_64BIT
+ && GET_CODE (offset) == MULT
+ && GET_MODE (offset) == DImode
+ && (GET_CODE (XEXP (offset, 0)) == SIGN_EXTEND
+ || GET_CODE (XEXP (offset, 0)) == ZERO_EXTEND)
+ && GET_MODE (XEXP (offset, 0)) == DImode
+ && REG_P (XEXP (XEXP (offset, 0), 0))
+ && GET_MODE (XEXP (XEXP (offset, 0), 0)) == SImode
+ && CONST_INT_P (XEXP (offset, 1)))
+ {
+ type = (GET_CODE (XEXP (offset, 0)) == SIGN_EXTEND)
+ ? ADDRESS_REG_REG : ADDRESS_REG_UREG;
+ shift = exact_log2 (INTVAL (XEXP (x, 1)));
+ offset = XEXP (XEXP (x, 0), 0);
+ }
/* (ashift:X (reg:X) (const_int shift)) */
else if (GET_CODE (offset) == ASHIFT
&& GET_MODE (offset) == Xmode
@@ -646,23 +685,46 @@ th_memidx_classify_address_index (struct riscv_address_info *info, rtx x,
shift = INTVAL (XEXP (offset, 1));
offset = XEXP (offset, 0);
}
- /* (ashift:DI (zero_extend:DI (reg:SI)) (const_int shift)) */
- else if (GET_CODE (offset) == ASHIFT
+ /* (ashift:DI (any_extend:DI (reg:SI)) (const_int shift)) */
+ else if (TARGET_64BIT
+ && GET_CODE (offset) == ASHIFT
&& GET_MODE (offset) == DImode
- && GET_CODE (XEXP (offset, 0)) == ZERO_EXTEND
+ && (GET_CODE (XEXP (offset, 0)) == SIGN_EXTEND
+ || GET_CODE (XEXP (offset, 0)) == ZERO_EXTEND)
&& GET_MODE (XEXP (offset, 0)) == DImode
&& GET_MODE (XEXP (XEXP (offset, 0), 0)) == SImode
&& CONST_INT_P (XEXP (offset, 1))
&& IN_RANGE(INTVAL (XEXP (offset, 1)), 0, 3))
{
- type = ADDRESS_REG_UREG;
+ type = (GET_CODE (XEXP (offset, 0)) == SIGN_EXTEND)
+ ? ADDRESS_REG_REG : ADDRESS_REG_UREG;
shift = INTVAL (XEXP (offset, 1));
offset = XEXP (XEXP (offset, 0), 0);
}
+ /* (and:X (mult:X (reg:X) (const_int scale)) (const_int mask)) */
+ else if (TARGET_64BIT
+ && GET_CODE (offset) == AND
+ && GET_MODE (offset) == DImode
+ && GET_CODE (XEXP (offset, 0)) == MULT
+ && GET_MODE (XEXP (offset, 0)) == DImode
+ && REG_P (XEXP (XEXP (offset, 0), 0))
+ && GET_MODE (XEXP (XEXP (offset, 0), 0)) == DImode
+ && CONST_INT_P (XEXP (XEXP (offset, 0), 1))
+ && pow2p_hwi (INTVAL (XEXP (XEXP (offset, 0), 1)))
+ && IN_RANGE (exact_log2 (INTVAL (XEXP (XEXP (offset, 0), 1))), 1, 3)
+ && CONST_INT_P (XEXP (offset, 1))
+ && INTVAL (XEXP (offset, 1))
+ >> exact_log2 (INTVAL (XEXP (XEXP (offset, 0), 1))) == 0xffffffff)
+ {
+ type = ADDRESS_REG_UREG;
+ shift = exact_log2 (INTVAL (XEXP (XEXP (offset, 0), 1)));
+ offset = XEXP (XEXP (offset, 0), 0);
+ }
else
return false;
- if (!strict_p && GET_CODE (offset) == SUBREG)
+ if (!strict_p && SUBREG_P (offset)
+ && GET_MODE (SUBREG_REG (offset)) == SImode)
offset = SUBREG_REG (offset);
if (!REG_P (offset)
@@ -774,7 +836,7 @@ th_fmemidx_output_index (rtx dest, rtx src, machine_mode mode, bool load)
rtx x = th_get_move_mem_addr (dest, src, load);
/* Validate x. */
- if (!th_memidx_classify_address_index (&info, x, mode, false))
+ if (!th_memidx_classify_address_index (&info, x, mode, reload_completed))
return NULL;
int index = exact_log2 (GET_MODE_SIZE (mode).to_constant ()) - 2;
@@ -456,26 +456,6 @@ (define_insn "*th_mempair_load_zero_extendsidi2"
;; XTheadMemIdx
-;; Help reload to add a displacement for the base register.
-;; In the case `zext(*(uN*)(base+(zext(rN)<<1)))` LRA splits
-;; off two new instructions: a) `new_base = base + disp`, and
-;; b) `index = zext(rN)<<1`. The index calculation has no
-;; corresponding instruction pattern and needs this insn_and_split
-;; to recover.
-
-(define_insn_and_split "*th_memidx_operand"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (ashift:DI
- (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
- (match_operand 2 "const_int_operand" "n")))]
- "TARGET_64BIT && TARGET_XTHEADMEMIDX && lra_in_progress"
- "#"
- ""
- [(set (match_dup 0) (zero_extend:DI (match_dup 1)))
- (set (match_dup 0) (ashift:DI (match_dup 0) (match_dup 2)))]
- ""
- [(set_attr "type" "bitmanip")])
-
(define_insn "*th_memidx_zero_extendqi<SUPERQI:mode>2"
[(set (match_operand:SUPERQI 0 "register_operand" "=r,r,r,r,r,r")
(zero_extend:SUPERQI
@@ -654,401 +634,4 @@ (define_insn "*th_memidx_bb_extendqi<SUPERQI:mode>2"
[(set_attr "move_type" "shift_shift,load,load,load,load,load")
(set_attr "mode" "<SUPERQI:MODE>")])
-;; All modes that are supported by XTheadMemIdx
-(define_mode_iterator TH_M_ANYI [(QI "TARGET_XTHEADMEMIDX")
- (HI "TARGET_XTHEADMEMIDX")
- (SI "TARGET_XTHEADMEMIDX")
- (DI "TARGET_64BIT && TARGET_XTHEADMEMIDX")])
-
-;; All modes that are supported by XTheadFMemIdx
-(define_mode_iterator TH_M_ANYF [(SF "TARGET_HARD_FLOAT && TARGET_XTHEADFMEMIDX")
- (DF "TARGET_DOUBLE_FLOAT && TARGET_XTHEADFMEMIDX")])
-
-;; All non-extension modes that are supported by XTheadMemIdx
-(define_mode_iterator TH_M_NOEXTI [(SI "!TARGET_64BIT && TARGET_XTHEADMEMIDX")
- (DI "TARGET_64BIT && TARGET_XTHEADMEMIDX")])
-
-;; All non-extension modes that are supported by XTheadFMemIdx
-(define_mode_iterator TH_M_NOEXTF [(SF "TARGET_HARD_FLOAT && TARGET_XTHEADFMEMIDX")
- (DF "TARGET_DOUBLE_FLOAT && TARGET_XTHEADFMEMIDX")])
-
-;; XTheadMemIdx optimizations
-;; All optimizations attempt to improve the operand utilization of
-;; XTheadMemIdx instructions, where one sign or zero extended
-;; register-index-operand can be shifted left by a 2-bit immediate.
-;;
-;; The basic idea is the following optimization:
-;; (set (reg 0) (op (reg 1) (imm 2)))
-;; (set (reg 3) (mem (plus (reg 0) (reg 4)))
-;; ==>
-;; (set (reg 3) (mem (plus (reg 4) (op2 (reg 1) (imm 2))))
-;; This optimization only valid if (reg 0) has no further uses.
-;;
-;; The three-instruction case is as follows:
-;; (set (reg 0) (op1 (reg 1) (imm 2)))
-;; (set (reg 3) (op2 (reg 0) (imm 4)))
-;; (set (reg 5) (mem (plus (reg 3) (reg 6)))
-;; ==>
-;; (set (reg 5) (mem (plus (reg 6) (op2 (reg 1) (imm 2/4)))))
-;; This optimization is only valid if (reg 0) and (reg 3) have no further uses.
-;;
-;; The optimization cases are:
-;; I) fold 2-bit ashift of register offset into mem-plus RTX
-;; US) fold 32-bit zero-extended (shift) offset into mem-plus
-;; UZ) fold 32-bit zero-extended (zext) offset into mem-plus
-;;
-;; The first optimization case is targeting the th.lr<MODE> instructions.
-;; The other optimization cases are targeting the th.lur<MODE> instructions
-;; and have to consider two forms of zero-extensions:
-;; - ashift-32 + lshiftrt-{29..32} if there are no zero-extension instructions.
-;; Left-shift amounts of 29..31 indicate a left-shifted zero-extended value.
-;; - zero-extend32 if there are zero-extension instructions (XTheadBb or Zbb).
-;;
-;; We always have three peephole passes per optimization case:
-;; a) no-extended (X) word-load
-;; b) any-extend (SUBX) word-load
-;; c) store
-;;
-;; Note, that SHIFTs will be converted to MULTs during combine.
-
-(define_insn_and_split "*th_memidx_I_a"
- [(set (match_operand:TH_M_NOEXTI 0 "register_operand" "=r")
- (mem:TH_M_NOEXTI (plus:X
- (mult:X (match_operand:X 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i"))
- (match_operand:X 3 "register_operand" "r"))))]
- "TARGET_XTHEADMEMIDX
- && CONST_INT_P (operands[2])
- && pow2p_hwi (INTVAL (operands[2]))
- && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)"
- "#"
- "&& 1"
- [(set (match_dup 0)
- (mem:TH_M_NOEXTI (plus:X
- (match_dup 3)
- (ashift:X (match_dup 1) (match_dup 2)))))]
- { operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
- }
-)
-
-(define_insn_and_split "*th_memidx_I_b"
- [(set (match_operand:X 0 "register_operand" "=r")
- (any_extend:X (mem:SUBX (plus:X
- (mult:X (match_operand:X 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i"))
- (match_operand:X 3 "register_operand" "r")))))]
- "TARGET_XTHEADMEMIDX
- && CONST_INT_P (operands[2])
- && pow2p_hwi (INTVAL (operands[2]))
- && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)"
- "#"
- "&& 1"
- [(set (match_dup 0)
- (any_extend:X (mem:SUBX (plus:X
- (match_dup 3)
- (ashift:X (match_dup 1) (match_dup 2))))))]
- { operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
- }
-)
-
-(define_insn_and_split "*th_memidx_I_c"
- [(set (mem:TH_M_ANYI (plus:X
- (mult:X (match_operand:X 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i"))
- (match_operand:X 3 "register_operand" "r")))
- (match_operand:TH_M_ANYI 0 "register_operand" "r"))]
- "TARGET_XTHEADMEMIDX
- && CONST_INT_P (operands[2])
- && pow2p_hwi (INTVAL (operands[2]))
- && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)"
- "#"
- "&& 1"
- [(set (mem:TH_M_ANYI (plus:X
- (match_dup 3)
- (ashift:X (match_dup 1) (match_dup 2))))
- (match_dup 0))]
- { operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
- }
-)
-
-(define_insn_and_split "*th_memidx_US_a"
- [(set (match_operand:TH_M_NOEXTI 0 "register_operand" "=r")
- (mem:TH_M_NOEXTI (plus:DI
- (and:DI
- (mult:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i"))
- (match_operand:DI 3 "immediate_operand" "i"))
- (match_operand:DI 4 "register_operand" "r"))))]
- "TARGET_64BIT && TARGET_XTHEADMEMIDX
- && CONST_INT_P (operands[2])
- && pow2p_hwi (INTVAL (operands[2]))
- && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)
- && CONST_INT_P (operands[3])
- && (INTVAL (operands[3]) >> exact_log2 (INTVAL (operands[2]))) == 0xffffffff"
- "#"
- "&& 1"
- [(set (match_dup 0)
- (mem:TH_M_NOEXTI (plus:DI
- (match_dup 4)
- (ashift:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))))]
- { operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
- }
-)
-
-(define_insn_and_split "*th_memidx_US_b"
- [(set (match_operand:X 0 "register_operand" "=r")
- (any_extend:X (mem:SUBX (plus:DI
- (and:DI
- (mult:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i"))
- (match_operand:DI 3 "immediate_operand" "i"))
- (match_operand:DI 4 "register_operand" "r")))))]
- "TARGET_64BIT && TARGET_XTHEADMEMIDX
- && CONST_INT_P (operands[2])
- && pow2p_hwi (INTVAL (operands[2]))
- && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)
- && CONST_INT_P (operands[3])
- && (INTVAL (operands[3]) >> exact_log2 (INTVAL (operands[2]))) == 0xffffffff"
- "#"
- "&& 1"
- [(set (match_dup 0)
- (any_extend:X (mem:SUBX (plus:DI
- (match_dup 4)
- (ashift:DI (zero_extend:DI (match_dup 1)) (match_dup 2))))))]
- { operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
- }
-)
-
-(define_insn_and_split "*th_memidx_US_c"
- [(set (mem:TH_M_ANYI (plus:DI
- (and:DI
- (mult:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i"))
- (match_operand:DI 3 "immediate_operand" "i"))
- (match_operand:DI 4 "register_operand" "r")))
- (match_operand:TH_M_ANYI 0 "register_operand" "r"))]
- "TARGET_64BIT && TARGET_XTHEADMEMIDX
- && CONST_INT_P (operands[2])
- && pow2p_hwi (INTVAL (operands[2]))
- && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)
- && CONST_INT_P (operands[3])
- && (INTVAL (operands[3]) >> exact_log2 (INTVAL (operands[2]))) == 0xffffffff"
- "#"
- "&& 1"
- [(set (mem:TH_M_ANYI (plus:DI
- (match_dup 4)
- (ashift:DI (zero_extend:DI (match_dup 1)) (match_dup 2))))
- (match_dup 0))]
- { operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
- }
-)
-
-(define_insn_and_split "*th_memidx_UZ_a"
- [(set (match_operand:TH_M_NOEXTI 0 "register_operand" "=r")
- (mem:TH_M_NOEXTI (plus:DI
- (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
- (match_operand:DI 2 "register_operand" "r"))))]
- "TARGET_64BIT && TARGET_XTHEADMEMIDX"
- "#"
- "&& 1"
- [(set (match_dup 0)
- (mem:TH_M_NOEXTI (plus:DI
- (match_dup 2)
- (zero_extend:DI (match_dup 1)))))]
-)
-
-(define_insn_and_split "*th_memidx_UZ_b"
- [(set (match_operand:X 0 "register_operand" "=r")
- (any_extend:X (mem:SUBX (plus:DI
- (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
- (match_operand:DI 2 "register_operand" "r")))))]
- "TARGET_64BIT && TARGET_XTHEADMEMIDX"
- "#"
- "&& 1"
- [(set (match_dup 0)
- (any_extend:X (mem:SUBX (plus:DI
- (match_dup 2)
- (zero_extend:DI (match_dup 1))))))]
-)
-
-(define_insn_and_split "*th_memidx_UZ_c"
- [(set (mem:TH_M_ANYI (plus:DI
- (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
- (match_operand:DI 2 "register_operand" "r")))
- (match_operand:TH_M_ANYI 0 "register_operand" "r"))]
- "TARGET_64BIT && TARGET_XTHEADMEMIDX"
- "#"
- "&& 1"
- [(set (mem:TH_M_ANYI (plus:DI
- (match_dup 2)
- (zero_extend:DI (match_dup 1))))
- (match_dup 0))]
-)
-
-;; XTheadFMemIdx
-;; Note, that we might get GP registers in FP-mode (reg:DF a2)
-;; which cannot be handled by the XTheadFMemIdx instructions.
-;; This might even happen after register allocation.
-;; We could implement splitters that undo the combiner results
-;; if "after_reload && !HARDFP_REG_P (operands[0])", but this
-;; raises even more questions (e.g. split into what?).
-;; So let's solve this by simply requiring XTheadMemIdx
-;; which provides the necessary instructions to cover this case.
-
-(define_insn "*th_fmemidx_movsf_hardfloat"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f,th_m_mir,f,th_m_miu")
- (match_operand:SF 1 "move_operand" " th_m_mir,f,th_m_miu,f"))]
- "TARGET_HARD_FLOAT && TARGET_XTHEADFMEMIDX && TARGET_XTHEADMEMIDX
- && (register_operand (operands[0], SFmode)
- || reg_or_0_operand (operands[1], SFmode))"
- { return riscv_output_move (operands[0], operands[1]); }
- [(set_attr "move_type" "fpload,fpstore,fpload,fpstore")
- (set_attr "mode" "SF")])
-
-(define_insn "*th_fmemidx_movdf_hardfloat_rv64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f,th_m_mir,f,th_m_miu")
- (match_operand:DF 1 "move_operand" " th_m_mir,f,th_m_miu,f"))]
- "TARGET_64BIT && TARGET_DOUBLE_FLOAT && TARGET_XTHEADFMEMIDX
- && TARGET_XTHEADMEMIDX
- && (register_operand (operands[0], DFmode)
- || reg_or_0_operand (operands[1], DFmode))"
- { return riscv_output_move (operands[0], operands[1]); }
- [(set_attr "move_type" "fpload,fpstore,fpload,fpstore")
- (set_attr "mode" "DF")])
-
-;; XTheadFMemIdx optimizations
-;; Similar like XTheadMemIdx optimizations, but less cases.
-
-(define_insn_and_split "*th_fmemidx_I_a"
- [(set (match_operand:TH_M_NOEXTF 0 "register_operand" "=f")
- (mem:TH_M_NOEXTF (plus:X
- (mult:X (match_operand:X 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i"))
- (match_operand:X 3 "register_operand" "r"))))]
- "TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX
- && CONST_INT_P (operands[2])
- && pow2p_hwi (INTVAL (operands[2]))
- && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)"
- "#"
- "&& reload_completed"
- [(set (match_dup 0)
- (mem:TH_M_NOEXTF (plus:X
- (match_dup 3)
- (ashift:X (match_dup 1) (match_dup 2)))))]
- { operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
- }
- [(set_attr "move_type" "fpload")
- (set_attr "mode" "<UNITMODE>")
- (set_attr "type" "fmove")
- (set (attr "length") (const_int 16))])
-
-(define_insn_and_split "*th_fmemidx_I_c"
- [(set (mem:TH_M_ANYF (plus:X
- (mult:X (match_operand:X 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i"))
- (match_operand:X 3 "register_operand" "r")))
- (match_operand:TH_M_ANYF 0 "register_operand" "f"))]
- "TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX
- && CONST_INT_P (operands[2])
- && pow2p_hwi (INTVAL (operands[2]))
- && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)"
- "#"
- "&& 1"
- [(set (mem:TH_M_ANYF (plus:X
- (match_dup 3)
- (ashift:X (match_dup 1) (match_dup 2))))
- (match_dup 0))]
- { operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
- }
-)
-
-(define_insn_and_split "*th_fmemidx_US_a"
- [(set (match_operand:TH_M_NOEXTF 0 "register_operand" "=f")
- (mem:TH_M_NOEXTF (plus:DI
- (and:DI
- (mult:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i"))
- (match_operand:DI 3 "immediate_operand" "i"))
- (match_operand:DI 4 "register_operand" "r"))))]
- "TARGET_64BIT && TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX
- && CONST_INT_P (operands[2])
- && pow2p_hwi (INTVAL (operands[2]))
- && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)
- && CONST_INT_P (operands[3])
- && (INTVAL (operands[3]) >> exact_log2 (INTVAL (operands[2]))) == 0xffffffff"
- "#"
- "&& reload_completed"
- [(set (match_dup 0)
- (mem:TH_M_NOEXTF (plus:DI
- (match_dup 4)
- (ashift:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))))]
- { operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
- }
- [(set_attr "move_type" "fpload")
- (set_attr "mode" "<UNITMODE>")
- (set_attr "type" "fmove")
- (set (attr "length") (const_int 16))])
-
-(define_insn_and_split "*th_fmemidx_US_c"
- [(set (mem:TH_M_ANYF (plus:DI
- (and:DI
- (mult:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i"))
- (match_operand:DI 3 "immediate_operand" "i"))
- (match_operand:DI 4 "register_operand" "r")))
- (match_operand:TH_M_ANYF 0 "register_operand" "f"))]
- "TARGET_64BIT && TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX
- && CONST_INT_P (operands[2])
- && pow2p_hwi (INTVAL (operands[2]))
- && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)
- && CONST_INT_P (operands[3])
- && (INTVAL (operands[3]) >> exact_log2 (INTVAL (operands[2]))) == 0xffffffff"
- "#"
- "&& 1"
- [(set (mem:TH_M_ANYF (plus:DI
- (match_dup 4)
- (ashift:DI (zero_extend:DI (match_dup 1)) (match_dup 2))))
- (match_dup 0))]
- { operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
- }
-)
-
-(define_insn_and_split "*th_fmemidx_UZ_a"
- [(set (match_operand:TH_M_NOEXTF 0 "register_operand" "=f")
- (mem:TH_M_NOEXTF (plus:DI
- (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
- (match_operand:DI 2 "register_operand" "r"))))]
- "TARGET_64BIT && TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX
- && (!HARD_REGISTER_NUM_P (REGNO (operands[0])) || HARDFP_REG_P (REGNO (operands[0])))"
- "#"
- "&& reload_completed"
- [(set (match_dup 0)
- (mem:TH_M_NOEXTF (plus:DI
- (match_dup 2)
- (zero_extend:DI (match_dup 1)))))]
- ""
- [(set_attr "move_type" "fpload")
- (set_attr "mode" "<UNITMODE>")
- (set_attr "type" "fmove")
- (set (attr "length") (const_int 16))])
-
-(define_insn_and_split "*th_fmemidx_UZ_c"
- [(set (mem:TH_M_ANYF (plus:DI
- (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
- (match_operand:DI 2 "register_operand" "r")))
- (match_operand:TH_M_ANYF 0 "register_operand" "f"))]
- "TARGET_64BIT && TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX"
- "#"
- "&& 1"
- [(set (mem:TH_M_ANYF (plus:DI
- (match_dup 2)
- (zero_extend:DI (match_dup 1))))
- (match_dup 0))]
-)
-
(include "thead-peephole.md")
new file mode 100644
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-flto" "-O0" "-Og" "-Os" "-Oz" } } */
+/* { dg-options "-march=rv64gc_xtheadmemidx" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xtheadmemidx" { target { rv32 } } } */
+
+volatile long long a;
+int b;
+int c[1];
+
+void d()
+{
+ c[a] = b;
+}
+
+/* { dg-final { scan-assembler "th.srw\t" } } */