@@ -2059,7 +2059,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
2059
2059
2060
2060
assert(src_lo != OptoReg::Bad && dst_lo != OptoReg::Bad, "must move at least 1 register");
2061
2061
2062
- if (src_hi != OptoReg::Bad) {
2062
+ if (src_hi != OptoReg::Bad && !bottom_type()->isa_vectmask() ) {
2063
2063
assert((src_lo&1)==0 && src_lo+1==src_hi &&
2064
2064
(dst_lo&1)==0 && dst_lo+1==dst_hi,
2065
2065
"expected aligned-adjacent pairs");
@@ -2074,7 +2074,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
2074
2074
int src_offset = ra_->reg2offset(src_lo);
2075
2075
int dst_offset = ra_->reg2offset(dst_lo);
2076
2076
2077
- if (bottom_type()->isa_vect() != NULL ) {
2077
+ if (bottom_type()->isa_vect() && !bottom_type()->isa_vectmask() ) {
2078
2078
uint ireg = ideal_reg();
2079
2079
if (ireg == Op_VecA && cbuf) {
2080
2080
C2_MacroAssembler _masm(cbuf);
@@ -2180,10 +2180,29 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
2180
2180
} else if (dst_lo_rc == rc_float) { // stack --> fpr load
2181
2181
__ unspill(as_FloatRegister(Matcher::_regEncode[dst_lo]),
2182
2182
is64 ? __ D : __ S, src_offset);
2183
+ } else if (dst_lo_rc == rc_predicate) {
2184
+ __ unspill_sve_predicate(as_PRegister(Matcher::_regEncode[dst_lo]), ra_->reg2offset(src_lo),
2185
+ Matcher::scalable_vector_reg_size(T_BYTE) >> 3);
2183
2186
} else { // stack --> stack copy
2184
2187
assert(dst_lo_rc == rc_stack, "spill to bad register class");
2185
- __ unspill(rscratch1, is64, src_offset);
2186
- __ spill(rscratch1, is64, dst_offset);
2188
+ if (ideal_reg() == Op_RegVectMask) {
2189
+ __ spill_copy_sve_predicate_stack_to_stack(src_offset, dst_offset,
2190
+ Matcher::scalable_vector_reg_size(T_BYTE) >> 3);
2191
+ } else {
2192
+ __ unspill(rscratch1, is64, src_offset);
2193
+ __ spill(rscratch1, is64, dst_offset);
2194
+ }
2195
+ }
2196
+ break;
2197
+ case rc_predicate:
2198
+ if (dst_lo_rc == rc_predicate) {
2199
+ __ sve_mov(as_PRegister(Matcher::_regEncode[dst_lo]), as_PRegister(Matcher::_regEncode[src_lo]));
2200
+ } else if (dst_lo_rc == rc_stack) {
2201
+ __ spill_sve_predicate(as_PRegister(Matcher::_regEncode[src_lo]), ra_->reg2offset(dst_lo),
2202
+ Matcher::scalable_vector_reg_size(T_BYTE) >> 3);
2203
+ } else {
2204
+ assert(false, "bad src and dst rc_class combination.");
2205
+ ShouldNotReachHere();
2187
2206
}
2188
2207
break;
2189
2208
default:
@@ -2204,7 +2223,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
2204
2223
} else {
2205
2224
st->print("%s", Matcher::regName[dst_lo]);
2206
2225
}
2207
- if (bottom_type()->isa_vect() != NULL ) {
2226
+ if (bottom_type()->isa_vect() && !bottom_type()->isa_vectmask() ) {
2208
2227
int vsize = 0;
2209
2228
switch (ideal_reg()) {
2210
2229
case Op_VecD:
@@ -2221,6 +2240,10 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
2221
2240
ShouldNotReachHere();
2222
2241
}
2223
2242
st->print("\t# vector spill size = %d", vsize);
2243
+ } else if (ideal_reg() == Op_RegVectMask) {
2244
+ assert(Matcher::supports_scalable_vector(), "bad register type for spill");
2245
+ int vsize = Matcher::scalable_predicate_reg_slots() * 32;
2246
+ st->print("\t# predicate spill size = %d", vsize);
2224
2247
} else {
2225
2248
st->print("\t# spill size = %d", is64 ? 64 : 32);
2226
2249
}
@@ -2382,6 +2405,18 @@ const bool Matcher::match_rule_supported(int opcode) {
2382
2405
ret_value = false;
2383
2406
}
2384
2407
break;
2408
+ case Op_LoadVectorMasked:
2409
+ case Op_StoreVectorMasked:
2410
+ case Op_LoadVectorGatherMasked:
2411
+ case Op_StoreVectorScatterMasked:
2412
+ case Op_MaskAll:
2413
+ case Op_AndVMask:
2414
+ case Op_OrVMask:
2415
+ case Op_XorVMask:
2416
+ if (UseSVE == 0) {
2417
+ ret_value = false;
2418
+ }
2419
+ break;
2385
2420
}
2386
2421
2387
2422
return ret_value; // Per default match rules are supported.
@@ -2430,6 +2465,15 @@ const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType
2430
2465
return vector_size_supported(bt, vlen);
2431
2466
}
2432
2467
2468
+ const bool Matcher::match_rule_supported_vector_masked(int opcode, int vlen, BasicType bt) {
2469
+ // Only SVE supports masked operations.
2470
+ if (UseSVE == 0) {
2471
+ return false;
2472
+ }
2473
+ return match_rule_supported(opcode) &&
2474
+ masked_op_sve_supported(opcode, vlen, bt);
2475
+ }
2476
+
2433
2477
const RegMask* Matcher::predicate_reg_mask(void) {
2434
2478
return &_PR_REG_mask;
2435
2479
}
@@ -2643,10 +2687,14 @@ bool size_fits_all_mem_uses(AddPNode* addp, int shift) {
2643
2687
2644
2688
// Should the matcher clone input 'm' of node 'n'?
2645
2689
bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) {
2646
- if (is_vshift_con_pattern(n, m)) { // ShiftV src (ShiftCntV con)
2647
- mstack.push(m, Visit); // m = ShiftCntV
2690
+ // ShiftV src (ShiftCntV con)
2691
+ // StoreVector (VectorStoreMask src)
2692
+ if (is_vshift_con_pattern(n, m) ||
2693
+ (UseSVE > 0 && m->Opcode() == Op_VectorStoreMask && n->Opcode() == Op_StoreVector)) {
2694
+ mstack.push(m, Visit);
2648
2695
return true;
2649
2696
}
2697
+
2650
2698
return false;
2651
2699
}
2652
2700
@@ -5505,6 +5553,7 @@ operand pReg()
5505
5553
%{
5506
5554
constraint(ALLOC_IN_RC(pr_reg));
5507
5555
match(RegVectMask);
5556
+ match(pRegGov);
5508
5557
op_cost(0);
5509
5558
format %{ %}
5510
5559
interface(REG_INTER);
@@ -8854,6 +8903,17 @@ instruct castVV(vReg dst)
8854
8903
ins_pipe(pipe_class_empty);
8855
8904
%}
8856
8905
8906
+ instruct castVVMask(pRegGov dst)
8907
+ %{
8908
+ match(Set dst (CastVV dst));
8909
+
8910
+ size(0);
8911
+ format %{ "# castVV of $dst" %}
8912
+ ins_encode(/* empty encoding */);
8913
+ ins_cost(0);
8914
+ ins_pipe(pipe_class_empty);
8915
+ %}
8916
+
8857
8917
// ============================================================================
8858
8918
// Atomic operation instructions
8859
8919
//
0 commit comments