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.
6 // NOTE: The code in this file is only used for LEGACY_BACKEND compiles.
19 #if FEATURE_STACK_FP_X87
20 regMaskTP RegSet::rsGetMaskUsed()
22 return rsMaskUsedFloat;
24 regMaskTP RegSet::rsGetMaskVars()
26 return rsMaskRegVarFloat;
28 regMaskTP RegSet::rsGetMaskLock()
30 return rsMaskLockedFloat;
32 regMaskTP RegSet::rsGetMaskMult()
37 void RegSet::rsSetMaskUsed(regMaskTP maskUsed)
39 rsMaskUsedFloat = maskUsed;
41 void RegSet::rsSetMaskVars(regMaskTP maskVars)
43 rsMaskRegVarFloat = maskVars;
45 void RegSet::rsSetMaskLock(regMaskTP maskLock)
47 rsMaskLockedFloat = maskLock;
50 void RegSet::rsSetUsedTree(regNumber regNum, GenTree* tree)
52 assert(genUsedRegsFloat[regNum] == 0);
53 genUsedRegsFloat[regNum] = tree;
55 void RegSet::rsFreeUsedTree(regNumber regNum, GenTree* tree)
57 assert(genUsedRegsFloat[regNum] == tree);
58 genUsedRegsFloat[regNum] = 0;
61 #else // !FEATURE_STACK_FP_X87
62 regMaskTP RegSet::rsGetMaskUsed()
66 regMaskTP RegSet::rsGetMaskVars()
70 regMaskTP RegSet::rsGetMaskLock()
74 regMaskTP RegSet::rsGetMaskMult()
79 void RegSet::rsSetMaskUsed(regMaskTP maskUsed)
81 rsMaskUsed = maskUsed;
83 void RegSet::rsSetMaskVars(regMaskTP maskVars)
85 rsMaskVars = maskVars;
87 void RegSet::rsSetMaskLock(regMaskTP maskLock)
89 rsMaskLock = maskLock;
92 void RegSet::rsSetUsedTree(regNumber regNum, GenTree* tree)
94 assert(rsUsedTree[regNum] == 0);
95 rsUsedTree[regNum] = tree;
97 void RegSet::rsFreeUsedTree(regNumber regNum, GenTree* tree)
99 assert(rsUsedTree[regNum] == tree);
100 rsUsedTree[regNum] = 0;
102 #endif // !FEATURE_STACK_FP_X87
104 // float stress mode. Will lock out registers to stress high register pressure.
105 // This implies setting interferences in register allocator and pushing regs in
106 // the prolog and popping them before a ret.
108 int CodeGenInterface::genStressFloat()
110 return compiler->compStressCompile(Compiler::STRESS_FLATFP, 40) ? 1 : JitConfig.JitStressFP();
114 regMaskTP RegSet::RegFreeFloat()
116 regMaskTP mask = RBM_ALLFLOAT;
117 #if FEATURE_FP_REGALLOC
118 mask &= m_rsCompiler->raConfigRestrictMaskFP();
121 mask &= ~rsGetMaskUsed();
122 mask &= ~rsGetMaskLock();
123 mask &= ~rsGetMaskVars();
126 if (m_rsCompiler->codeGen->genStressFloat())
128 mask &= ~(m_rsCompiler->codeGen->genStressLockedMaskFloat());
135 // order registers are picked
136 // go in reverse order to minimize chance of spilling with calls
137 static const regNumber pickOrder[] = {REG_F15, REG_F14, REG_F13, REG_F12, REG_F11, REG_F10, REG_F9, REG_F8,
138 REG_F7, REG_F6, REG_F5, REG_F4, REG_F3, REG_F2, REG_F1, REG_F0,
140 REG_F16, REG_F17, REG_F18, REG_F19, REG_F20, REG_F21, REG_F22, REG_F23,
141 REG_F24, REG_F25, REG_F26, REG_F27, REG_F28, REG_F29, REG_F30, REG_F31};
144 // order registers are picked
145 static const regNumber pickOrder[] = {REG_XMM0, REG_XMM1, REG_XMM2, REG_XMM3, REG_XMM4, REG_XMM5,
146 REG_XMM6, REG_XMM7, REG_XMM8, REG_XMM9, REG_XMM10, REG_XMM11,
147 REG_XMM12, REG_XMM13, REG_XMM14, REG_XMM15};
150 // order registers are picked
151 static const regNumber pickOrder[] = {REG_FPV0, REG_FPV1, REG_FPV2, REG_FPV3, REG_FPV4, REG_FPV5, REG_FPV6, REG_FPV7};
154 // picks a reg other than the one specified
155 regNumber RegSet::PickRegFloatOtherThan(GenTree* tree, var_types type, regNumber reg)
157 return PickRegFloatOtherThan(type, reg);
160 regNumber RegSet::PickRegFloatOtherThan(var_types type, regNumber reg)
162 RegisterPreference pref(RBM_ALLFLOAT ^ genRegMask(reg), 0);
163 return PickRegFloat(type, &pref);
166 regNumber RegSet::PickRegFloat(GenTree* tree, var_types type, RegisterPreference* pref, bool bUsed)
168 return PickRegFloat(type, pref, bUsed);
171 regNumber RegSet::PickRegFloat(var_types type, RegisterPreference* pref, bool bUsed)
173 regMaskTP wantedMask;
177 regNumber reg = REG_NA;
185 wantedMask = pref->best;
191 wantedMask = pref->ok;
197 wantedMask = RBM_ALLFLOAT;
202 // better not have asked for a non-fp register
203 assert((wantedMask & ~RBM_ALLFLOAT) == 0);
205 regMaskTP availMask = RegFreeFloat();
206 regMaskTP OKmask = availMask & wantedMask;
212 // the pref->best mask doesn't work so try the pref->ok mask next
218 // Allow used registers to be picked
219 OKmask |= rsGetMaskUsed() & ~rsGetMaskLock();
223 #if FEATURE_FP_REGALLOC
224 regMaskTP restrictMask = (m_rsCompiler->raConfigRestrictMaskFP() | RBM_FLT_CALLEE_TRASH);
227 for (unsigned i = 0; i < ArrLen(pickOrder); i++)
229 regNumber r = pickOrder[i];
230 if (!floatRegCanHoldType(r, type))
233 regMaskTP mask = genRegMaskFloat(r, type);
235 #if FEATURE_FP_REGALLOC
236 if ((mask & restrictMask) != mask)
239 if ((OKmask & mask) == mask)
248 // We couldn't find a register using tryBest
252 assert(!"Unable to find a free FP virtual register");
253 NO_WAY("FP register allocator was too optimistic!");
258 m_rsCompiler->codeGen->SpillFloat(reg);
261 #if FEATURE_FP_REGALLOC
262 rsSetRegsModified(genRegMaskFloat(reg, type));
268 #ifdef LEGACY_BACKEND
269 void RegSet::SetUsedRegFloat(GenTree* tree, bool bValue)
271 /* The value must be sitting in a register */
273 assert(tree->InReg());
275 var_types type = tree->TypeGet();
277 if (type == TYP_STRUCT)
279 assert(m_rsCompiler->IsHfa(tree));
283 regNumber regNum = tree->gtRegNum;
284 regMaskTP regMask = genRegMaskFloat(regNum, type);
289 if (m_rsCompiler->verbose)
291 printf("\t\t\t\t\t\t\tThe register %s currently holds ", getRegNameFloat(regNum, type));
292 Compiler::printTreeID(tree);
298 assert((rsGetMaskLock() & regMask) == 0);
300 #if FEATURE_STACK_FP_X87
301 assert((rsGetMaskUsed() & regMask) == 0);
303 /* Is the register used by two different values simultaneously? */
305 if (regMask & rsGetMaskUsed())
307 /* Save the preceding use information */
309 rsRecMultiReg(regNum, type);
312 /* Set the register's bit in the 'used' bitset */
314 rsSetMaskUsed((rsGetMaskUsed() | regMask));
317 rsSetUsedTree(regNum, tree);
322 if (m_rsCompiler->verbose)
324 printf("\t\t\t\t\t\t\tThe register %s no longer holds ", getRegNameFloat(regNum, type));
325 Compiler::printTreeID(tree);
331 assert((rsGetMaskUsed() & regMask) == regMask);
333 // Are we freeing a multi-use registers?
335 if (regMask & rsGetMaskMult())
337 // Free any multi-use registers
338 rsMultRegFree(regMask);
342 rsSetMaskUsed((rsGetMaskUsed() & ~regMask));
345 rsFreeUsedTree(regNum, tree);
348 #endif // LEGACY_BACKEND
350 void RegSet::SetLockedRegFloat(GenTree* tree, bool bValue)
352 regNumber reg = tree->gtRegNum;
353 var_types type = tree->TypeGet();
354 assert(varTypeIsFloating(type));
355 regMaskTP regMask = genRegMaskFloat(reg, tree->TypeGet());
359 JITDUMP("locking register %s\n", getRegNameFloat(reg, type));
361 assert((rsGetMaskUsed() & regMask) == regMask);
362 assert((rsGetMaskLock() & regMask) == 0);
364 rsSetMaskLock((rsGetMaskLock() | regMask));
368 JITDUMP("unlocking register %s\n", getRegNameFloat(reg, type));
370 assert((rsGetMaskUsed() & regMask) == regMask);
371 assert((rsGetMaskLock() & regMask) == regMask);
373 rsSetMaskLock((rsGetMaskLock() & ~regMask));
377 bool RegSet::IsLockedRegFloat(GenTree* tree)
379 /* The value must be sitting in a register */
381 assert(tree->InReg());
382 assert(varTypeIsFloating(tree->TypeGet()));
384 regMaskTP regMask = genRegMaskFloat(tree->gtRegNum, tree->TypeGet());
385 return (rsGetMaskLock() & regMask) == regMask;
388 void CodeGen::UnspillFloat(GenTree* tree)
393 printf("UnspillFloat() for tree ");
394 Compiler::printTreeID(tree);
399 RegSet::SpillDsc* cur = regSet.rsSpillFloat;
402 while (cur->spillTree != tree)
403 cur = cur->spillNext;
408 void CodeGen::UnspillFloat(LclVarDsc* varDsc)
410 JITDUMP("UnspillFloat() for var [%08p]\n", dspPtr(varDsc));
412 RegSet::SpillDsc* cur = regSet.rsSpillFloat;
415 while (cur->spillVarDsc != varDsc)
416 cur = cur->spillNext;
421 void CodeGen::RemoveSpillDsc(RegSet::SpillDsc* spillDsc)
423 RegSet::SpillDsc* cur;
424 RegSet::SpillDsc** prev;
426 for (cur = regSet.rsSpillFloat, prev = ®Set.rsSpillFloat; cur != spillDsc;
427 prev = &cur->spillNext, cur = cur->spillNext)
432 // Remove node from list
433 *prev = cur->spillNext;
436 void CodeGen::UnspillFloat(RegSet::SpillDsc* spillDsc)
438 JITDUMP("UnspillFloat() for SpillDsc [%08p]\n", dspPtr(spillDsc));
440 RemoveSpillDsc(spillDsc);
441 UnspillFloatMachineDep(spillDsc);
443 RegSet::SpillDsc::freeDsc(®Set, spillDsc);
444 compiler->tmpRlsTemp(spillDsc->spillTemp);
447 #if FEATURE_STACK_FP_X87
449 Compiler::fgWalkResult CodeGen::genRegVarDiesInSubTreeWorker(GenTree** pTree, Compiler::fgWalkData* data)
451 GenTree* tree = *pTree;
452 genRegVarDiesInSubTreeData* pData = (genRegVarDiesInSubTreeData*)data->pCallbackData;
454 // if it's dying, just rename the register, else load it normally
455 if (tree->IsRegVar() && tree->IsRegVarDeath() && tree->gtRegVar.gtRegNum == pData->reg)
457 pData->result = true;
458 return Compiler::WALK_ABORT;
461 return Compiler::WALK_CONTINUE;
464 bool CodeGen::genRegVarDiesInSubTree(GenTree* tree, regNumber reg)
466 genRegVarDiesInSubTreeData Data;
470 compiler->fgWalkTreePre(&tree, genRegVarDiesInSubTreeWorker, (void*)&Data);
475 #endif // FEATURE_STACK_FP_X87
477 /*****************************************************************************
479 * Force floating point expression results to memory, to get rid of the extra
480 * 80 byte "temp-real" precision.
481 * Assumes the tree operand has been computed to the top of the stack.
482 * If type!=TYP_UNDEF, that is the desired presicion, else it is op->gtType
485 void CodeGen::genRoundFpExpression(GenTree* op, var_types type)
487 #if FEATURE_STACK_FP_X87
488 return genRoundFpExpressionStackFP(op, type);
490 return genRoundFloatExpression(op, type);
494 void CodeGen::genCodeForTreeFloat(GenTree* tree, regMaskTP needReg, regMaskTP bestReg)
496 RegSet::RegisterPreference pref(needReg, bestReg);
497 genCodeForTreeFloat(tree, &pref);
500 #endif // LEGACY_BACKEND