gcc/ChangeLog:
* config/loongarch/loongarch.md (*and<mode>3): Delete.
(*and<mode>3_extend): New.
(zero_extend<SHORT:mode><GPR:mode>2_la32r): New.
(extend<SHORT:mode><GPR:mode>2_la32r): New.
(extendqihi2_la32r): Add TARGET_32BIT_S condition.
* config/loongarch/sync.md (atomic_<amop><mode>): Change to
define_expand.
(la64_atomic_<amop><mode>): New.
(la32_atomic_<amop>si): New.
(atomic_fetch_<amop><mode>): Change to define_expand.
(la64_atomic_fetch_<amop><mode>): New.
(la32_atomic_fetch_<amop>si): New.
(atomic_exchange<mode>): Change to define_expand.
(la64_atomic_exchange<mode>): New.
(la32_atomic_exchangesi): New.
---
gcc/config/loongarch/loongarch.md | 191 +++++++++++++++++++-----------
gcc/config/loongarch/sync.md | 120 +++++++++++++++++--
2 files changed, 233 insertions(+), 78 deletions(-)
diff --git a/gcc/config/loongarch/loongarch.md
b/gcc/config/loongarch/loongarch.md
index e23c973c38b..1ea71a84403 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -633,7 +633,7 @@ (define_int_attr bytepick_imm [(8 "1")
;; so the redundant sign extension can be removed if the output is used as
;; an input of a bitwise operation. Note plus, rotl, and div are handled
;; separately.
-(define_code_iterator shift_w [any_shift rotatert])
+(define_code_iterator shift_w [any_shift (rotatert "!TARGET_32BIT_R")])
(define_code_iterator arith_w [minus mult])
(define_expand "<optab><mode>3"
@@ -1376,7 +1376,7 @@ (define_insn "ldexp<mode>3"
(unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")
(match_operand:<IMODE> 2 "register_operand" "f")]
UNSPEC_FSCALEB))]
- "TARGET_HARD_FLOAT"
+ "TARGET_64BIT"
"fscaleb.<fmt>\t%0,%1,%2"
[(set_attr "type" "fscaleb")
(set_attr "mode" "<UNITMODE>")])
@@ -1392,7 +1392,7 @@ (define_insn "logb_non_negative<mode>2"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")]
UNSPEC_FLOGB))]
- "TARGET_HARD_FLOAT"
+ "TARGET_64BIT"
"flogb.<fmt>\t%0,%1"
[(set_attr "type" "flogb")
(set_attr "mode" "<UNITMODE>")])
@@ -1401,7 +1401,7 @@ (define_expand "logb<mode>2"
[(set (match_operand:ANYF 0 "register_operand")
(unspec:ANYF [(abs:ANYF (match_operand:ANYF 1 "register_operand"))]
UNSPEC_FLOGB))]
- "TARGET_HARD_FLOAT"
+ "TARGET_64BIT"
{
rtx tmp = gen_reg_rtx (<MODE>mode);
@@ -1421,7 +1421,7 @@ (define_expand "logb<mode>2"
(define_insn "clz<mode>2"
[(set (match_operand:GPR 0 "register_operand" "=r")
(clz:GPR (match_operand:GPR 1 "register_operand" "r")))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"clz.<d>\t%0,%1"
[(set_attr "type" "clz")
(set_attr "mode" "<MODE>")])
@@ -1437,7 +1437,7 @@ (define_insn "clz<mode>2"
(define_insn "ctz<mode>2"
[(set (match_operand:GPR 0 "register_operand" "=r")
(ctz:GPR (match_operand:GPR 1 "register_operand" "r")))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"ctz.<d>\t%0,%1"
[(set_attr "type" "clz")
(set_attr "mode" "<MODE>")])
@@ -1553,28 +1553,26 @@ (define_insn "neg<mode>2"
(define_insn "*<optab><mode>3"
[(set (match_operand:GPR 0 "register_operand" "=r,r")
- (any_or:GPR (match_operand:GPR 1 "register_operand" "%r,r")
- (match_operand:GPR 2 "uns_arith_operand" "r,K")))]
+ (any_bitwise:GPR (match_operand:GPR 1 "register_operand" "%r,r")
+ (match_operand:GPR 2 "uns_arith_operand" "r,K")))]
""
"<insn>%i2\t%0,%1,%2"
[(set_attr "type" "logical")
(set_attr "mode" "<MODE>")])
-(define_insn "*and<mode>3"
- [(set (match_operand:GPR 0 "register_operand" "=r,r,r,r")
- (and:GPR (match_operand:GPR 1 "register_operand" "%r,r,r,0")
- (match_operand:GPR 2 "and_operand" "r,K,Yx,Yy")))]
- ""
+(define_insn "*and<mode>3_extend"
+ [(set (match_operand:GPR 0 "register_operand" "=r,r")
+ (and:GPR (match_operand:GPR 1 "register_operand" "%r,0")
+ (match_operand:GPR 2 "and_operand" "Yx,Yy")))]
+ "TARGET_64BIT || TARGET_32BIT_S"
"@
- and\t%0,%1,%2
- andi\t%0,%1,%2
* operands[2] = GEN_INT (INTVAL (operands[2]) \
& GET_MODE_MASK (<MODE>mode)); \
return \"bstrpick.<d>\t%0,%1,%M2\";
* operands[2] = GEN_INT (~INTVAL (operands[2]) \
& GET_MODE_MASK (<MODE>mode)); \
return \"bstrins.<d>\t%0,%.,%M2\";"
- [(set_attr "move_type" "logical,logical,pick_ins,pick_ins")
+ [(set_attr "move_type" "pick_ins,pick_ins")
(set_attr "mode" "<MODE>")])
(define_expand "<optab><mode>3"
@@ -1606,7 +1604,8 @@ (define_insn_and_split "*bstrins_<mode>_for_ior_mask"
(match_operand:GPR 2 "const_int_operand" "i"))
(and:GPR (match_operand:GPR 3 "register_operand" "r")
(match_operand:GPR 4 "const_int_operand" "i"))))]
- "loongarch_pre_reload_split ()
+ "(TARGET_64BIT || TARGET_32BIT_S )
+ && loongarch_pre_reload_split ()
&& loongarch_use_bstrins_for_ior_with_mask (<MODE>mode, operands)"
"#"
"&& true"
@@ -1675,7 +1674,7 @@ (define_peephole2
(match_operand:SI 3 "const_int_operand")
(const_int 0))
(match_dup 0))]
- "peep2_reg_dead_p (3, operands[0])"
+ "(TARGET_64BIT || TARGET_32BIT_S) && peep2_reg_dead_p (3, operands[0])"
[(const_int 0)]
{
int len = GET_MODE_BITSIZE (<MODE>mode) - INTVAL (operands[3]);
@@ -1736,7 +1735,7 @@ (define_insn "<optab>n<mode>3"
(neg_bitwise:X
(not:X (match_operand:X 2 "register_operand" "r"))
(match_operand:X 1 "register_operand" "r")))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"<insn>n\t%0,%1,%2"
[(set_attr "type" "logical")
(set_attr "mode" "<MODE>")])
@@ -1835,7 +1834,7 @@ (define_insn "zero_extend<SHORT:mode><GPR:mode>2"
[(set (match_operand:GPR 0 "register_operand" "=r,r,r")
(zero_extend:GPR
(match_operand:SHORT 1 "nonimmediate_operand" "r,m,k")))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"@
bstrpick.w\t%0,%1,<SHORT:7_or_15>,0
ld.<SHORT:size>u\t%0,%1
@@ -1843,6 +1842,15 @@ (define_insn "zero_extend<SHORT:mode><GPR:mode>2"
[(set_attr "move_type" "pick_ins,load,load")
(set_attr "mode" "<GPR:MODE>")])
+(define_insn "zero_extend<SHORT:mode><GPR:mode>2_la32r"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (zero_extend:GPR
+ (match_operand:SHORT 1 "nonimmediate_operand" "m")))]
+ "TARGET_32BIT_R"
+ "ld.<SHORT:size>u\t%0,%1"
+ [(set_attr "move_type" "load")
+ (set_attr "mode" "<GPR:MODE>")])
+
(define_insn "zero_extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=r,r,r")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,k,m")))]
@@ -1860,7 +1868,7 @@ (define_insn "*zero_extend<GPR:mode>_trunc<SHORT:mode>"
[(set (match_operand:GPR 0 "register_operand" "=r")
(zero_extend:GPR
(truncate:SHORT (match_operand:DI 1 "register_operand" "r"))))]
- "TARGET_64BIT"
+ "TARGET_64BIT || TARGET_32BIT_S"
"bstrpick.w\t%0,%1,<SHORT:7_or_15>,0"
[(set_attr "move_type" "pick_ins")
(set_attr "mode" "<GPR:MODE>")])
@@ -1899,7 +1907,7 @@ (define_insn "extend<SHORT:mode><GPR:mode>2"
[(set (match_operand:GPR 0 "register_operand" "=r,r,r")
(sign_extend:GPR
(match_operand:SHORT 1 "nonimmediate_operand" "r,m,k")))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"@
ext.w.<SHORT:size>\t%0,%1
ld.<SHORT:size>\t%0,%1
@@ -1907,11 +1915,20 @@ (define_insn "extend<SHORT:mode><GPR:mode>2"
[(set_attr "move_type" "signext,load,load")
(set_attr "mode" "<GPR:MODE>")])
+(define_insn "extend<SHORT:mode><GPR:mode>2_la32r"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (sign_extend:GPR
+ (match_operand:SHORT 1 "nonimmediate_operand" "m")))]
+ "TARGET_32BIT_R"
+ "ld.<SHORT:size>\t%0,%1"
+ [(set_attr "move_type" "load")
+ (set_attr "mode" "<GPR:MODE>")])
+
(define_insn "extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=r,r,r")
(sign_extend:HI
(match_operand:QI 1 "nonimmediate_operand" "r,m,k")))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"@
ext.w.b\t%0,%1
ld.b\t%0,%1
@@ -1919,6 +1936,15 @@ (define_insn "extendqihi2"
[(set_attr "move_type" "signext,load,load")
(set_attr "mode" "SI")])
+(define_insn "extendqihi2_la32r"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI
+ (match_operand:QI 1 "nonimmediate_operand" "m")))]
+ ""
+ "ld.b\t%0,%1"
+ [(set_attr "move_type" "load")
+ (set_attr "mode" "SI")])
+
(define_insn "extendsfdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
(float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
@@ -2031,7 +2057,7 @@ (define_expand "fixuns_truncdfsi2"
(define_expand "fixuns_truncdfdi2"
[(set (match_operand:DI 0 "register_operand")
(unsigned_fix:DI (match_operand:DF 1 "register_operand")))]
- "TARGET_DOUBLE_FLOAT"
+ "TARGET_64BIT && TARGET_DOUBLE_FLOAT"
{
rtx reg1 = gen_reg_rtx (DFmode);
rtx reg2 = gen_reg_rtx (DFmode);
@@ -2113,7 +2139,7 @@ (define_expand "fixuns_truncsfsi2"
(define_expand "fixuns_truncsfdi2"
[(set (match_operand:DI 0 "register_operand")
(unsigned_fix:DI (match_operand:SF 1 "register_operand")))]
- "TARGET_DOUBLE_FLOAT"
+ "TARGET_64BIT && TARGET_DOUBLE_FLOAT"
{
rtx reg1 = gen_reg_rtx (SFmode);
rtx reg2 = gen_reg_rtx (SFmode);
@@ -2163,7 +2189,7 @@ (define_expand "extzv<mode>"
(zero_extract:X (match_operand:X 1 "register_operand")
(match_operand 2 "const_int_operand")
(match_operand 3 "const_int_operand")))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
{
if (!loongarch_use_ins_ext_p (operands[1], INTVAL (operands[2]),
INTVAL (operands[3])))
@@ -2173,10 +2199,11 @@ (define_expand "extzv<mode>"
(define_insn "*extzv<mode>"
[(set (match_operand:X 0 "register_operand" "=r")
(zero_extract:X (match_operand:X 1 "register_operand" "r")
- (match_operand 2 "const_int_operand" "")
- (match_operand 3 "const_int_operand" "")))]
- "loongarch_use_ins_ext_p (operands[1], INTVAL (operands[2]),
- INTVAL (operands[3]))"
+ (match_operand 2 "const_int_operand" "")
+ (match_operand 3 "const_int_operand" "")))]
+ "(TARGET_64BIT || TARGET_32BIT_S)
+ && loongarch_use_ins_ext_p (operands[1], INTVAL (operands[2]),
+ INTVAL (operands[3]))"
{
operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]) - 1);
return "bstrpick.<d>\t%0,%1,%2,%3";
@@ -2189,7 +2216,7 @@ (define_expand "insv<mode>"
(match_operand 1 "const_int_operand")
(match_operand 2 "const_int_operand"))
(match_operand:GPR 3 "reg_or_0_operand"))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
{
if (!loongarch_use_ins_ext_p (operands[0], INTVAL (operands[1]),
INTVAL (operands[2])))
@@ -2201,8 +2228,9 @@ (define_insn "*insv<mode>"
(match_operand:SI 1 "const_int_operand" "")
(match_operand:SI 2 "const_int_operand" ""))
(match_operand:GPR 3 "reg_or_0_operand" "rJ"))]
- "loongarch_use_ins_ext_p (operands[0], INTVAL (operands[1]),
- INTVAL (operands[2]))"
+ "(TARGET_64BIT || TARGET_32BIT_S)
+ && loongarch_use_ins_ext_p (operands[0], INTVAL (operands[1]),
+ INTVAL (operands[2]))"
{
operands[1] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[2]) - 1);
return "bstrins.<d>\t%0,%z3,%1,%2";
@@ -2319,7 +2347,7 @@ (define_insn "la_pcrel64_two_parts"
(unspec:DI [(match_operand:DI 2 "") (pc)] UNSPEC_LA_PCREL_64_PART1))
(set (match_operand:DI 1 "register_operand" "=r")
(unspec:DI [(match_dup 2) (pc)] UNSPEC_LA_PCREL_64_PART2))]
- "TARGET_ABI_LP64 && la_opt_explicit_relocs != EXPLICIT_RELOCS_NONE"
+ "TARGET_64BIT && la_opt_explicit_relocs != EXPLICIT_RELOCS_NONE"
{
return "pcalau12i\t%0,%r2\n\t"
"addi.d\t%1,$r0,%L2\n\t"
@@ -2337,6 +2365,15 @@ (define_expand "movsi"
(match_operand:SI 1 ""))]
""
{
+ if (TARGET_32BIT
+ && ((MEM_P (operands[0])
+ && loongarch_14bit_shifted_offset_address_p (XEXP (operands[0], 0),
SImode)
+ && !loongarch_12bit_offset_address_p (XEXP (operands[0], 0), SImode))
+ || (MEM_P (operands[1])
+ && loongarch_14bit_shifted_offset_address_p (XEXP (operands[1],
0), SImode)
+ && !loongarch_12bit_offset_address_p (XEXP (operands[1], 0),
SImode))))
+ FAIL;
+
if (loongarch_legitimize_move (SImode, operands[0], operands[1]))
DONE;
})
@@ -2345,10 +2382,17 @@ (define_insn_and_split "*movsi_internal"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,w,f,f,r,*m")
(match_operand:SI 1 "move_operand" "r,Yd,w,rJ,rJ,m,f,*f"))]
"(register_operand (operands[0], SImode)
- || reg_or_0_operand (operands[1], SImode))"
+ || reg_or_0_operand (operands[1], SImode))
+ && !(TARGET_32BIT
+ && ((MEM_P (operands[0])
+ && loongarch_14bit_shifted_offset_address_p (XEXP (operands[0],
0), SImode)
+ && !loongarch_12bit_offset_address_p (XEXP (operands[0], 0),
SImode))
+ || (MEM_P (operands[1])
+ && loongarch_14bit_shifted_offset_address_p (XEXP (operands[1],
0), SImode)
+ && !loongarch_12bit_offset_address_p (XEXP (operands[1], 0),
SImode))))"
{ return loongarch_output_move (operands); }
- "CONST_INT_P (operands[1]) && REG_P (operands[0]) && GP_REG_P (REGNO
- (operands[0]))"
+ "&& CONST_INT_P (operands[1]) && REG_P (operands[0])
+ && GP_REG_P (REGNO (operands[0]))"
[(const_int 0)]
"
{
@@ -2423,7 +2467,7 @@ (define_insn "*movqi_internal"
(define_expand "movsf"
[(set (match_operand:SF 0 "")
(match_operand:SF 1 ""))]
- ""
+ "TARGET_HARD_FLOAT"
{
if (loongarch_legitimize_move (SFmode, operands[0], operands[1]))
DONE;
@@ -2454,7 +2498,7 @@ (define_insn "*movsf_softfloat"
(define_expand "movdf"
[(set (match_operand:DF 0 "")
(match_operand:DF 1 ""))]
- ""
+ "TARGET_DOUBLE_FLOAT"
{
if (loongarch_legitimize_move (DFmode, operands[0], operands[1]))
DONE;
@@ -2559,8 +2603,9 @@ (define_insn "*sel<code><GPR:mode>_using_<X:mode>"
(const_int 0))
(match_operand:GPR 2 "reg_or_0_operand" "r,J")
(match_operand:GPR 3 "reg_or_0_operand" "J,r")))]
- "register_operand (operands[2], <GPR:MODE>mode)
- != register_operand (operands[3], <GPR:MODE>mode)"
+ "(TARGET_64BIT || TARGET_32BIT_S)
+ && register_operand (operands[2], <GPR:MODE>mode)
+ != register_operand (operands[3], <GPR:MODE>mode)"
"@
<sel>\t%0,%2,%1
<selinv>\t%0,%3,%1"
@@ -2622,7 +2667,7 @@ (define_expand "mov<mode>cc"
(if_then_else:GPR (match_operator 1 "comparison_operator"
[(match_operand:GPR 2 "reg_or_0_operand")
(match_operand:GPR 3 "reg_or_0_operand")])))]
- "TARGET_COND_MOVE_INT"
+ "(TARGET_64BIT || TARGET_32BIT_S) && TARGET_COND_MOVE_INT"
{
if (!INTEGRAL_MODE_P (GET_MODE (XEXP (operands[1], 0))))
FAIL;
@@ -2727,7 +2772,7 @@ (define_insn "@pcalau12i<mode>"
[(set (match_operand:P 0 "register_operand" "=j")
(unspec:P [(match_operand:P 1 "symbolic_operand" "")]
UNSPEC_PCALAU12I))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"pcalau12i\t%0,%%pc_hi20(%1)"
[(set_attr "type" "move")])
@@ -2737,7 +2782,7 @@ (define_insn "@pcalau12i_gr<mode>"
[(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_operand:P 1 "symbolic_operand" "")]
UNSPEC_PCALAU12I_GR))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"pcalau12i\t%0,%%pc_hi20(%1)"
[(set_attr "type" "move")])
@@ -2787,7 +2832,7 @@ (define_insn "rint<mode>2"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")]
UNSPEC_FRINT))]
- ""
+ "TARGET_64BIT"
"frint.<fmt>\t%0,%1"
[(set_attr "type" "fcvt")
(set_attr "mode" "<MODE>")])
@@ -3043,7 +3088,7 @@ (define_insn "loongarch_lddir_<d>"
(match_operand 2 "const_uimm5_operand")]
UNSPECV_LDDIR)
(clobber (mem:BLK (scratch)))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"lddir\t%0,%1,%2"
[(set_attr "type" "load")
(set_attr "mode" "<MODE>")])
@@ -3053,7 +3098,7 @@ (define_insn "loongarch_ldpte_<d>"
(match_operand 1 "const_uimm5_operand")]
UNSPECV_LDPTE)
(clobber (mem:BLK (scratch)))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"ldpte\t%0,%1"
[(set_attr "type" "load")
(set_attr "mode" "<MODE>")])
@@ -3131,7 +3176,7 @@ (define_insn "*rotr<mode>3"
[(set (match_operand:GPR 0 "register_operand" "=r,r")
(rotatert:GPR (match_operand:GPR 1 "register_operand" "r,r")
(match_operand:SI 2 "arith_operand" "r,I")))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"rotr%i2.<d>\t%0,%1,%2"
[(set_attr "type" "shift,shift")
(set_attr "mode" "<MODE>")])
@@ -3141,7 +3186,7 @@ (define_insn "rotrsi3_extend"
(sign_extend:DI
(rotatert:SI (match_operand:SI 1 "register_operand" "r,r")
(match_operand:SI 2 "arith_operand" "r,I"))))]
- "TARGET_64BIT"
+ "TARGET_64BIT || TARGET_32BIT_S"
"rotr%i2.w\t%0,%1,%2"
[(set_attr "type" "shift,shift")
(set_attr "mode" "SI")])
@@ -3153,7 +3198,7 @@ (define_expand "rotl<mode>3"
(set (match_operand:GPR 0 "register_operand")
(rotatert:GPR (match_operand:GPR 1 "register_operand")
(match_dup 3)))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
{
operands[3] = gen_reg_rtx (SImode);
@@ -3176,7 +3221,7 @@ (define_insn "alsl<mode>3"
(plus:GPR (ashift:GPR (match_operand:GPR 1 "register_operand" "r")
(match_operand 2 "const_immalsl_operand" ""))
(match_operand:GPR 3 "register_operand" "r")))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"alsl.<d>\t%0,%1,%3,%2"
[(set_attr "type" "arith")
(set_attr "mode" "<MODE>")])
@@ -3219,8 +3264,9 @@ (define_insn_and_split "<optab>_shift_reverse<X:mode>"
(ashift:X (match_operand:X 1 "register_operand" "r")
(match_operand:SI 2 "const_int_operand" "i"))
(match_operand:X 3 "const_int_operand" "i")))]
- "(const_immalsl_operand (operands[2], SImode)
- || !<bitwise_operand> (operands[3], <MODE>mode))
+ "TARGET_64BIT
+ && (const_immalsl_operand (operands[2], SImode)
+ || !<bitwise_operand> (operands[3], <MODE>mode))
&& loongarch_reassoc_shift_bitwise (<is_and>, operands[2], operands[3],
<MODE>mode)"
"#"
@@ -3301,7 +3347,7 @@ (define_insn "revb_2h"
[(set (match_operand:SI 0 "register_operand" "=r")
(rotatert:SI (bswap:SI (match_operand:SI 1 "register_operand" "r"))
(const_int 16)))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"revb.2h\t%0,%1"
[(set_attr "type" "shift")])
@@ -3311,14 +3357,14 @@ (define_insn "revb_2h_extend"
(rotatert:SI
(bswap:SI (match_operand:SI 1 "register_operand" "r"))
(const_int 16))))]
- "TARGET_64BIT"
+ "TARGET_64BIT || TARGET_32BIT_S"
"revb.2h\t%0,%1"
[(set_attr "type" "shift")])
(define_insn "bswaphi2"
[(set (match_operand:HI 0 "register_operand" "=r")
(bswap:HI (match_operand:HI 1 "register_operand" "r")))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"revb.2h\t%0,%1"
[(set_attr "type" "shift")])
@@ -3340,9 +3386,9 @@ (define_insn "*bswapsi2"
(define_expand "bswapsi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(bswap:SI (match_operand:SI 1 "register_operand" "r")))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
{
- if (!TARGET_64BIT)
+ if (TARGET_32BIT_S)
{
rtx t = gen_reg_rtx (SImode);
emit_insn (gen_revb_2h (t, operands[1]));
@@ -3506,7 +3552,7 @@ (define_expand "cstore<mode>4"
(match_operator:SI 1 "loongarch_cstore_operator"
[(match_operand:GPR 2 "register_operand")
(match_operand:GPR 3 "nonmemory_operand")]))]
- ""
+ "TARGET_64BIT"
{
loongarch_expand_scc (operands);
DONE;
@@ -4334,7 +4380,7 @@ (define_insn "*bytepick_w_<bytepick_imm>"
(const_int <bytepick_w_lshiftrt_amount>))
(ashift:SI (match_operand:SI 2 "register_operand" "r")
(const_int bytepick_w_ashift_amount))))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"bytepick.w\t%0,%1,%2,<bytepick_imm>"
[(set_attr "mode" "SI")])
@@ -4352,7 +4398,7 @@ (define_insn "bytepick_w_<bytepick_imm>_extend"
(zero_extract:DI (match_operand:DI 2 "register_operand" "r")
(const_int <bytepick_w_ashift_amount>)
(const_int <bitsize>))))]
- "TARGET_64BIT"
+ "TARGET_64BIT || TARGET_32BIT_S"
"bytepick.w\t%0,%2,%1,<bytepick_imm>"
[(set_attr "mode" "SI")])
@@ -4367,7 +4413,7 @@ (define_insn "bytepick_w_1_extend"
(zero_extract:DI (match_operand:DI 2 "register_operand" "r")
(const_int 8)
(const_int 24))))]
- "TARGET_64BIT"
+ "TARGET_64BIT || TARGET_32BIT_S"
"bytepick.w\t%0,%2,%1,1"
[(set_attr "mode" "SI")])
@@ -4397,7 +4443,7 @@ (define_insn "bitrev_4b"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec:SI [(match_operand:SI 1 "register_operand" "r")]
UNSPEC_BITREV_4B))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"bitrev.4b\t%0,%1"
[(set_attr "type" "unknown")
(set_attr "mode" "SI")])
@@ -4406,7 +4452,7 @@ (define_insn "bitrev_8b"
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(match_operand:DI 1 "register_operand" "r")]
UNSPEC_BITREV_8B))]
- ""
+ "TARGET_64BIT"
"bitrev.8b\t%0,%1"
[(set_attr "type" "unknown")
(set_attr "mode" "DI")])
@@ -4414,7 +4460,7 @@ (define_insn "bitrev_8b"
(define_insn "@rbit<mode>"
[(set (match_operand:GPR 0 "register_operand" "=r")
(bitreverse:GPR (match_operand:GPR 1 "register_operand" "r")))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"bitrev.<size>\t%0,%1"
[(set_attr "type" "unknown")
(set_attr "mode" "<MODE>")])
@@ -4433,7 +4479,7 @@ (define_insn "rbitsi_extended"
(define_insn "rbitqi"
[(set (match_operand:QI 0 "register_operand" "=r")
(bitreverse:QI (match_operand:QI 1 "register_operand" "r")))]
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
"bitrev.4b\t%0,%1"
[(set_attr "type" "unknown")
(set_attr "mode" "SI")])
@@ -4576,7 +4622,7 @@ (define_insn "loongarch_<crc>_w_<size>_w"
(unspec:SI [(match_operand:QHWD 1 "register_operand" "r")
(match_operand:SI 2 "register_operand" "r")]
CRC))]
- ""
+ "TARGET_64BIT"
"<crc>.w.<size>.w\t%0,%1,%2"
[(set_attr "type" "unknown")
(set_attr "mode" "<MODE>")])
@@ -4597,7 +4643,7 @@ (define_expand "crc_rev<mode>si4"
(match_operand:SI 1 "register_operand") ; old_chksum
(match_operand:SUBDI 2 "reg_or_0_operand") ; msg
(match_operand 3 "const_int_operand")] ; poly
- ""
+ "TARGET_64BIT"
{
unsigned HOST_WIDE_INT poly = UINTVAL (operands[3]);
rtx msg = operands[2];
@@ -4694,7 +4740,8 @@ (define_insn_and_split "*crc_combine"
(define_insn_and_rewrite "simple_load<mode>"
[(set (match_operand:LD_AT_LEAST_32_BIT 0 "register_operand" "=r,f")
(match_operand:LD_AT_LEAST_32_BIT 1 "mem_simple_ldst_operand" ""))]
- "loongarch_pre_reload_split ()
+ "(TARGET_64BIT || TARGET_32BIT_S)
+ && loongarch_pre_reload_split ()
&& la_opt_explicit_relocs == EXPLICIT_RELOCS_AUTO
&& (TARGET_CMODEL_NORMAL || TARGET_CMODEL_MEDIUM)"
"#"
@@ -4707,7 +4754,8 @@ (define_insn_and_rewrite
"simple_load_<su>ext<SUBDI:mode><GPR:mode>"
[(set (match_operand:GPR 0 "register_operand" "=r")
(any_extend:GPR
(match_operand:SUBDI 1 "mem_simple_ldst_operand" "")))]
- "loongarch_pre_reload_split ()
+ "(TARGET_64BIT || TARGET_32BIT_S)
+ && loongarch_pre_reload_split ()
&& la_opt_explicit_relocs == EXPLICIT_RELOCS_AUTO
&& (TARGET_CMODEL_NORMAL || TARGET_CMODEL_MEDIUM)"
"#"
@@ -4719,7 +4767,8 @@ (define_insn_and_rewrite
"simple_load_<su>ext<SUBDI:mode><GPR:mode>"
(define_insn_and_rewrite "simple_store<mode>"
[(set (match_operand:ST_ANY 0 "mem_simple_ldst_operand" "")
(match_operand:ST_ANY 1 "reg_or_0_operand" "r,f"))]
- "loongarch_pre_reload_split ()
+ "(TARGET_64BIT || TARGET_32BIT_S)
+ && loongarch_pre_reload_split ()
&& la_opt_explicit_relocs == EXPLICIT_RELOCS_AUTO
&& (TARGET_CMODEL_NORMAL || TARGET_CMODEL_MEDIUM)"
"#"
diff --git a/gcc/config/loongarch/sync.md b/gcc/config/loongarch/sync.md
index 5784dab92a6..91d76af01cc 100644
--- a/gcc/config/loongarch/sync.md
+++ b/gcc/config/loongarch/sync.md
@@ -45,6 +45,10 @@ (define_code_iterator any_atomic [plus ior xor and])
;; particular code.
(define_code_attr amop [(ior "or") (xor "xor") (and "and") (plus "add")])
+;; For 32 bit.
+(define_code_attr atomic_optab_insn
+ [(plus "add.w") (ior "or") (xor "xor") (and "and")])
+
;; Memory barriers.
(define_expand "mem_thread_fence"
@@ -260,17 +264,48 @@ (define_expand "atomic_storeti"
DONE;
})
-(define_insn "atomic_<amop><mode>"
+(define_expand "atomic_<amop><mode>"
+ [(any_atomic:GPR (match_operand:GPR 0 "memory_operand") ;; mem location
+ (match_operand:GPR 1 "reg_or_0_operand")) ;; value for op
+ (match_operand:SI 2 "const_int_operand")] ;; model
+ ""
+{
+ if (TARGET_64BIT)
+ emit_insn (gen_la64_atomic_<amop><mode> (operands[0], operands[1],
operands[2]));
+ else
+ emit_insn (gen_la32_atomic_<amop>si (operands[0], operands[1],
operands[2]));
+ DONE;
+})
+
+(define_insn "la64_atomic_<amop><mode>"
[(set (match_operand:GPR 0 "memory_operand" "+ZB")
(unspec_volatile:GPR
[(any_atomic:GPR (match_dup 0)
(match_operand:GPR 1 "reg_or_0_operand" "rJ"))
(match_operand:SI 2 "const_int_operand")] ;; model
UNSPEC_SYNC_OLD_OP))]
- ""
+ "TARGET_64BIT"
"am<amop>%A2.<size>\t$zero,%z1,%0"
[(set (attr "length") (const_int 4))])
+(define_insn "la32_atomic_<amop>si"
+ [(set (match_operand:SI 0 "memory_operand" "+ZB")
+ (unspec_volatile:SI
+ [(any_atomic:SI (match_dup 0)
+ (match_operand:SI 1 "reg_or_0_operand" "rJ"))
+ (match_operand:SI 2 "const_int_operand")] ;; model
+ UNSPEC_SYNC_OLD_OP))
+ (clobber (match_scratch:SI 3 "=&r"))]
+ "!TARGET_64BIT"
+{
+ return "1:\n\t"
+ "ll.w\t%3,%0\n\t"
+ "<atomic_optab_insn>\t%3,%z1,%3\n\t"
+ "sc.w\t%3,%0\n\t"
+ "beq\t$zero,%3,1b\n\t";
+}
+ [(set (attr "length") (const_int 16))])
+
(define_insn "atomic_add<mode>"
[(set (match_operand:SHORT 0 "memory_operand" "+ZB")
(unspec_volatile:SHORT
@@ -282,7 +317,23 @@ (define_insn "atomic_add<mode>"
"amadd%A2.<size>\t$zero,%z1,%0"
[(set (attr "length") (const_int 4))])
-(define_insn "atomic_fetch_<amop><mode>"
+(define_expand "atomic_fetch_<amop><mode>"
+ [(match_operand:GPR 0 "register_operand") ;; old value at mem
+ (any_atomic:GPR (match_operand:GPR 1 "memory_operand") ;; mem location
+ (match_operand:GPR 2 "reg_or_0_operand")) ;; value for op
+ (match_operand:SI 3 "const_int_operand")] ;; model
+ ""
+ {
+ if (TARGET_64BIT)
+ emit_insn (gen_la64_atomic_fetch_<amop><mode> (operands[0], operands[1],
+ operands[2], operands[3]));
+ else
+ emit_insn (gen_la32_atomic_fetch_<amop>si (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+ })
+
+(define_insn "la64_atomic_fetch_<amop><mode>"
[(set (match_operand:GPR 0 "register_operand" "=&r")
(match_operand:GPR 1 "memory_operand" "+ZB"))
(set (match_dup 1)
@@ -291,10 +342,30 @@ (define_insn "atomic_fetch_<amop><mode>"
(match_operand:GPR 2 "reg_or_0_operand" "rJ"))
(match_operand:SI 3 "const_int_operand")] ;; model
UNSPEC_SYNC_OLD_OP))]
- ""
+ "TARGET_64BIT"
"am<amop>%A3.<size>\t%0,%z2,%1"
[(set (attr "length") (const_int 4))])
+(define_insn "la32_atomic_fetch_<amop>si"
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (match_operand:SI 1 "memory_operand" "+ZB"))
+ (set (match_dup 1)
+ (unspec_volatile:SI
+ [(any_atomic:SI (match_dup 1)
+ (match_operand:SI 2 "reg_or_0_operand" "rJ"))
+ (match_operand:SI 3 "const_int_operand")] ;; model
+ UNSPEC_SYNC_OLD_OP))
+ (clobber (match_scratch:SI 4 "=&r"))]
+ "!TARGET_64BIT"
+{
+ return "1:\n\t"
+ "ll.w\t%0,%1\n\t"
+ "<atomic_optab_insn>\t%4,%z2,%0\n\t"
+ "sc.w\t%4,%1\n\t"
+ "beq\t$zero,%4,1b\n\t";
+}
+ [(set (attr "length") (const_int 16))])
+
(define_insn "atomic_fetch_nand_mask_inverted<mode>"
[(set (match_operand:GPR 0 "register_operand" "=&r")
(match_operand:GPR 1 "memory_operand" "+ZC"))
@@ -338,7 +409,23 @@ (define_expand "atomic_fetch_nand<mode>"
DONE;
})
-(define_insn "atomic_exchange<mode>"
+(define_expand "atomic_exchange<mode>"
+ [(match_operand:GPR 0 "register_operand") ;; old value at mem
+ (match_operand:GPR 1 "memory_operand") ;; mem location
+ (match_operand:GPR 2 "register_operand") ;; value for op
+ (match_operand:SI 3 "const_int_operand")] ;; model
+ ""
+ {
+ if (TARGET_64BIT)
+ emit_insn (gen_la64_atomic_exchange<mode> (operands[0], operands[1],
+ operands[2], operands[3]));
+ else
+ emit_insn (gen_la32_atomic_exchangesi (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+ })
+
+(define_insn "la64_atomic_exchange<mode>"
[(set (match_operand:GPR 0 "register_operand" "=&r")
(unspec_volatile:GPR
[(match_operand:GPR 1 "memory_operand" "+ZB")
@@ -346,10 +433,29 @@ (define_insn "atomic_exchange<mode>"
UNSPEC_SYNC_EXCHANGE))
(set (match_dup 1)
(match_operand:GPR 2 "register_operand" "r"))]
- ""
+ "TARGET_64BIT"
"amswap%A3.<size>\t%0,%z2,%1"
[(set (attr "length") (const_int 4))])
+(define_insn "la32_atomic_exchangesi"
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (unspec_volatile:SI
+ [(match_operand:SI 1 "memory_operand" "+ZB")
+ (match_operand:SI 3 "const_int_operand")] ;; model
+ UNSPEC_SYNC_EXCHANGE))
+ (set (match_dup 1)
+ (match_operand:SI 2 "register_operand" "r"))
+ (clobber (match_scratch:SI 4 "=&r"))]
+ "!TARGET_64BIT"
+{
+ return "1:\n\t"
+ "ll.w\t%0,%1\n\t"
+ "or\t%4,$zero,%2\n\t"
+ "sc.w\t%4,%1\n\t"
+ "beq\t$zero,%4,1b\n\t";
+}
+ [(set (attr "length") (const_int 16))])
+
(define_insn "atomic_exchangeti_scq"
[(set (match_operand:TI 0 "register_operand" "=&r")
(unspec_volatile:TI
@@ -515,7 +621,7 @@ (define_expand "atomic_fetch_<amop><mode>"
(any_bitwise (match_operand:SHORT 1 "memory_operand" "+ZB") ;; memory
(match_operand:SHORT 2 "reg_or_0_operand" "rJ")) ;; val
(match_operand:SI 3 "const_int_operand" "")] ;;
model
- ""
+ "TARGET_64BIT || TARGET_32BIT_S"
{
/* We have no QI/HImode bitwise atomics, so use the address LSBs to form
a mask, then use an aligned SImode atomic. */
--
2.34.1