66#include " Luau/Label.h"
77#include " Luau/RegisterX64.h"
88#include " Luau/RegisterA64.h"
9+ #include " Luau/SmallVector.h"
910
1011#include < optional>
1112#include < vector>
1213
1314#include < stdint.h>
1415#include < string.h>
1516
17+ #define OP_A (inst ) getOp(inst, 0 )
18+ #define OP_B (inst ) getOp(inst, 1 )
19+ #define OP_C (inst ) getOp(inst, 2 )
20+ #define OP_D (inst ) getOp(inst, 3 )
21+ #define OP_E (inst ) getOp(inst, 4 )
22+ #define OP_F (inst ) getOp(inst, 5 )
23+ #define OP_G (inst ) getOp(inst, 6 )
24+
1625struct Proto ;
1726
1827LUAU_FASTFLAG (LuauCodegenChainedSpills)
@@ -1008,18 +1017,15 @@ enum class IrValueKind : uint8_t
10081017 Count
10091018};
10101019
1020+ using IrOps = SmallVector<IrOp, 6 >;
1021+
10111022struct IrInst
10121023{
10131024 IrCmd cmd;
10141025
10151026 // Operands
1016- IrOp a;
1017- IrOp b;
1018- IrOp c;
1019- IrOp d;
1020- IrOp e;
1021- IrOp f;
1022- IrOp g;
1027+ // All frequiently used instructions use only A-D slots.
1028+ IrOps ops;
10231029
10241030 uint32_t lastUse = 0 ;
10251031 uint16_t useCount = 0 ;
@@ -1032,6 +1038,20 @@ struct IrInst
10321038 bool needsReload = false ;
10331039};
10341040
1041+ inline IrOp& getOp (IrInst& inst, uint32_t idx)
1042+ {
1043+ if (LUAU_UNLIKELY (idx >= inst.ops .size ()))
1044+ {
1045+ inst.ops .resize (idx + 1 );
1046+ }
1047+ return inst.ops [idx];
1048+ }
1049+
1050+ inline IrOp& getOp (IrInst* inst, uint32_t idx)
1051+ {
1052+ return getOp (*inst, idx);
1053+ }
1054+
10351055// When IrInst operands are used, current instruction index is often required to track lifetime
10361056inline constexpr uint32_t kInvalidInstIdx = ~0u ;
10371057
@@ -1068,13 +1088,8 @@ struct IrInstHash
10681088 uint32_t h = 25 ;
10691089
10701090 h = mix (h, uint32_t (key.cmd ));
1071- h = mix (h, key.a );
1072- h = mix (h, key.b );
1073- h = mix (h, key.c );
1074- h = mix (h, key.d );
1075- h = mix (h, key.e );
1076- h = mix (h, key.f );
1077- h = mix (h, key.g );
1091+ for (size_t i = 0 ; i < 7 ; i++)
1092+ h = mix (h, i < uint32_t (key.ops .size ()) ? key.ops [i] : IrOp{});
10781093
10791094 // MurmurHash2 tail
10801095 h ^= h >> 13 ;
@@ -1089,7 +1104,35 @@ struct IrInstEq
10891104{
10901105 bool operator ()(const IrInst& a, const IrInst& b) const
10911106 {
1092- return a.cmd == b.cmd && a.a == b.a && a.b == b.b && a.c == b.c && a.d == b.d && a.e == b.e && a.f == b.f && a.g == b.g ;
1107+ if (a.cmd != b.cmd )
1108+ return false ;
1109+ if (a.ops .size () == b.ops .size ())
1110+ {
1111+ for (size_t i = 0 ; i < a.ops .size (); i++)
1112+ if (a.ops [i] != b.ops [i])
1113+ return false ;
1114+ }
1115+ else if (a.ops .size () < b.ops .size ())
1116+ {
1117+ size_t i = 0 ;
1118+ for (; i < a.ops .size (); i++)
1119+ if (a.ops [i] != b.ops [i])
1120+ return false ;
1121+ for (; i < b.ops .size (); i++)
1122+ if (b.ops [i].kind != IrOpKind::None)
1123+ return false ;
1124+ }
1125+ else
1126+ {
1127+ size_t i = 0 ;
1128+ for (; i < b.ops .size (); i++)
1129+ if (a.ops [i] != b.ops [i])
1130+ return false ;
1131+ for (; i < a.ops .size (); i++)
1132+ if (a.ops [i].kind != IrOpKind::None)
1133+ return false ;
1134+ }
1135+ return true ;
10931136 }
10941137};
10951138
0 commit comments