Fix reading Time zone rules using Julian days (#17672)
[platform/upstream/coreclr.git] / src / jit / regset.h
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 /*****************************************************************************/
6
7 #ifndef _REGSET_H
8 #define _REGSET_H
9 #include "vartype.h"
10 #include "target.h"
11
12 class LclVarDsc;
13 class TempDsc;
14 class Compiler;
15 class CodeGen;
16 class GCInfo;
17
18 /*
19 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
20 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
21 XX                                                                           XX
22 XX                           RegSet                                          XX
23 XX                                                                           XX
24 XX  Represents the register set, and their states during code generation     XX
25 XX  Can select an unused register, keeps track of the contents of the        XX
26 XX  registers, and can spill registers                                       XX
27 XX                                                                           XX
28 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
29 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
30 */
31
32 #ifdef LEGACY_BACKEND
33 /*****************************************************************************
34 *
35 *  Keep track of the current state of each register. This is intended to be
36 *  used for things like register reload suppression, but for now the only
37 *  thing it does is note which registers we use in each method.
38 */
39
40 enum regValKind
41 {
42     RV_TRASH,          // random unclassified garbage
43     RV_INT_CNS,        // integer constant
44     RV_LCL_VAR,        // local variable value
45     RV_LCL_VAR_LNG_LO, // lower half of long local variable
46     RV_LCL_VAR_LNG_HI,
47 };
48 #endif // LEGACY_BACKEND
49
50 /*****************************************************************************/
51
52 class RegSet
53 {
54     friend class CodeGen;
55     friend class CodeGenInterface;
56
57 private:
58     Compiler* m_rsCompiler;
59     GCInfo&   m_rsGCInfo;
60
61 public:
62     RegSet(Compiler* compiler, GCInfo& gcInfo);
63
64 #ifdef _TARGET_ARM_
65     regMaskTP rsMaskPreSpillRegs(bool includeAlignment)
66     {
67         return includeAlignment ? (rsMaskPreSpillRegArg | rsMaskPreSpillAlign) : rsMaskPreSpillRegArg;
68     }
69 #endif // _TARGET_ARM_
70
71 private:
72     // The same descriptor is also used for 'multi-use' register tracking, BTW.
73     struct SpillDsc
74     {
75         SpillDsc* spillNext; // next spilled value of same reg
76
77         union {
78             GenTree* spillTree; // the value that was spilled
79 #ifdef LEGACY_BACKEND
80             LclVarDsc* spillVarDsc; // variable if it's an enregistered variable
81 #endif                              // LEGACY_BACKEND
82         };
83
84         TempDsc* spillTemp; // the temp holding the spilled value
85
86 #ifdef LEGACY_BACKEND
87         GenTree* spillAddr; // owning complex address mode or nullptr
88
89         union {
90             bool spillMoreMultis;
91             bool bEnregisteredVariable; // For FP. Indicates that what was spilled was
92                                         // an enregistered variable
93         };
94 #endif // LEGACY_BACKEND
95
96         static SpillDsc* alloc(Compiler* pComp, RegSet* regSet, var_types type);
97         static void freeDsc(RegSet* regSet, SpillDsc* spillDsc);
98     };
99
100 #ifdef LEGACY_BACKEND
101 public:
102     regMaskTP rsUseIfZero(regMaskTP regs, regMaskTP includeHint);
103 #endif // LEGACY_BACKEND
104
105 //-------------------------------------------------------------------------
106 //
107 //  Track the status of the registers
108 //
109 #ifdef LEGACY_BACKEND
110 public:                             // TODO-Cleanup: Should be private, but Compiler uses it
111     GenTree* rsUsedTree[REG_COUNT]; // trees currently sitting in the registers
112 private:
113     GenTree*  rsUsedAddr[REG_COUNT];  // addr for which rsUsedTree[reg] is a part of the addressing mode
114     SpillDsc* rsMultiDesc[REG_COUNT]; // keeps track of 'multiple-use' registers.
115 #endif                                // LEGACY_BACKEND
116
117 private:
118     bool      rsNeededSpillReg;   // true if this method needed to spill any registers
119     regMaskTP rsModifiedRegsMask; // mask of the registers modified by the current function.
120
121 #ifdef DEBUG
122     bool rsModifiedRegsMaskInitialized; // Has rsModifiedRegsMask been initialized? Guards against illegal use.
123 #endif                                  // DEBUG
124
125 public:
126     regMaskTP rsGetModifiedRegsMask() const
127     {
128         assert(rsModifiedRegsMaskInitialized);
129         return rsModifiedRegsMask;
130     }
131
132     void rsClearRegsModified();
133
134     void rsSetRegsModified(regMaskTP mask DEBUGARG(bool suppressDump = false));
135
136     void rsRemoveRegsModified(regMaskTP mask);
137
138     bool rsRegsModified(regMaskTP mask) const
139     {
140         assert(rsModifiedRegsMaskInitialized);
141         return (rsModifiedRegsMask & mask) != 0;
142     }
143
144 public: // TODO-Cleanup: Should be private, but GCInfo uses them
145 #ifdef LEGACY_BACKEND
146     regMaskTP rsMaskUsed; // currently 'used' registers mask
147 #endif                    // LEGACY_BACKEND
148
149     __declspec(property(get = GetMaskVars, put = SetMaskVars)) regMaskTP rsMaskVars; // mask of registers currently
150                                                                                      // allocated to variables
151
152     regMaskTP GetMaskVars() const // 'get' property function for rsMaskVars property
153     {
154         return _rsMaskVars;
155     }
156
157     void SetMaskVars(regMaskTP newMaskVars); // 'put' property function for rsMaskVars property
158
159     void AddMaskVars(regMaskTP addMaskVars) // union 'addMaskVars' with the rsMaskVars set
160     {
161         SetMaskVars(_rsMaskVars | addMaskVars);
162     }
163
164     void RemoveMaskVars(regMaskTP removeMaskVars) // remove 'removeMaskVars' from the rsMaskVars set (like bitset DiffD)
165     {
166         SetMaskVars(_rsMaskVars & ~removeMaskVars);
167     }
168
169     void ClearMaskVars() // Like SetMaskVars(RBM_NONE), but without any debug output.
170     {
171         _rsMaskVars = RBM_NONE;
172     }
173
174 private:
175     regMaskTP _rsMaskVars; // backing store for rsMaskVars property
176
177 #ifdef LEGACY_BACKEND
178     regMaskTP rsMaskLock; // currently 'locked' registers mask
179     regMaskTP rsMaskMult; // currently 'multiply used' registers mask
180 #endif                    // LEGACY_BACKEND
181
182 #ifdef _TARGET_ARMARCH_
183     regMaskTP rsMaskCalleeSaved; // mask of the registers pushed/popped in the prolog/epilog
184 #endif                           // _TARGET_ARM_
185
186 public:                    // TODO-Cleanup: Should be private, but Compiler uses it
187     regMaskTP rsMaskResvd; // mask of the registers that are reserved for special purposes (typically empty)
188
189 public: // The PreSpill masks are used in LclVars.cpp
190 #ifdef _TARGET_ARM_
191     regMaskTP rsMaskPreSpillAlign;  // Mask of alignment padding added to prespill to keep double aligned args
192                                     // at aligned stack addresses.
193     regMaskTP rsMaskPreSpillRegArg; // mask of incoming registers that are spilled at the start of the prolog
194                                     // This includes registers used to pass a struct (or part of a struct)
195                                     // and all enregistered user arguments in a varargs call
196 #endif                              // _TARGET_ARM_
197
198 #ifdef LEGACY_BACKEND
199
200 private:
201     // These getters/setters are ifdef here so that the accesses to these values in sharedfloat.cpp are redirected
202     // to the appropriate value.
203     // With FEATURE_STACK_FP_X87 (x86 FP codegen) we have separate register mask that just handle FP registers.
204     // For all other platforms (and eventually on x86) we use unified register masks that handle both kinds.
205     //
206     regMaskTP rsGetMaskUsed(); // Getter for rsMaskUsed or rsMaskUsedFloat
207     regMaskTP rsGetMaskVars(); // Getter for rsMaskVars or rsMaskRegVarFloat
208     regMaskTP rsGetMaskLock(); // Getter for rsMaskLock or rsMaskLockedFloat
209     regMaskTP rsGetMaskMult(); // Getter for rsMaskMult or 0
210
211     void rsSetMaskUsed(regMaskTP maskUsed); // Setter for rsMaskUsed or rsMaskUsedFloat
212     void rsSetMaskVars(regMaskTP maskVars); // Setter for rsMaskVars or rsMaskRegVarFloat
213     void rsSetMaskLock(regMaskTP maskLock); // Setter for rsMaskLock or rsMaskLockedFloat
214
215     void rsSetUsedTree(regNumber regNum, GenTree* tree);  // Setter for  rsUsedTree[]/genUsedRegsFloat[]
216     void rsFreeUsedTree(regNumber regNum, GenTree* tree); // Free   for  rsUsedTree[]/genUsedRegsFloat[]
217
218 public:
219     regPairNo rsFindRegPairNo(regMaskTP regMask);
220
221 private:
222     bool rsIsTreeInReg(regNumber reg, GenTree* tree);
223
224     regMaskTP rsExcludeHint(regMaskTP regs, regMaskTP excludeHint);
225     regMaskTP rsNarrowHint(regMaskTP regs, regMaskTP narrowHint);
226     regMaskTP rsMustExclude(regMaskTP regs, regMaskTP exclude);
227     regMaskTP rsRegMaskFree();
228     regMaskTP rsRegMaskCanGrab();
229
230     void rsMarkRegUsed(GenTree* tree, GenTree* addr = 0);
231     // A special case of "rsMarkRegUsed": the register used is an argument register, used to hold part of
232     // the given argument node "promotedStructArg".  (The name suggests that we're likely to use use this
233     // for register holding a promoted struct argument, but the implementation doesn't depend on that.)  The
234     // "isGCRef" argument indicates whether the register contains a GC reference.
235     void rsMarkArgRegUsedByPromotedFieldArg(GenTree* promotedStructArg, regNumber regNum, bool isGCRef);
236
237     void rsMarkRegPairUsed(GenTree* tree);
238
239     void rsMarkRegFree(regMaskTP regMask);
240     void rsMarkRegFree(regNumber reg, GenTree* tree);
241     void rsMultRegFree(regMaskTP regMask);
242     unsigned rsFreeNeededRegCount(regMaskTP needReg);
243
244     void rsLockReg(regMaskTP regMask);
245     void rsUnlockReg(regMaskTP regMask);
246     void rsLockUsedReg(regMaskTP regMask);
247     void rsUnlockUsedReg(regMaskTP regMask);
248     void rsLockReg(regMaskTP regMask, regMaskTP* usedMask);
249     void rsUnlockReg(regMaskTP regMask, regMaskTP usedMask);
250
251     regMaskTP rsRegExclMask(regMaskTP regMask, regMaskTP rmvMask);
252
253     regNumber rsPickRegInTmpOrder(regMaskTP regMask);
254
255 public: // used by emitter (!)
256     regNumber rsGrabReg(regMaskTP regMask);
257
258 private:
259     regNumber rsPickReg(regMaskTP regMask = RBM_NONE, regMaskTP regBest = RBM_NONE);
260
261 public: // used by emitter (!)
262     regNumber rsPickFreeReg(regMaskTP regMaskHint = RBM_ALLINT);
263
264 private:
265     regPairNo rsGrabRegPair(regMaskTP regMask);
266     regPairNo rsPickRegPair(regMaskTP regMask);
267
268     class RegisterPreference
269     {
270     public:
271         regMaskTP ok;
272         regMaskTP best;
273         RegisterPreference(regMaskTP _ok, regMaskTP _best)
274         {
275             ok   = _ok;
276             best = _best;
277         }
278     };
279     regNumber PickRegFloat(GenTree*            tree,
280                            var_types           type  = TYP_DOUBLE,
281                            RegisterPreference* pref  = NULL,
282                            bool                bUsed = true);
283     regNumber PickRegFloat(var_types type = TYP_DOUBLE, RegisterPreference* pref = NULL, bool bUsed = true);
284     regNumber PickRegFloatOtherThan(GenTree* tree, var_types type, regNumber reg);
285     regNumber PickRegFloatOtherThan(var_types type, regNumber reg);
286
287     regMaskTP RegFreeFloat();
288
289     void SetUsedRegFloat(GenTree* tree, bool bValue);
290     void SetLockedRegFloat(GenTree* tree, bool bValue);
291     bool IsLockedRegFloat(GenTree* tree);
292
293     var_types rsRmvMultiReg(regNumber reg);
294     void rsRecMultiReg(regNumber reg, var_types type);
295 #endif // LEGACY_BACKEND
296
297 public:
298 #ifdef DEBUG
299     /*****************************************************************************
300         *  Should we stress register tracking logic ?
301         *  This is set via COMPlus_JitStressRegs.
302         *  The following values are ordered, such that any value greater than RS_xx
303         *  implies RS_xx.
304         *  LSRA defines a different set of values, but uses the same COMPlus_JitStressRegs
305         *  value, with the same notion of relative ordering.
306         *  1 = rsPickReg() picks 'bad' registers.
307         *  2 = codegen spills at safe points. This is still flaky
308         */
309     enum rsStressRegsType
310     {
311         RS_STRESS_NONE  = 0,
312         RS_PICK_BAD_REG = 01,
313         RS_SPILL_SAFE   = 02,
314     };
315     rsStressRegsType rsStressRegs();
316 #endif // DEBUG
317
318 private:
319     //-------------------------------------------------------------------------
320     //
321     //  The following tables keep track of spilled register values.
322     //
323
324     // When a register gets spilled, the old information is stored here
325     SpillDsc* rsSpillDesc[REG_COUNT];
326     SpillDsc* rsSpillFree; // list of unused spill descriptors
327
328 #ifdef LEGACY_BACKEND
329     SpillDsc* rsSpillFloat;
330 #endif // LEGACY_BACKEND
331
332     void rsSpillChk();
333     void rsSpillInit();
334     void rsSpillDone();
335     void rsSpillBeg();
336     void rsSpillEnd();
337
338     void rsSpillTree(regNumber reg, GenTree* tree, unsigned regIdx = 0);
339
340 #if defined(_TARGET_X86_) && !FEATURE_STACK_FP_X87
341     void rsSpillFPStack(GenTreeCall* call);
342 #endif // defined(_TARGET_X86_) && !FEATURE_STACK_FP_X87
343
344 #ifdef LEGACY_BACKEND
345     void rsSpillReg(regNumber reg);
346     void rsSpillRegIfUsed(regNumber reg);
347     void rsSpillRegs(regMaskTP regMask);
348 #endif // LEGACY_BACKEND
349
350     SpillDsc* rsGetSpillInfo(GenTree*   tree,
351                              regNumber  reg,
352                              SpillDsc** pPrevDsc = nullptr
353 #ifdef LEGACY_BACKEND
354                              ,
355                              SpillDsc** pMultiDsc = NULL
356 #endif // LEGACY_BACKEND
357                              );
358
359     TempDsc* rsGetSpillTempWord(regNumber oldReg, SpillDsc* dsc, SpillDsc* prevDsc);
360
361 #ifdef LEGACY_BACKEND
362     enum ExactReg
363     {
364         ANY_REG,
365         EXACT_REG
366     };
367     enum KeepReg
368     {
369         FREE_REG,
370         KEEP_REG
371     };
372
373     regNumber rsUnspillOneReg(GenTree* tree, regNumber oldReg, KeepReg willKeepNewReg, regMaskTP needReg);
374 #endif // LEGACY_BACKEND
375
376     TempDsc* rsUnspillInPlace(GenTree* tree, regNumber oldReg, unsigned regIdx = 0);
377
378 #ifdef LEGACY_BACKEND
379     void rsUnspillReg(GenTree* tree, regMaskTP needReg, KeepReg keepReg);
380
381     void rsUnspillRegPair(GenTree* tree, regMaskTP needReg, KeepReg keepReg);
382 #endif // LEGACY_BACKEND
383
384     void rsMarkSpill(GenTree* tree, regNumber reg);
385
386 #ifdef LEGACY_BACKEND
387     void rsMarkUnspill(GenTree* tree, regNumber reg);
388 #endif // LEGACY_BACKEND
389
390 #if FEATURE_STACK_FP_X87
391     regMaskTP  rsMaskUsedFloat;
392     regMaskTP  rsMaskRegVarFloat;
393     regMaskTP  rsMaskLockedFloat;
394     GenTree*   genUsedRegsFloat[REG_FPCOUNT];
395     LclVarDsc* genRegVarsFloat[REG_FPCOUNT];
396 #endif // FEATURE_STACK_FP_X87
397 };
398
399 //-------------------------------------------------------------------------
400 //
401 //  These are used to track the contents of the registers during
402 //  code generation.
403 //
404 //  Only integer registers are tracked.
405 //
406
407 #ifdef LEGACY_BACKEND
408 struct RegValDsc
409 {
410     regValKind rvdKind;
411     union {
412         ssize_t  rvdIntCnsVal; // for rvdKind == RV_INT_CNS
413         unsigned rvdLclVarNum; // for rvdKind == RV_LCL_VAR, RV_LCL_VAR_LNG_LO, RV_LCL_VAR_LNG_HI
414     };
415 };
416 #endif // LEGACY_BACKEND
417
418 class RegTracker
419 {
420     Compiler* compiler;
421     RegSet*   regSet;
422 #ifdef LEGACY_BACKEND
423     RegValDsc rsRegValues[REG_COUNT];
424 #endif
425
426 public:
427     void rsTrackInit(Compiler* comp, RegSet* rs)
428     {
429         compiler = comp;
430         regSet   = rs;
431 #ifdef LEGACY_BACKEND
432         rsTrackRegClr();
433 #endif
434     }
435
436 #ifdef LEGACY_BACKEND
437     void rsTrackRegClr();
438     void rsTrackRegClrPtr();
439 #endif // LEGACY_BACKEND
440     void rsTrackRegTrash(regNumber reg);
441 #ifdef LEGACY_BACKEND
442     void rsTrackRegMaskTrash(regMaskTP regMask);
443     regMaskTP rsTrashRegsForGCInterruptability();
444 #endif // LEGACY_BACKEND
445     void rsTrackRegIntCns(regNumber reg, ssize_t val);
446     void rsTrackRegLclVar(regNumber reg, unsigned var);
447 #ifdef LEGACY_BACKEND
448     void rsTrackRegLclVarLng(regNumber reg, unsigned var, bool low);
449     bool rsTrackIsLclVarLng(regValKind rvKind);
450     void rsTrackRegClsVar(regNumber reg, GenTree* clsVar);
451 #endif // LEGACY_BACKEND
452     void rsTrackRegCopy(regNumber reg1, regNumber reg2);
453 #ifdef LEGACY_BACKEND
454     void rsTrackRegSwap(regNumber reg1, regNumber reg2);
455     void rsTrackRegAssign(GenTree* op1, GenTree* op2);
456
457     regNumber rsIconIsInReg(ssize_t val, ssize_t* closeDelta = nullptr);
458     bool rsIconIsInReg(ssize_t val, regNumber reg);
459     regNumber rsLclIsInReg(unsigned var);
460     regPairNo rsLclIsInRegPair(unsigned var);
461
462     //---------------------- Load suppression ---------------------------------
463
464     void rsTrashLclLong(unsigned var);
465     void rsTrashLcl(unsigned var);
466 #endif // LEGACY_BACKEND
467     void rsTrashRegSet(regMaskTP regMask);
468 #ifdef LEGACY_BACKEND
469     regMaskTP rsUselessRegs();
470 #endif // LEGACY_BACKEND
471 };
472 #endif // _REGSET_H