if ((regsToFree | delayRegsToFree) != RBM_NONE)
{
- bool doFreeRegs = false;
// Free at a new location, or at a basic block boundary
- if (currentLocation > prevLocation || refType == RefTypeBB)
+ if (refType == RefTypeBB)
{
- doFreeRegs = true;
+ assert(currentLocation > prevLocation);
}
-
- if (doFreeRegs)
+ if (currentLocation > prevLocation)
{
freeRegisters(regsToFree);
+ if ((currentLocation > (prevLocation + 1)) && (delayRegsToFree != RBM_NONE))
+ {
+ // We should never see a delayReg that is delayed until a Location that has no RefPosition
+ // (that would be the RefPosition that it was supposed to interfere with).
+ assert(!"Found a delayRegFree associated with Location with no reference");
+ // However, to be cautious for the Release build case, we will free them.
+ freeRegisters(delayRegsToFree);
+ delayRegsToFree = RBM_NONE;
+ }
regsToFree = delayRegsToFree;
delayRegsToFree = RBM_NONE;
}
// it may be used used multiple during retries
assert(!tree->gtOp.gtOp1->isContained());
LocationInfoListNode* op1Info = getLocationInfo(tree->gtOp.gtOp1);
- op1Info->info.isDelayFree = true;
useList.Append(op1Info);
+ LocationInfoListNode* op2Info = nullptr;
if (!tree->gtOp.gtOp2->isContained())
{
- LocationInfoListNode* op2Info = getLocationInfo(tree->gtOp.gtOp2);
- op2Info->info.isDelayFree = true;
+ op2Info = getLocationInfo(tree->gtOp.gtOp2);
useList.Append(op2Info);
}
- info->hasDelayFreeSrc = true;
-
- // Internals may not collide with target
- info->isInternalRegDelayFree = true;
+ if (info->dstCount != 0)
+ {
+ op1Info->info.isDelayFree = true;
+ if (op2Info != nullptr)
+ {
+ op2Info->info.isDelayFree = true;
+ }
+ // Internals may not collide with target
+ info->isInternalRegDelayFree = true;
+ info->hasDelayFreeSrc = true;
+ }
}
break;
// Is this a non-commutative operator, or is op2 a contained memory op?
// In either case, we need to make op2 remain live until the op is complete, by marking
- // the source(s) associated with op2 as "delayFree".
+ // the source(s) associated with op2 as "delayFree" if this node defines a register.
// Note that if op2 of a binary RMW operator is a memory op, even if the operator
// is commutative, codegen cannot reverse them.
// TODO-XArch-CQ: This is not actually the case for all RMW binary operators, but there's
delayUseSrc = op1;
}
- else if ((op2 != nullptr) && (!tree->OperIsCommutative() || (op2->isContained() && !op2->IsCnsIntOrI())))
+ else if ((info->dstCount != 0) && (op2 != nullptr) &&
+ (!tree->OperIsCommutative() || (op2->isContained() && !op2->IsCnsIntOrI())))
{
delayUseSrc = op2;
}