void TR_LoadExtensions::flagPreferredLoadExtensions(TR::Node* parent) { if (isSupportedType(parent) && parent->getOpCode().isConversion()) { TR::Node* child = parent->getFirstChild(); bool canSkipConversion = false; if (isSupportedType(child)) { if (parent->getSize() == child->getSize()) { TR::DebugCounter::incStaticDebugCounter(comp(), TR::DebugCounter::debugCounterName(comp(), "codegen/LoadExtensions/success/unneededConversion/%s", comp()->signature())); parent->setUnneededConversion(true); } else { TR::ILOpCode& childOpCode = child->getOpCode(); if (childOpCode.isLoadReg() && !(parent->getSize() > 4 && TR::Compiler->target.is32Bit()) && excludedNodes->count(parent) == 0) { TR::Node* useRegLoad = child; TR_UseDefInfo* useDefInfo = optimizer()->getUseDefInfo(); if (useDefInfo != NULL && useDefInfo->infoIsValid() && useRegLoad->getUseDefIndex() != 0 && useDefInfo->isUseIndex(useRegLoad->getUseDefIndex() != 0)) { TR_UseDefInfo::BitVector info(comp()->allocator()); if (useDefInfo->getUseDef(info, useRegLoad->getUseDefIndex())) { TR_UseDefInfo::BitVector::Cursor cursor(info); int32_t firstDefIndex = useDefInfo->getFirstRealDefIndex(); int32_t firstUseIndex = useDefInfo->getFirstUseIndex(); canSkipConversion = true; bool forceExtensionOnAnyLoads = false; bool forceExtensionOnAllLoads = true; for (cursor.SetToFirstOne(); cursor.Valid() && canSkipConversion; cursor.SetToNextOne()) { int32_t defIndex = cursor; // We've examined all the defs of this particular use if (defIndex >= firstUseIndex) { break; } // Do not consider defs that correspond to method arguments as we cannot force extension on those if (defIndex < firstDefIndex) { continue; } TR::Node* defRegLoad = useDefInfo->getNode(defIndex); if (defRegLoad != NULL) { TR::Node* defRegLoadChild = defRegLoad->getFirstChild(); bool forceExtension = false; canSkipConversion = TR_LoadExtensions::canSkipConversion(parent, defRegLoadChild, forceExtension); forceExtensionOnAnyLoads |= forceExtension; forceExtensionOnAllLoads &= forceExtension; // If we have to force extension on any loads which feed a def of this use ensure we must also // force extension on all such loads. Conversely the conversion can be skipped if none of the // loads feeding the def of this use need to be extended. This ensures either all loads feeding // into defs of this use should be extended or none of them. canSkipConversion &= forceExtensionOnAllLoads == forceExtensionOnAnyLoads; if (trace()) { traceMsg(comp(), "\t\tPeeked through %s [%p] and found %s [%p] with child %s [%p] - conversion %s be skipped\n", useRegLoad->getOpCode().getName(), useRegLoad, defRegLoad->getOpCode().getName(), defRegLoad, defRegLoadChild->getOpCode().getName(), defRegLoadChild, canSkipConversion ? "can" : "cannot"); } } } if (canSkipConversion && performTransformation(comp(), "%sSkipping conversion %s [%p] after RegLoad\n", optDetailString(), parent->getOpCode().getName(), parent)) { TR::DebugCounter::incStaticDebugCounter(comp(), TR::DebugCounter::debugCounterName(comp(), "codegen/LoadExtensions/success/unneededConversion/GRA/%s", comp()->signature())); parent->setUnneededConversion(true); if (forceExtensionOnAllLoads) { TR_UseDefInfo::BitVector info(comp()->allocator()); if (useDefInfo->getUseDef(info, useRegLoad->getUseDefIndex())) { TR_UseDefInfo::BitVector::Cursor cursor(info); for (cursor.SetToFirstOne(); cursor.Valid(); cursor.SetToNextOne()) { int32_t defIndex = cursor; // We've examined all the defs of this particular use if (defIndex >= firstUseIndex) { break; } // Do not consider defs that correspond to method arguments as we cannot force extension on those if (defIndex < firstDefIndex) { continue; } TR::Node *defRegLoad = useDefInfo->getNode(defIndex); if (defRegLoad != NULL) { TR::Node* defRegLoadChild = defRegLoad->getFirstChild(); const int32_t preference = getExtensionPreference(defRegLoadChild); if (preference > 0) { if (trace()) { traceMsg(comp(), "\t\t\tForcing sign extension on %s [%p]\n", defRegLoadChild->getOpCode().getName(), defRegLoadChild); } if (parent->getSize() == 8 || parent->useSignExtensionMode()) { defRegLoadChild->setSignExtendTo64BitAtSource(true); } else { defRegLoadChild->setSignExtendTo32BitAtSource(true); } } if (preference < 0) { if (trace()) { traceMsg(comp(), "\t\t\tForcing zero extension on %s [%p]\n", defRegLoadChild->getOpCode().getName(), defRegLoadChild); } if (parent->getSize() == 8 || parent->useSignExtensionMode()) { defRegLoadChild->setZeroExtendTo64BitAtSource(true); } else { defRegLoadChild->setZeroExtendTo32BitAtSource(true); } } } } } } if (parent->getType().isInt64() && parent->getSize() > child->getSize()) { if (trace()) { traceMsg(comp(), "\t\t\tSet global register %s in getExtendedToInt64GlobalRegisters for child %s [%p] with parent node %s [%p]\n", comp()->getDebug()->getGlobalRegisterName(child->getGlobalRegisterNumber()), child->getOpCode().getName(), child, parent->getOpCode().getName(), parent); } // getExtendedToInt64GlobalRegisters is used by the evaluators to force a larger virtual register to be used when // evaluating the regload so any instructions generated by local RA are the correct size to preserve the upper bits cg()->getExtendedToInt64GlobalRegisters()[child->getGlobalRegisterNumber()] = true; } } } } } } } if (!canSkipConversion) { bool forceExtension = false; canSkipConversion = TR_LoadExtensions::canSkipConversion(parent, child, forceExtension); if (canSkipConversion && performTransformation(comp(), "%sSkipping conversion %s [%p]\n", optDetailString(), parent->getOpCode().getName(), parent)) { TR::DebugCounter::incStaticDebugCounter(comp(), TR::DebugCounter::debugCounterName(comp(), "codegen/LoadExtensions/success/unneededConversion/%s", comp()->signature())); parent->setUnneededConversion(true); if (forceExtension) { const int32_t preference = getExtensionPreference(child); if (preference > 0) { if (trace()) { traceMsg(comp(), "\t\t\tForcing sign extension on %s [%p]\n", child->getOpCode().getName(), child); } if (parent->getSize() == 8 || parent->useSignExtensionMode()) { child->setSignExtendTo64BitAtSource(true); } else { child->setSignExtendTo32BitAtSource(true); } } if (preference < 0) { if (trace()) { traceMsg(comp(), "\t\t\tForcing zero extension on %s [%p]\n", child->getOpCode().getName(), child); } if (parent->getSize() == 8 || parent->useSignExtensionMode()) { child->setZeroExtendTo64BitAtSource(true); } else { child->setZeroExtendTo32BitAtSource(true); } } } } } } }