2424
2525struct Proto ;
2626
27- LUAU_FASTFLAG (LuauCodegenChainedSpills)
28-
2927namespace Luau
3028{
3129namespace CodeGen
3230{
3331
3432struct LoweringStats ;
3533
34+ constexpr uint8_t kUnknownTag = 0xff ;
35+
3636// IR extensions to LuauBuiltinFunction enum (these only exist inside IR, and start from 256 to avoid collisions)
3737enum
3838{
@@ -264,22 +264,40 @@ enum class IrCmd : uint8_t
264264 SELECT_IF_TRUTHY ,
265265
266266 // Add/Sub/Mul/Div/Idiv two vectors
267- // A, B: TValue
267+ // A, B: TValue (vector)
268268 ADD_VEC ,
269269 SUB_VEC ,
270270 MUL_VEC ,
271271 DIV_VEC ,
272272 IDIV_VEC ,
273273 // Lanewise A * B + C
274- // A, B, C: TValue
274+ // A, B, C: TValue (vector)
275275 MULADD_VEC ,
276276
277277 // Negate a vector
278- // A: TValue
278+ // A: TValue (vector)
279279 UNM_VEC ,
280280
281+ // Get the minimum/maximum of two vector elements
282+ // If one of the element values is NaN, 'B' is returned as the result
283+ // A, B: TValue (vector)
284+ MIN_VEC ,
285+ MAX_VEC ,
286+
287+ // Round vector elements to negative infinity
288+ // A: TValue (vector)
289+ FLOOR_VEC ,
290+
291+ // Round vector elements to positive infinity
292+ // A: TValue (vector)
293+ CEIL_VEC ,
294+
295+ // Get absolute value of vector elements
296+ // A: TValue (vector)
297+ ABS_VEC ,
298+
281299 // Compute dot product between two vectors as a float number (use FLOAT_TO_NUM to convert to double)
282- // A, B: TValue
300+ // A, B: TValue (vector)
283301 DOT_VEC ,
284302
285303 // Extract a component of a vector (use FLOAT_TO_NUM to convert to double)
@@ -444,10 +462,6 @@ enum class IrCmd : uint8_t
444462 // A: double
445463 NUM_TO_FLOAT ,
446464
447- // Converts a double number to a vector with the value in X/Y/Z
448- // A: double
449- NUM_TO_VEC_DEPRECATED ,
450-
451465 // Converts a float number to a vector with the value in X/Y/Z (use NUM_TO_FLOAT to convert from double)
452466 // A: float
453467 FLOAT_TO_VEC ,
@@ -1024,7 +1038,7 @@ struct IrInst
10241038 IrCmd cmd;
10251039
10261040 // Operands
1027- // All frequiently used instructions use only A-D slots.
1041+ // All frequently used instructions use only A-F slots.
10281042 IrOps ops;
10291043
10301044 uint32_t lastUse = 0 ;
@@ -1052,6 +1066,20 @@ inline IrOp& getOp(IrInst* inst, uint32_t idx)
10521066 return getOp (*inst, idx);
10531067}
10541068
1069+ inline bool hasOp (IrInst& inst, uint32_t idx)
1070+ {
1071+ return idx < inst.ops .size ();
1072+ }
1073+
1074+ // TODO: once we update kind checks to not use getOp, it will no longer cause a resize and second part can be removed
1075+ #define HAS_OP_A (inst ) (0 < (inst).ops.size() && (inst).ops[0 ].kind != IrOpKind::None)
1076+ #define HAS_OP_B (inst ) (1 < (inst).ops.size() && (inst).ops[1 ].kind != IrOpKind::None)
1077+ #define HAS_OP_C (inst ) (2 < (inst).ops.size() && (inst).ops[2 ].kind != IrOpKind::None)
1078+ #define HAS_OP_D (inst ) (3 < (inst).ops.size() && (inst).ops[3 ].kind != IrOpKind::None)
1079+ #define HAS_OP_E (inst ) (4 < (inst).ops.size() && (inst).ops[4 ].kind != IrOpKind::None)
1080+ #define HAS_OP_F (inst ) (5 < (inst).ops.size() && (inst).ops[5 ].kind != IrOpKind::None)
1081+ #define HAS_OP_G (inst ) (6 < (inst).ops.size() && (inst).ops[6 ].kind != IrOpKind::None)
1082+
10551083// When IrInst operands are used, current instruction index is often required to track lifetime
10561084inline constexpr uint32_t kInvalidInstIdx = ~0u ;
10571085
@@ -1233,8 +1261,7 @@ struct IrFunction
12331261 uint32_t endLocation = 0 ;
12341262
12351263 // For each instruction, an operand that can be used to recompute the value
1236- std::vector<IrOp> valueRestoreOps_DEPRECATED; // TODO: Remove with FFlagLuauCodegenChainedSpills
1237- std::vector<ValueRestoreLocation> valueRestoreOps_NEW;
1264+ std::vector<ValueRestoreLocation> valueRestoreOps;
12381265 std::vector<uint32_t > validRestoreOpBlocks;
12391266
12401267 BytecodeTypeInfo bcOriginalTypeInfo; // Bytecode type information as loaded
@@ -1379,63 +1406,19 @@ struct IrFunction
13791406 return uint32_t (&inst - instructions.data ());
13801407 }
13811408
1382- void recordRestoreOp_DEPRECATED (uint32_t instIdx, IrOp location)
1383- {
1384- CODEGEN_ASSERT (!FFlag::LuauCodegenChainedSpills);
1385-
1386- if (instIdx >= valueRestoreOps_DEPRECATED.size ())
1387- valueRestoreOps_DEPRECATED.resize (instIdx + 1 );
1388-
1389- valueRestoreOps_DEPRECATED[instIdx] = location;
1390- }
1391-
1392- IrOp findRestoreOp_DEPRECATED (uint32_t instIdx, bool limitToCurrentBlock) const
1393- {
1394- CODEGEN_ASSERT (!FFlag::LuauCodegenChainedSpills);
1395-
1396- if (instIdx >= valueRestoreOps_DEPRECATED.size ())
1397- return {};
1398-
1399- // When spilled, values can only reference restore operands in the current block chain
1400- if (limitToCurrentBlock)
1401- {
1402- for (uint32_t blockIdx : validRestoreOpBlocks)
1403- {
1404- const IrBlock& block = blocks[blockIdx];
1405-
1406- if (instIdx >= block.start && instIdx <= block.finish )
1407- return valueRestoreOps_DEPRECATED[instIdx];
1408- }
1409-
1410- return {};
1411- }
1412-
1413- return valueRestoreOps_DEPRECATED[instIdx];
1414- }
1415-
1416- IrOp findRestoreOp_DEPRECATED (const IrInst& inst, bool limitToCurrentBlock) const
1417- {
1418- CODEGEN_ASSERT (!FFlag::LuauCodegenChainedSpills);
1419-
1420- return findRestoreOp_DEPRECATED (getInstIndex (inst), limitToCurrentBlock);
1421- }
1422-
14231409 void recordRestoreLocation (uint32_t instIdx, ValueRestoreLocation location)
14241410 {
1425- CODEGEN_ASSERT (FFlag::LuauCodegenChainedSpills);
14261411 CODEGEN_ASSERT (location.op .kind == IrOpKind::None || location.op .kind == IrOpKind::VmReg || location.op .kind == IrOpKind::VmConst);
14271412
1428- if (instIdx >= valueRestoreOps_NEW .size ())
1429- valueRestoreOps_NEW .resize (instIdx + 1 );
1413+ if (instIdx >= valueRestoreOps .size ())
1414+ valueRestoreOps .resize (instIdx + 1 );
14301415
1431- valueRestoreOps_NEW [instIdx] = location;
1416+ valueRestoreOps [instIdx] = location;
14321417 }
14331418
14341419 ValueRestoreLocation findRestoreLocation (uint32_t instIdx, bool limitToCurrentBlock) const
14351420 {
1436- CODEGEN_ASSERT (FFlag::LuauCodegenChainedSpills);
1437-
1438- if (instIdx >= valueRestoreOps_NEW.size ())
1421+ if (instIdx >= valueRestoreOps.size ())
14391422 return {};
14401423
14411424 // When spilled, values can only reference restore operands in the current block chain
@@ -1446,26 +1429,22 @@ struct IrFunction
14461429 const IrBlock& block = blocks[blockIdx];
14471430
14481431 if (instIdx >= block.start && instIdx <= block.finish )
1449- return valueRestoreOps_NEW [instIdx];
1432+ return valueRestoreOps [instIdx];
14501433 }
14511434
14521435 return {};
14531436 }
14541437
1455- return valueRestoreOps_NEW [instIdx];
1438+ return valueRestoreOps [instIdx];
14561439 }
14571440
14581441 ValueRestoreLocation findRestoreLocation (const IrInst& inst, bool limitToCurrentBlock) const
14591442 {
1460- CODEGEN_ASSERT (FFlag::LuauCodegenChainedSpills);
1461-
14621443 return findRestoreLocation (getInstIndex (inst), limitToCurrentBlock);
14631444 }
14641445
14651446 bool hasRestoreLocation (const IrInst& inst, bool limitToCurrentBlock) const
14661447 {
1467- CODEGEN_ASSERT (FFlag::LuauCodegenChainedSpills);
1468-
14691448 return findRestoreLocation (getInstIndex (inst), limitToCurrentBlock).op .kind != IrOpKind::None;
14701449 }
14711450
0 commit comments