11/*
2- * Copyright (c) 2019, 2023 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2019, 2024 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
@@ -1081,14 +1081,43 @@ void ZBarrierSetAssembler::generate_c1_store_barrier_runtime_stub(StubAssembler*
10811081
10821082#ifdef COMPILER2
10831083
1084+ OptoReg::Name ZBarrierSetAssembler::encode_float_vector_register_size (const Node* node, OptoReg::Name opto_reg) {
1085+ switch (node->ideal_reg ()) {
1086+ case Op_RegF:
1087+ // No need to refine. The original encoding is already fine to distinguish.
1088+ assert (opto_reg % 4 == 0 , " Float register should only occupy a single slot" );
1089+ break ;
1090+ // Use different encoding values of the same fp/vector register to help distinguish different sizes.
1091+ // Such as V16. The OptoReg::name and its corresponding slot value are
1092+ // "V16": 64, "V16_H": 65, "V16_J": 66, "V16_K": 67.
1093+ case Op_RegD:
1094+ case Op_VecD:
1095+ opto_reg &= ~3 ;
1096+ opto_reg |= 1 ;
1097+ break ;
1098+ case Op_VecX:
1099+ opto_reg &= ~3 ;
1100+ opto_reg |= 2 ;
1101+ break ;
1102+ case Op_VecA:
1103+ opto_reg &= ~3 ;
1104+ opto_reg |= 3 ;
1105+ break ;
1106+ default :
1107+ assert (false , " unexpected ideal register" );
1108+ ShouldNotReachHere ();
1109+ }
1110+ return opto_reg;
1111+ }
1112+
10841113OptoReg::Name ZBarrierSetAssembler::refine_register (const Node* node, OptoReg::Name opto_reg) {
10851114 if (!OptoReg::is_reg (opto_reg)) {
10861115 return OptoReg::Bad;
10871116 }
10881117
10891118 const VMReg vm_reg = OptoReg::as_VMReg (opto_reg);
10901119 if (vm_reg->is_FloatRegister ()) {
1091- return opto_reg & ~ 1 ;
1120+ opto_reg = encode_float_vector_register_size (node, opto_reg) ;
10921121 }
10931122
10941123 return opto_reg;
@@ -1099,28 +1128,82 @@ OptoReg::Name ZBarrierSetAssembler::refine_register(const Node* node, OptoReg::N
10991128
11001129class ZSaveLiveRegisters {
11011130private:
1131+ struct RegisterData {
1132+ VMReg _reg;
1133+ int _slots; // slots occupied once pushed into stack
1134+
1135+ // Used by GrowableArray::find()
1136+ bool operator == (const RegisterData& other) {
1137+ return _reg == other._reg ;
1138+ }
1139+ };
1140+
11021141 MacroAssembler* const _masm;
11031142 RegSet _gp_regs;
11041143 FloatRegSet _fp_regs;
1144+ FloatRegSet _neon_regs;
1145+ FloatRegSet _sve_regs;
11051146 PRegSet _p_regs;
11061147
11071148public:
11081149 void initialize (ZBarrierStubC2* stub) {
1109- // Record registers that needs to be saved/restored
1150+ int index = -1 ;
1151+ GrowableArray<RegisterData> registers;
1152+ VMReg prev_vm_reg = VMRegImpl::Bad ();
1153+
11101154 RegMaskIterator rmi (stub->live ());
11111155 while (rmi.has_next ()) {
1112- const OptoReg::Name opto_reg = rmi.next ();
1113- if (OptoReg::is_reg (opto_reg)) {
1114- const VMReg vm_reg = OptoReg::as_VMReg (opto_reg);
1115- if (vm_reg->is_Register ()) {
1116- _gp_regs += RegSet::of (vm_reg->as_Register ());
1117- } else if (vm_reg->is_FloatRegister ()) {
1156+ OptoReg::Name opto_reg = rmi.next ();
1157+ VMReg vm_reg = OptoReg::as_VMReg (opto_reg);
1158+
1159+ if (vm_reg->is_Register ()) {
1160+ // GPR may have one or two slots in regmask
1161+ // Determine whether the current vm_reg is the same physical register as the previous one
1162+ if (is_same_register (vm_reg, prev_vm_reg)) {
1163+ registers.at (index)._slots ++;
1164+ } else {
1165+ RegisterData reg_data = { vm_reg, 1 };
1166+ index = registers.append (reg_data);
1167+ }
1168+ } else if (vm_reg->is_FloatRegister ()) {
1169+ // We have size encoding in OptoReg of stub->live()
1170+ // After encoding, float/neon/sve register has only one slot in regmask
1171+ // Decode it to get the actual size
1172+ VMReg vm_reg_base = vm_reg->as_FloatRegister ()->as_VMReg ();
1173+ int slots = decode_float_vector_register_size (opto_reg);
1174+ RegisterData reg_data = { vm_reg_base, slots };
1175+ index = registers.append (reg_data);
1176+ } else if (vm_reg->is_PRegister ()) {
1177+ // PRegister has only one slot in regmask
1178+ RegisterData reg_data = { vm_reg, 1 };
1179+ index = registers.append (reg_data);
1180+ } else {
1181+ assert (false , " Unknown register type" );
1182+ ShouldNotReachHere ();
1183+ }
1184+ prev_vm_reg = vm_reg;
1185+ }
1186+
1187+ // Record registers that needs to be saved/restored
1188+ for (GrowableArrayIterator<RegisterData> it = registers.begin (); it != registers.end (); ++it) {
1189+ RegisterData reg_data = *it;
1190+ VMReg vm_reg = reg_data._reg ;
1191+ int slots = reg_data._slots ;
1192+ if (vm_reg->is_Register ()) {
1193+ assert (slots == 1 || slots == 2 , " Unexpected register save size" );
1194+ _gp_regs += RegSet::of (vm_reg->as_Register ());
1195+ } else if (vm_reg->is_FloatRegister ()) {
1196+ if (slots == 1 || slots == 2 ) {
11181197 _fp_regs += FloatRegSet::of (vm_reg->as_FloatRegister ());
1119- } else if (vm_reg-> is_PRegister () ) {
1120- _p_regs += PRegSet ::of (vm_reg->as_PRegister ());
1198+ } else if (slots == 4 ) {
1199+ _neon_regs += FloatRegSet ::of (vm_reg->as_FloatRegister ());
11211200 } else {
1122- fatal (" Unknown register type" );
1201+ assert (slots == Matcher::scalable_vector_reg_size (T_FLOAT), " Unexpected register save size" );
1202+ _sve_regs += FloatRegSet::of (vm_reg->as_FloatRegister ());
11231203 }
1204+ } else {
1205+ assert (vm_reg->is_PRegister () && slots == 1 , " Unknown register type" );
1206+ _p_regs += PRegSet::of (vm_reg->as_PRegister ());
11241207 }
11251208 }
11261209
@@ -1130,27 +1213,84 @@ class ZSaveLiveRegisters {
11301213 } else {
11311214 _gp_regs -= RegSet::range (r19, r30) + RegSet::of (r8, r9);
11321215 }
1216+
1217+ // Remove C-ABI SOE fp registers
1218+ _fp_regs -= FloatRegSet::range (v8, v15);
1219+ }
1220+
1221+ static enum RC rc_class (VMReg reg) {
1222+ if (reg->is_reg ()) {
1223+ if (reg->is_Register ()) {
1224+ return rc_int;
1225+ } else if (reg->is_FloatRegister ()) {
1226+ return rc_float;
1227+ } else if (reg->is_PRegister ()) {
1228+ return rc_predicate;
1229+ }
1230+ }
1231+ if (reg->is_stack ()) {
1232+ return rc_stack;
1233+ }
1234+ return rc_bad;
1235+ }
1236+
1237+ static bool is_same_register (VMReg reg1, VMReg reg2) {
1238+ if (reg1 == reg2) {
1239+ return true ;
1240+ }
1241+ if (rc_class (reg1) == rc_class (reg2)) {
1242+ if (reg1->is_Register ()) {
1243+ return reg1->as_Register () == reg2->as_Register ();
1244+ } else if (reg1->is_FloatRegister ()) {
1245+ return reg1->as_FloatRegister () == reg2->as_FloatRegister ();
1246+ } else if (reg1->is_PRegister ()) {
1247+ return reg1->as_PRegister () == reg2->as_PRegister ();
1248+ }
1249+ }
1250+ return false ;
1251+ }
1252+
1253+ static int decode_float_vector_register_size (OptoReg::Name opto_reg) {
1254+ switch (opto_reg & 3 ) {
1255+ case 0 :
1256+ return 1 ;
1257+ case 1 :
1258+ return 2 ;
1259+ case 2 :
1260+ return 4 ;
1261+ case 3 :
1262+ return Matcher::scalable_vector_reg_size (T_FLOAT);
1263+ default :
1264+ ShouldNotReachHere ();
1265+ return 0 ;
1266+ }
11331267 }
11341268
11351269 ZSaveLiveRegisters (MacroAssembler* masm, ZBarrierStubC2* stub)
11361270 : _masm(masm),
11371271 _gp_regs (),
11381272 _fp_regs(),
1273+ _neon_regs(),
1274+ _sve_regs(),
11391275 _p_regs() {
11401276
11411277 // Figure out what registers to save/restore
11421278 initialize (stub);
11431279
11441280 // Save registers
11451281 __ push (_gp_regs, sp);
1146- __ push_fp (_fp_regs, sp);
1282+ __ push_fp (_fp_regs, sp, MacroAssembler::PushPopFp);
1283+ __ push_fp (_neon_regs, sp, MacroAssembler::PushPopNeon);
1284+ __ push_fp (_sve_regs, sp, MacroAssembler::PushPopSVE);
11471285 __ push_p (_p_regs, sp);
11481286 }
11491287
11501288 ~ZSaveLiveRegisters () {
11511289 // Restore registers
11521290 __ pop_p (_p_regs, sp);
1153- __ pop_fp (_fp_regs, sp);
1291+ __ pop_fp (_sve_regs, sp, MacroAssembler::PushPopSVE);
1292+ __ pop_fp (_neon_regs, sp, MacroAssembler::PushPopNeon);
1293+ __ pop_fp (_fp_regs, sp, MacroAssembler::PushPopFp);
11541294
11551295 // External runtime call may clobber ptrue reg
11561296 __ reinitialize_ptrue ();
0 commit comments