diff --git a/compiler/aarch64/codegen/OMRCodeGenerator.cpp b/compiler/aarch64/codegen/OMRCodeGenerator.cpp index d7e4fbe609f..8f486b6fd69 100644 --- a/compiler/aarch64/codegen/OMRCodeGenerator.cpp +++ b/compiler/aarch64/codegen/OMRCodeGenerator.cpp @@ -41,6 +41,121 @@ #include "il/Node_inlines.hpp" #include "il/StaticSymbol.hpp" + +OMR::ARM64::CodeGenerator::CodeGenerator(TR::Compilation *comp) : + OMR::CodeGenerator(comp), + _dataSnippetList(getTypedAllocator(comp->allocator())), + _outOfLineCodeSectionList(getTypedAllocator(comp->allocator())), + _firstTimeLiveOOLRegisterList(NULL) + { + } + +void +OMR::ARM64::CodeGenerator::initialize() + { + self()->OMR::CodeGenerator::initialize(); + + TR::CodeGenerator *cg = self(); + TR::Compilation *comp = self()->comp(); + + // Initialize Linkage for Code Generator + cg->initializeLinkage(); + + _unlatchedRegisterList = + (TR::RealRegister**)cg->trMemory()->allocateHeapMemory(sizeof(TR::RealRegister*)*(TR::RealRegister::NumRegisters + 1)); + + _unlatchedRegisterList[0] = 0; // mark that list is empty + + _linkageProperties = &cg->getLinkage()->getProperties(); + + cg->setStackPointerRegister(cg->machine()->getRealRegister(_linkageProperties->getStackPointerRegister())); + cg->setMethodMetaDataRegister(cg->machine()->getRealRegister(_linkageProperties->getMethodMetaDataRegister())); + + // Tactical GRA settings + // + cg->setGlobalRegisterTable(_linkageProperties->getRegisterAllocationOrder()); + _numGPR = _linkageProperties->getNumAllocatableIntegerRegisters(); + _numFPR = _linkageProperties->getNumAllocatableFloatRegisters(); + cg->setLastGlobalGPR(_numGPR - 1); + cg->setLastGlobalFPR(_numGPR + _numFPR - 1); + + cg->getLinkage()->initARM64RealRegisterLinkage(); + cg->setSupportsGlRegDeps(); + cg->setSupportsGlRegDepOnFirstBlock(); + + cg->addSupportedLiveRegisterKind(TR_GPR); + cg->addSupportedLiveRegisterKind(TR_FPR); + cg->setLiveRegisters(new (cg->trHeapMemory()) TR_LiveRegisters(comp), TR_GPR); + cg->setLiveRegisters(new (cg->trHeapMemory()) TR_LiveRegisters(comp), TR_FPR); + + cg->setSupportsVirtualGuardNOPing(); + + cg->setSupportsRecompilation(); + + cg->setSupportsSelect(); + + _numberBytesReadInaccessible = 0; + _numberBytesWriteInaccessible = 0; + + if (TR::Compiler->vm.hasResumableTrapHandler(comp)) + cg->setHasResumableTrapHandler(); + + if (!comp->getOption(TR_DisableRegisterPressureSimulation)) + { + for (int32_t i = 0; i < TR_numSpillKinds; i++) + _globalRegisterBitVectors[i].init(cg->getNumberOfGlobalRegisters(), cg->trMemory()); + + for (TR_GlobalRegisterNumber grn=0; grn < cg->getNumberOfGlobalRegisters(); grn++) + { + TR::RealRegister::RegNum reg = (TR::RealRegister::RegNum)cg->getGlobalRegister(grn); + if (cg->getFirstGlobalGPR() <= grn && grn <= cg->getLastGlobalGPR()) + _globalRegisterBitVectors[ TR_gprSpill ].set(grn); + else if (cg->getFirstGlobalFPR() <= grn && grn <= cg->getLastGlobalFPR()) + _globalRegisterBitVectors[ TR_fprSpill ].set(grn); + + if (!cg->getProperties().getPreserved(reg)) + _globalRegisterBitVectors[ TR_volatileSpill ].set(grn); + if (cg->getProperties().getIntegerArgument(reg) || cg->getProperties().getFloatArgument(reg)) + _globalRegisterBitVectors[ TR_linkageSpill ].set(grn); + } + } + + // Calculate inverse of getGlobalRegister function + // + TR_GlobalRegisterNumber grn; + int i; + + TR_GlobalRegisterNumber globalRegNumbers[TR::RealRegister::NumRegisters]; + for (i = 0; i < cg->getNumberOfGlobalGPRs(); i++) + { + grn = cg->getFirstGlobalGPR() + i; + globalRegNumbers[cg->getGlobalRegister(grn)] = grn; + } + for (i = 0; i < cg->getNumberOfGlobalFPRs(); i++) + { + grn = cg->getFirstGlobalFPR() + i; + globalRegNumbers[cg->getGlobalRegister(grn)] = grn; + } + + // Initialize linkage reg arrays + TR::ARM64LinkageProperties linkageProperties = cg->getProperties(); + for (i = 0; i < linkageProperties.getNumIntArgRegs(); i++) + _gprLinkageGlobalRegisterNumbers[i] = globalRegNumbers[linkageProperties.getIntegerArgumentRegister(i)]; + for (i = 0; i < linkageProperties.getNumFloatArgRegs(); i++) + _fprLinkageGlobalRegisterNumbers[i] = globalRegNumbers[linkageProperties.getFloatArgumentRegister(i)]; + + if (comp->getOption(TR_TraceRA)) + { + cg->setGPRegisterIterator(new (cg->trHeapMemory()) TR::RegisterIterator(cg->machine(), TR::RealRegister::FirstGPR, TR::RealRegister::LastGPR)); + cg->setFPRegisterIterator(new (cg->trHeapMemory()) TR::RegisterIterator(cg->machine(), TR::RealRegister::FirstFPR, TR::RealRegister::LastFPR)); + } + + cg->getLinkage()->setParameterLinkageRegisterIndex(comp->getJittedMethodSymbol()); + + if (comp->target().isSMP()) + cg->setEnforceStoreOrder(); + } + OMR::ARM64::CodeGenerator::CodeGenerator() : OMR::CodeGenerator(), _dataSnippetList(getTypedAllocator(TR::comp()->allocator())), diff --git a/compiler/aarch64/codegen/OMRCodeGenerator.hpp b/compiler/aarch64/codegen/OMRCodeGenerator.hpp index edfa5134095..e4b51dde3ec 100644 --- a/compiler/aarch64/codegen/OMRCodeGenerator.hpp +++ b/compiler/aarch64/codegen/OMRCodeGenerator.hpp @@ -150,10 +150,16 @@ namespace ARM64 class OMR_EXTENSIBLE CodeGenerator : public OMR::CodeGenerator { - public: +protected: + + CodeGenerator(TR::Compilation *comp); + +public: CodeGenerator(); + void initialize(); + /** * @brief AArch64 hook to begin instruction selection */ @@ -474,7 +480,7 @@ class OMR_EXTENSIBLE CodeGenerator : public OMR::CodeGenerator /** * @brief Returns bit mask for real register * @param[in] reg: real register number - * + * * @return bit mask for real register */ static uint32_t registerBitMask(int32_t reg); diff --git a/compiler/arm/codegen/OMRCodeGenerator.cpp b/compiler/arm/codegen/OMRCodeGenerator.cpp index e30d7d3e309..cdad02c1cb5 100644 --- a/compiler/arm/codegen/OMRCodeGenerator.cpp +++ b/compiler/arm/codegen/OMRCodeGenerator.cpp @@ -73,6 +73,178 @@ TR::Linkage *OMR::ARM::CodeGenerator::createLinkage(TR_LinkageConventions lc) return linkage; } +OMR::ARM::CodeGenerator::CodeGenerator(TR::Compilation *comp) + : OMR::CodeGenerator(comp), + _frameRegister(NULL), + _constantData(NULL), + _outOfLineCodeSectionList(comp->trMemory()), + _internalControlFlowNestingDepth(0), + _internalControlFlowSafeNestingDepth(0) + { + } + +void +OMR::ARM::CodeGenerator::initialize() + { + self()->OMR::CodeGenerator::initialize(); + + TR::CodeGenerator *cg = self(); + TR::Compilation *comp = self()->comp(); + + // Initialize Linkage for Code Generator + cg->initializeLinkage(); + + _unlatchedRegisterList = + (TR::RealRegister**)cg->trMemory()->allocateHeapMemory(sizeof(TR::RealRegister*)*(TR::RealRegister::NumRegisters + 1)); + + _unlatchedRegisterList[0] = 0; // mark that list is empty + + _linkageProperties = &cg->getLinkage()->getProperties(); + _linkageProperties->setEndianness(comp->target().cpu.isBigEndian()); + + if (!comp->getOption(TR_FullSpeedDebug)) + cg->setSupportsDirectJNICalls(); + cg->setSupportsVirtualGuardNOPing(); + + if(comp->target().isLinux()) + { + // only hardhat linux-arm builds have the required gcc soft libraries + // that allow the vm to be compiled with -msoft-float. + // With -msoft-float any floating point return value is placed in gr0 for single precision and + // gr0 and gr1 for double precision. This is where the jit expects the result following a directToJNI call. + // The floating point return value on non-hardhat linux-arm builds is through the coprocessor register f0. + // Therefore the HasHardFloatReturn flag must be set to force generation of instructions to move the result + // from f0 to gr0/gr1 following a directToJNI dispatch. + + #if !defined(HARDHAT) && !defined(__VFP_FP__) // gcc does not support VFP with -mfloat-abi=hard yet + cg->setHasHardFloatReturn(); + #endif + } + + if (!debug("hasFramePointer")) + cg->setFrameRegister(cg->machine()->getRealRegister(_linkageProperties->getStackPointerRegister())); + else + cg->setFrameRegister(cg->machine()->getRealRegister(_linkageProperties->getFramePointerRegister())); + + cg->setMethodMetaDataRegister(cg->machine()->getRealRegister(_linkageProperties->getMethodMetaDataRegister())); + + // Tactical GRA settings +#if 1 // PPC enables below, but seem no longer used? + cg->setGlobalGPRPartitionLimit(TR::Machine::getGlobalGPRPartitionLimit()); + cg->setGlobalFPRPartitionLimit(TR::Machine::getGlobalFPRPartitionLimit()); +#endif + cg->setGlobalRegisterTable(TR::Machine::getGlobalRegisterTable()); + _numGPR = _linkageProperties->getNumAllocatableIntegerRegisters(); + cg->setLastGlobalGPR(TR::Machine::getLastGlobalGPRRegisterNumber()); + cg->setLast8BitGlobalGPR(TR::Machine::getLast8BitGlobalGPRRegisterNumber()); + cg->setLastGlobalFPR(TR::Machine::getLastGlobalFPRRegisterNumber()); + _numFPR = _linkageProperties->getNumAllocatableFloatRegisters(); + + // TODO: Disable FP-GRA since current GRA does not work well with ARM linkage (where Float register usage is limited). + cg->setDisableFpGRA(); + + cg->setSupportsRecompilation(); + + cg->setSupportsGlRegDeps(); + cg->setSupportsGlRegDepOnFirstBlock(); + cg->setPerformsChecksExplicitly(); + cg->setConsiderAllAutosAsTacticalGlobalRegisterCandidates(); + cg->setSupportsScaledIndexAddressing(); + cg->setSupportsAlignedAccessOnly(); + cg->setSupportsPrimitiveArrayCopy(); + cg->setSupportsReferenceArrayCopy(); + cg->setSupportsLoweringConstIDiv(); + cg->setSupportsNewInstanceImplOpt(); + +#ifdef J9_PROJECT_SPECIFIC + cg->setAheadOfTimeCompile(new (cg->trHeapMemory()) TR::AheadOfTimeCompile(cg)); +#endif + cg->getLinkage()->initARMRealRegisterLinkage(); + //To enable this, we must change OMR::ARM::Linkage::saveArguments to support GRA registers + //cg->getLinkage()->setParameterLinkageRegisterIndex(comp->getJittedMethodSymbol()); + + _numberBytesReadInaccessible = 0; + _numberBytesWriteInaccessible = 0; + + cg->setSupportsJavaFloatSemantics(); + cg->setSupportsInliningOfTypeCoersionMethods(); + + if (comp->target().isLinux()) + { + // On AIX and Linux, we are very far away from address + // wrapping-around. + _maxObjectSizeGuaranteedNotToOverflow = 0x10000000; + cg->setSupportsDivCheck(); + if (!comp->getOption(TR_DisableTraps)) + cg->setHasResumableTrapHandler(); + } + else + { + TR_ASSERT(0, "unknown target"); + } + + // Tactical GRA + if (!comp->getOption(TR_DisableRegisterPressureSimulation)) + { + for (int32_t i = 0; i < TR_numSpillKinds; i++) + _globalRegisterBitVectors[i].init(cg->getNumberOfGlobalRegisters(), cg->trMemory()); + + for (TR_GlobalRegisterNumber grn=0; grn < cg->getNumberOfGlobalRegisters(); grn++) + { + TR::RealRegister::RegNum reg = (TR::RealRegister::RegNum)cg->getGlobalRegister(grn); + if (cg->getFirstGlobalGPR() <= grn && grn <= cg->getLastGlobalGPR()) + _globalRegisterBitVectors[ TR_gprSpill ].set(grn); + else if (cg->getFirstGlobalFPR() <= grn && grn <= cg->getLastGlobalFPR()) + _globalRegisterBitVectors[ TR_fprSpill ].set(grn); + + if (!cg->getProperties().getPreserved(reg)) + _globalRegisterBitVectors[ TR_volatileSpill ].set(grn); + if (cg->getProperties().getIntegerArgument(reg) || cg->getProperties().getFloatArgument(reg)) + _globalRegisterBitVectors[ TR_linkageSpill ].set(grn); + } + + } + + // Calculate inverse of getGlobalRegister function + // + TR_GlobalRegisterNumber grn; + int i; + + TR_GlobalRegisterNumber globalRegNumbers[TR::RealRegister::NumRegisters]; + for (i=0; i < cg->getNumberOfGlobalGPRs(); i++) + { + grn = cg->getFirstGlobalGPR() + i; + globalRegNumbers[cg->getGlobalRegister(grn)] = grn; + } + for (i=0; i < cg->getNumberOfGlobalFPRs(); i++) + { + grn = cg->getFirstGlobalFPR() + i; + globalRegNumbers[cg->getGlobalRegister(grn)] = grn; + } + + // Initialize linkage reg arrays + TR::ARMLinkageProperties linkageProperties = cg->getProperties(); + for (i=0; i < linkageProperties.getNumIntArgRegs(); i++) + _gprLinkageGlobalRegisterNumbers[i] = globalRegNumbers[linkageProperties.getIntegerArgumentRegister(i)]; + for (i=0; i < linkageProperties.getNumFloatArgRegs(); i++) + _fprLinkageGlobalRegisterNumbers[i] = globalRegNumbers[linkageProperties.getFloatArgumentRegister(i)]; + + if (comp->getOption(TR_TraceRA)) + { + cg->setGPRegisterIterator(new (cg->trHeapMemory()) TR::RegisterIterator(cg->machine(), TR::RealRegister::FirstGPR, TR::RealRegister::LastGPR)); + cg->setFPRegisterIterator(new (cg->trHeapMemory()) TR::RegisterIterator(cg->machine(), TR::RealRegister::FirstFPR, TR::RealRegister::LastFPR)); + } + + if (!comp->compileRelocatableCode()) + { + cg->setSupportsProfiledInlining(); + } + + // Disable optimizations for max min by default on arm + comp->setOption(TR_DisableMaxMinOptimization); + } + + OMR::ARM::CodeGenerator::CodeGenerator() : OMR::CodeGenerator(), _frameRegister(NULL), diff --git a/compiler/arm/codegen/OMRCodeGenerator.hpp b/compiler/arm/codegen/OMRCodeGenerator.hpp index 63c32ad2bba..4989d934a72 100644 --- a/compiler/arm/codegen/OMRCodeGenerator.hpp +++ b/compiler/arm/codegen/OMRCodeGenerator.hpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2018 IBM Corp. and others + * Copyright (c) 2000, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -112,10 +112,16 @@ class CodeGenerator; class OMR_EXTENSIBLE CodeGenerator : public OMR::CodeGenerator { - public: +protected: + + CodeGenerator(TR::Compilation *comp); + +public: + + CodeGenerator(); + + void initialize(); - CodeGenerator(); /* @@ */ - CodeGenerator(TR::Compilation * comp); TR::Linkage *createLinkage(TR_LinkageConventions lc); void beginInstructionSelection(); diff --git a/compiler/codegen/OMRCodeGenerator.cpp b/compiler/codegen/OMRCodeGenerator.cpp index 2242ba3b63c..841671fd71e 100644 --- a/compiler/codegen/OMRCodeGenerator.cpp +++ b/compiler/codegen/OMRCodeGenerator.cpp @@ -148,6 +148,133 @@ TR::Instruction * OMR::CodeGenerator::generateNop(TR::Node * node, TR::Instruction *instruction, TR_NOPKind nopKind) { TR_ASSERT(0, "shouldn't get here"); return NULL;} + +OMR::CodeGenerator::CodeGenerator(TR::Compilation *comp) : + _compilation(comp), + _trMemory(comp->trMemory()), + _liveLocals(0), + _currentEvaluationTreeTop(0), + _currentEvaluationBlock(0), + _prePrologueSize(0), + _implicitExceptionPoint(0), + _localsThatAreStored(NULL), + _numLocalsWhenStoreAnalysisWasDone(-1), + _ialoadUnneeded(comp->trMemory()), + _symRefTab(comp->getSymRefTab()), + _vmThreadRegister(NULL), + _stackAtlas(NULL), + _methodStackMap(NULL), + _binaryBufferStart(NULL), + _binaryBufferCursor(NULL), + _largestOutgoingArgSize(0), + _estimatedCodeLength(0), + _estimatedSnippetStart(0), + _accumulatedInstructionLengthError(0), + _registerSaveDescription(0), + _extendedToInt64GlobalRegisters(comp->allocator()), + _liveButMaybeUnreferencedLocals(NULL), + _assignedGlobalRegisters(NULL), + _aheadOfTimeCompile(NULL), + _globalRegisterTable(NULL), + _currentGRABlockLiveOutSet(NULL), + _localsIG(NULL), + _lastGlobalGPR(0), + _firstGlobalFPR(0), + _lastGlobalFPR(0), + _firstOverlappedGlobalFPR(0), + _lastOverlappedGlobalFPR(0), + _last8BitGlobalGPR(0), + _globalGPRPartitionLimit(0), + _globalFPRPartitionLimit(0), + _firstInstruction(NULL), + _appendInstruction(NULL), + _firstGlobalVRF(-1), + _lastGlobalVRF(-1), + _firstOverlappedGlobalVRF(-1), + _lastOverlappedGlobalVRF(-1), + _overlapOffsetBetweenFPRandVRFgrns(0), + _supportedLiveRegisterKinds(0), + _blocksWithCalls(NULL), + _codeCache(0), + _committedToCodeCache(false), + _codeCacheSwitched(false), + _blockRegisterPressureCache(NULL), + _simulatedNodeStates(NULL), + _availableSpillTemps(getTypedAllocator(comp->allocator())), + _counterBlocks(getTypedAllocator(comp->allocator())), + _liveReferenceList(getTypedAllocator(comp->allocator())), + _snippetList(getTypedAllocator(comp->allocator())), + _registerArray(comp->trMemory()), + _spill4FreeList(getTypedAllocator(comp->allocator())), + _spill8FreeList(getTypedAllocator(comp->allocator())), + _spill16FreeList(getTypedAllocator(comp->allocator())), + _internalPointerSpillFreeList(getTypedAllocator(comp->allocator())), + _spilledRegisterList(NULL), + _referencedRegistersList(NULL), + _variableSizeSymRefPendingFreeList(getTypedAllocator(comp->allocator())), + _variableSizeSymRefFreeList(getTypedAllocator(comp->allocator())), + _variableSizeSymRefAllocList(getTypedAllocator(comp->allocator())), + _accumulatorNodeUsage(0), + _collectedSpillList(getTypedAllocator(comp->allocator())), + _allSpillList(getTypedAllocator(comp->allocator())), + _relocationList(getTypedAllocator(comp->allocator())), + _externalRelocationList(getTypedAllocator(comp->allocator())), + _staticRelocationList(comp->allocator()), + _preJitMethodEntrySize(0), + _jitMethodEntryPaddingSize(0), + _lastInstructionBeforeCurrentEvaluationTreeTop(NULL), + _unlatchedRegisterList(NULL), + _indentation(2), + _currentBlock(NULL), + _realVMThreadRegister(NULL), + _internalControlFlowNestingDepth(0), + _internalControlFlowSafeNestingDepth(0), + _stackOfArtificiallyInflatedNodes(comp->trMemory(), 16), + _stackOfMemoryReferencesCreatedDuringEvaluation(comp->trMemory(), 16), + randomizer(comp), + _outOfLineColdPathNestedDepth(0), + _codeGenPhase(self()), + _symbolDataTypeMap(comp->allocator()), + _lmmdFailed(false) + { + } + + +void +OMR::CodeGenerator::initialize() + { + TR::CodeGenerator *cg = self(); + TR::Compilation *comp = self()->comp(); + + _machine = new (cg->trHeapMemory()) TR::Machine(cg); + + _disableInternalPointers = comp->getOption(TR_MimicInterpreterFrameShape) || + comp->getOptions()->realTimeGC() || + comp->getOption(TR_DisableInternalPointers); + + uintptr_t maxSize = TR::Compiler->vm.getOverflowSafeAllocSize(comp); + int32_t i; + + for (i = 0; i < NumRegisterKinds; ++i) + { + _liveRegisters[i] = NULL; + _liveRealRegisters[i] = 0; + } + + for (i = 0 ; i < TR_NumLinkages; ++i) + _linkages[i] = NULL; + + _maxObjectSizeGuaranteedNotToOverflow = (maxSize > UINT_MAX) ? UINT_MAX : maxSize; + + if (comp->getDebug()) + { + comp->getDebug()->resetDebugData(); + } + + cg->setIsLeafMethod(); + } + + OMR::CodeGenerator::CodeGenerator() : _compilation(TR::comp()), _trMemory(_compilation->trMemory()), diff --git a/compiler/codegen/OMRCodeGenerator.hpp b/compiler/codegen/OMRCodeGenerator.hpp index 98301b97787..92c0a0a4d3c 100644 --- a/compiler/codegen/OMRCodeGenerator.hpp +++ b/compiler/codegen/OMRCodeGenerator.hpp @@ -246,7 +246,8 @@ namespace OMR class OMR_EXTENSIBLE CodeGenerator { - private: + +private: TR::Compilation *_compilation; TR_Memory *_trMemory; @@ -262,16 +263,28 @@ class OMR_EXTENSIBLE CodeGenerator TR::Instruction *_implicitExceptionPoint; bool areMergeableGuards(TR::Instruction *earlierGuard, TR::Instruction *laterGuard); - protected: +protected: TR_BitVector *_localsThatAreStored; int32_t _numLocalsWhenStoreAnalysisWasDone; List > _ialoadUnneeded; - public: + /** + * @brief Constructor + * + * @param[in] comp \c TR::Compilation object + */ + CodeGenerator(TR::Compilation *comp); + +public: TR_ALLOC(TR_Memory::CodeGenerator) + /** + * @brief Initialize a \c TR::CodeGenerator object + */ + void initialize(); + inline TR::CodeGenerator *self(); TR_StackMemory trStackMemory(); diff --git a/compiler/p/codegen/OMRCodeGenerator.cpp b/compiler/p/codegen/OMRCodeGenerator.cpp index deb2ffc4090..a75561393a1 100644 --- a/compiler/p/codegen/OMRCodeGenerator.cpp +++ b/compiler/p/codegen/OMRCodeGenerator.cpp @@ -107,6 +107,259 @@ #include #endif + +OMR::Power::CodeGenerator::CodeGenerator(TR::Compilation *comp) : + OMR::CodeGenerator(comp), + _stackPtrRegister(NULL), + _constantData(NULL), + _blockCallInfo(NULL), + _transientLongRegisters(comp->trMemory()), + conversionBuffer(NULL), + _outOfLineCodeSectionList(getTypedAllocator(comp->allocator())), + _startPCLabel(NULL) + { + } + + +void +OMR::Power::CodeGenerator::initialize() + { + self()->OMR::CodeGenerator::initialize(); + + TR::CodeGenerator *cg = self(); + TR::Compilation *comp = self()->comp(); + + // Initialize Linkage for Code Generator + cg->initializeLinkage(); + + _unlatchedRegisterList = + (TR::RealRegister**)cg->trMemory()->allocateHeapMemory(sizeof(TR::RealRegister*)*(TR::RealRegister::NumRegisters + 1)); + + _unlatchedRegisterList[0] = 0; // mark that list is empty + + _linkageProperties = &cg->getLinkage()->getProperties(); + + // Set up to collect items for later TOC mapping + if (comp->target().is64Bit()) + { + cg->setTrackStatics(new (cg->trHeapMemory()) TR_Array(cg->trMemory())); + cg->setTrackItems(new (cg->trHeapMemory()) TR_Array(cg->trMemory())); + } + else + { + cg->setTrackStatics(NULL); + cg->setTrackItems(NULL); + } + + cg->setStackPointerRegister(cg->machine()->getRealRegister(_linkageProperties->getNormalStackPointerRegister())); + cg->setMethodMetaDataRegister(cg->machine()->getRealRegister(_linkageProperties->getMethodMetaDataRegister())); + cg->setTOCBaseRegister(cg->machine()->getRealRegister(_linkageProperties->getTOCBaseRegister())); + cg->getLinkage()->initPPCRealRegisterLinkage(); + cg->getLinkage()->setParameterLinkageRegisterIndex(comp->getJittedMethodSymbol()); + cg->machine()->initREGAssociations(); + + // Tactical GRA settings. + // + cg->setGlobalGPRPartitionLimit(TR::Machine::getGlobalGPRPartitionLimit()); + cg->setGlobalFPRPartitionLimit(TR::Machine::getGlobalFPRPartitionLimit()); + cg->setGlobalRegisterTable(_linkageProperties->getRegisterAllocationOrder()); + _numGPR = _linkageProperties->getNumAllocatableIntegerRegisters(); + _firstGPR = 0; + _lastGPR = _numGPR - 1; + _firstParmGPR = _linkageProperties->getFirstAllocatableIntegerArgumentRegister(); + _lastVolatileGPR = _linkageProperties->getLastAllocatableIntegerVolatileRegister(); + _numFPR = _linkageProperties->getNumAllocatableFloatRegisters(); + _firstFPR = _numGPR; + _lastFPR = _firstFPR + _numFPR - 1; + _firstParmFPR = _linkageProperties->getFirstAllocatableFloatArgumentRegister(); + _lastVolatileFPR = _linkageProperties->getLastAllocatableFloatVolatileRegister(); + cg->setLastGlobalGPR(_lastGPR); + cg->setLast8BitGlobalGPR(_lastGPR); + cg->setLastGlobalFPR(_lastFPR); + + _numVRF = _linkageProperties->getNumAllocatableVectorRegisters(); + cg->setFirstGlobalVRF(_lastFPR + 1); + cg->setLastGlobalVRF(_lastFPR + _numVRF); + + cg->setSupportsGlRegDeps(); + cg->setSupportsGlRegDepOnFirstBlock(); + + cg->setSupportsRecompilation(); + + if (comp->target().is32Bit()) + cg->setUsesRegisterPairsForLongs(); + + cg->setPerformsChecksExplicitly(); + cg->setConsiderAllAutosAsTacticalGlobalRegisterCandidates(); + + cg->setEnableRefinedAliasSets(); + + static char * accessStaticsIndirectly = feGetEnv("TR_AccessStaticsIndirectly"); + if (accessStaticsIndirectly) + cg->setAccessStaticsIndirectly(true); + + if (!debug("noLiveRegisters")) + { + cg->addSupportedLiveRegisterKind(TR_GPR); + cg->addSupportedLiveRegisterKind(TR_FPR); + cg->addSupportedLiveRegisterKind(TR_CCR); + cg->addSupportedLiveRegisterKind(TR_VSX_SCALAR); + cg->addSupportedLiveRegisterKind(TR_VSX_VECTOR); + cg->addSupportedLiveRegisterKind(TR_VRF); + + cg->setLiveRegisters(new (cg->trHeapMemory()) TR_LiveRegisters(comp), TR_GPR); + cg->setLiveRegisters(new (cg->trHeapMemory()) TR_LiveRegisters(comp), TR_FPR); + cg->setLiveRegisters(new (cg->trHeapMemory()) TR_LiveRegisters(comp), TR_CCR); + cg->setLiveRegisters(new (cg->trHeapMemory()) TR_LiveRegisters(comp), TR_VRF); + cg->setLiveRegisters(new (cg->trHeapMemory()) TR_LiveRegisters(comp), TR_VSX_SCALAR); + cg->setLiveRegisters(new (cg->trHeapMemory()) TR_LiveRegisters(comp), TR_VSX_VECTOR); + } + + cg->setSupportsConstantOffsetInAddressing(); + cg->setSupportsVirtualGuardNOPing(); + cg->setSupportsPrimitiveArrayCopy(); + cg->setSupportsReferenceArrayCopy(); + cg->setSupportsSelect(); + cg->setSupportsByteswap(); + + // disabled for now + // + if (comp->getOption(TR_AggressiveOpts) && + !comp->getOption(TR_DisableArraySetOpts)) + { + cg->setSupportsArraySet(); + } + cg->setSupportsArrayCmp(); + + if (comp->target().cpu.supportsFeature(OMR_FEATURE_PPC_HAS_VSX)) + { + static bool disablePPCTRTO = (feGetEnv("TR_disablePPCTRTO") != NULL); + static bool disablePPCTRTO255 = (feGetEnv("TR_disablePPCTRTO255") != NULL); + static bool disablePPCTROT = (feGetEnv("TR_disablePPCTROT") != NULL); + static bool disablePPCTROTNoBreak = (feGetEnv("TR_disablePPCTROTNoBreak") != NULL); + + if (!disablePPCTRTO) + cg->setSupportsArrayTranslateTRTO(); +#ifndef __LITTLE_ENDIAN__ + else if (!disablePPCTRTO255) + setSupportsArrayTranslateTRTO255(); +#endif + + if (!disablePPCTROT) + cg->setSupportsArrayTranslateTROT(); + + if (!disablePPCTROTNoBreak) + cg->setSupportsArrayTranslateTROTNoBreak(); + } + + _numberBytesReadInaccessible = 0; + _numberBytesWriteInaccessible = 4096; + + // Poorly named. Not necessarily Java specific. + // + cg->setSupportsJavaFloatSemantics(); + + cg->setSupportsDivCheck(); + cg->setSupportsLoweringConstIDiv(); + if (comp->target().is64Bit()) + cg->setSupportsLoweringConstLDiv(); + cg->setSupportsLoweringConstLDivPower2(); + + static bool disableDCAS = (feGetEnv("TR_DisablePPCDCAS") != NULL); + + if (!disableDCAS && + comp->target().is64Bit() && + TR::Options::useCompressedPointers()) + { + cg->setSupportsDoubleWordCAS(); + cg->setSupportsDoubleWordSet(); + } + + if (cg->is64BitProcessor()) + cg->setSupportsInlinedAtomicLongVolatiles(); + + // Standard allows only offset multiple of 4 + // TODO: either improves the query to be size-based or gets the offset into a register + if (comp->target().is64Bit()) + cg->setSupportsAlignedAccessOnly(); + + // TODO: distinguishing among OOO and non-OOO implementations + if (comp->target().isSMP()) + cg->setEnforceStoreOrder(); + + if (!comp->getOption(TR_DisableTraps) && TR::Compiler->vm.hasResumableTrapHandler(comp)) + cg->setHasResumableTrapHandler(); + + /* + * TODO: TM is currently not compatible with read barriers. If read barriers are required, TM is disabled until the issue is fixed. + * TM is now disabled by default, due to various reasons (OS, hardware, etc), unless it is explicitly enabled. + */ + if (comp->target().cpu.supportsFeature(OMR_FEATURE_PPC_HTM) && comp->getOption(TR_EnableTM) && + !comp->getOption(TR_DisableTM) && TR::Compiler->om.readBarrierType() == gc_modron_readbar_none) + cg->setSupportsTM(); + + if (comp->target().cpu.supportsFeature(OMR_FEATURE_PPC_HAS_ALTIVEC) && comp->target().cpu.supportsFeature(OMR_FEATURE_PPC_HAS_VSX)) + cg->setSupportsAutoSIMD(); + + if (!comp->getOption(TR_DisableRegisterPressureSimulation)) + { + for (int32_t i = 0; i < TR_numSpillKinds; i++) + _globalRegisterBitVectors[i].init(cg->getNumberOfGlobalRegisters(), cg->trMemory()); + + for (TR_GlobalRegisterNumber grn=0; grn < cg->getNumberOfGlobalRegisters(); grn++) + { + TR::RealRegister::RegNum reg = (TR::RealRegister::RegNum)cg->getGlobalRegister(grn); + if (cg->getFirstGlobalGPR() <= grn && grn <= cg->getLastGlobalGPR()) + _globalRegisterBitVectors[ TR_gprSpill ].set(grn); + else if (cg->getFirstGlobalFPR() <= grn && grn <= cg->getLastGlobalFPR()) + _globalRegisterBitVectors[ TR_fprSpill ].set(grn); + + if (!cg->getProperties().getPreserved(reg)) + _globalRegisterBitVectors[ TR_volatileSpill ].set(grn); + if (cg->getProperties().getIntegerArgument(reg) || cg->getProperties().getFloatArgument(reg)) + _globalRegisterBitVectors[ TR_linkageSpill ].set(grn); + } + + } + + // Calculate inverse of getGlobalRegister function + // + TR_GlobalRegisterNumber grn; + int i; + + TR_GlobalRegisterNumber globalRegNumbers[TR::RealRegister::NumRegisters]; + for (i=0; i < cg->getNumberOfGlobalGPRs(); i++) + { + grn = cg->getFirstGlobalGPR() + i; + globalRegNumbers[cg->getGlobalRegister(grn)] = grn; + } + for (i=0; i < cg->getNumberOfGlobalFPRs(); i++) + { + grn = cg->getFirstGlobalFPR() + i; + globalRegNumbers[cg->getGlobalRegister(grn)] = grn; + } + + // Initialize linkage reg arrays + TR::PPCLinkageProperties linkageProperties = cg->getProperties(); + for (i=0; i < linkageProperties.getNumIntArgRegs(); i++) + _gprLinkageGlobalRegisterNumbers[i] = globalRegNumbers[linkageProperties.getIntegerArgumentRegister(i)]; + for (i=0; i < linkageProperties.getNumFloatArgRegs(); i++) + _fprLinkageGlobalRegisterNumbers[i] = globalRegNumbers[linkageProperties.getFloatArgumentRegister(i)]; + + if (comp->getOption(TR_TraceRA)) + { + cg->setGPRegisterIterator(new (cg->trHeapMemory()) TR::RegisterIterator(cg->machine(), TR::RealRegister::FirstGPR, TR::RealRegister::LastGPR)); + cg->setFPRegisterIterator(new (cg->trHeapMemory()) TR::RegisterIterator(cg->machine(), TR::RealRegister::FirstFPR, TR::RealRegister::LastFPR)); + } + + cg->setSupportsProfiledInlining(); + + TR_ResolvedMethod *method = comp->getJittedMethodSymbol()->getResolvedMethod(); + TR_ReturnInfo returnInfo = cg->getLinkage()->getReturnInfoFromReturnType(method->returnType()); + comp->setReturnInfo(returnInfo); + } + + OMR::Power::CodeGenerator::CodeGenerator() : OMR::CodeGenerator(), _stackPtrRegister(NULL), diff --git a/compiler/p/codegen/OMRCodeGenerator.hpp b/compiler/p/codegen/OMRCodeGenerator.hpp index a0d7725deb5..d0cb11aef37 100644 --- a/compiler/p/codegen/OMRCodeGenerator.hpp +++ b/compiler/p/codegen/OMRCodeGenerator.hpp @@ -172,7 +172,7 @@ class CodeGenerator; class OMR_EXTENSIBLE CodeGenerator : public OMR::CodeGenerator { - public: +public: List * conversionBuffer; ListIterator * conversionBufferIt; @@ -180,8 +180,16 @@ class OMR_EXTENSIBLE CodeGenerator : public OMR::CodeGenerator CodeGenerator(); +protected: + + CodeGenerator(TR::Compilation *comp); + +public: + TR::Linkage *createLinkage(TR_LinkageConventions lc); + void initialize(); + static bool supportsTransientPrefetch(); bool is64BitProcessor(); @@ -561,7 +569,6 @@ class OMR_EXTENSIBLE CodeGenerator : public OMR::CodeGenerator DummyLastFlag }; - void initialize(); TR_BitVector *computeCallInfoBitVector(); @@ -619,15 +626,15 @@ class TR_PPCScratchRegisterManager : public TR_ScratchRegisterManager TR::Register *sourceReg, int32_t value, TR::CodeGenerator *cg); - + void mulConstant( TR::Node *, TR::Register *trgReg, TR::Register *sourceReg, int64_t value, TR::CodeGenerator *cg); - - + + TR::Register *addConstantToLong( TR::Node * node, TR::Register *srcReg, @@ -642,7 +649,7 @@ class TR_PPCScratchRegisterManager : public TR_ScratchRegisterManager int32_t valHigh, int32_t valLow, TR::CodeGenerator *cg); - + TR::Register *addConstantToInteger( TR::Node * node, TR::Register *srcReg, diff --git a/compiler/riscv/codegen/OMRCodeGenerator.cpp b/compiler/riscv/codegen/OMRCodeGenerator.cpp index 90c0b00ad8b..2280122336d 100644 --- a/compiler/riscv/codegen/OMRCodeGenerator.cpp +++ b/compiler/riscv/codegen/OMRCodeGenerator.cpp @@ -34,6 +34,101 @@ #include "il/Node.hpp" #include "il/Node_inlines.hpp" +OMR::RV::CodeGenerator::CodeGenerator(TR::Compilation *comp) : + OMR::CodeGenerator(comp), + _constantData(NULL), + _outOfLineCodeSectionList(getTypedAllocator(comp->allocator())) + { + } + +void +OMR::RV::CodeGenerator::initialize() + { + self()->OMR::CodeGenerator::initialize(); + + TR::CodeGenerator *cg = self(); + TR::Compilation *comp = self()->comp(); + + // Initialize Linkage for Code Generator + cg->initializeLinkage(); + + _unlatchedRegisterList = + (TR::RealRegister**)cg->trMemory()->allocateHeapMemory(sizeof(TR::RealRegister*)*(TR::RealRegister::NumRegisters + 1)); + + _unlatchedRegisterList[0] = 0; // mark that list is empty + + _linkageProperties = &cg->getLinkage()->getProperties(); + + cg->setStackPointerRegister(cg->machine()->getRealRegister(_linkageProperties->getStackPointerRegister())); + cg->setMethodMetaDataRegister(cg->machine()->getRealRegister(_linkageProperties->getMethodMetaDataRegister())); + + // Tactical GRA settings + // + cg->setGlobalRegisterTable(TR::Machine::getGlobalRegisterTable()); + _numGPR = _linkageProperties->getNumAllocatableIntegerRegisters(); + _numFPR = _linkageProperties->getNumAllocatableFloatRegisters(); + cg->setLastGlobalGPR(TR::Machine::getLastGlobalGPRRegisterNumber()); + cg->setLastGlobalFPR(TR::Machine::getLastGlobalFPRRegisterNumber()); + + cg->getLinkage()->initRVRealRegisterLinkage(); + + _numberBytesReadInaccessible = 0; + _numberBytesWriteInaccessible = 0; + + if (TR::Compiler->vm.hasResumableTrapHandler(comp)) + cg->setHasResumableTrapHandler(); + + if (!comp->getOption(TR_DisableRegisterPressureSimulation)) + { + for (int32_t i = 0; i < TR_numSpillKinds; i++) + _globalRegisterBitVectors[i].init(cg->getNumberOfGlobalRegisters(), cg->trMemory()); + + for (TR_GlobalRegisterNumber grn=0; grn < cg->getNumberOfGlobalRegisters(); grn++) + { + TR::RealRegister::RegNum reg = (TR::RealRegister::RegNum)cg->getGlobalRegister(grn); + if (cg->getFirstGlobalGPR() <= grn && grn <= cg->getLastGlobalGPR()) + _globalRegisterBitVectors[ TR_gprSpill ].set(grn); + else if (cg->getFirstGlobalFPR() <= grn && grn <= cg->getLastGlobalFPR()) + _globalRegisterBitVectors[ TR_fprSpill ].set(grn); + + if (!cg->getProperties().getPreserved(reg)) + _globalRegisterBitVectors[ TR_volatileSpill ].set(grn); + if (cg->getProperties().getIntegerArgument(reg) || cg->getProperties().getFloatArgument(reg)) + _globalRegisterBitVectors[ TR_linkageSpill ].set(grn); + } + } + + // Calculate inverse of getGlobalRegister function + // + TR_GlobalRegisterNumber grn; + int i; + + TR_GlobalRegisterNumber globalRegNumbers[TR::RealRegister::NumRegisters]; + for (i = 0; i < cg->getNumberOfGlobalGPRs(); i++) + { + grn = cg->getFirstGlobalGPR() + i; + globalRegNumbers[cg->getGlobalRegister(grn)] = grn; + } + for (i = 0; i < cg->getNumberOfGlobalFPRs(); i++) + { + grn = cg->getFirstGlobalFPR() + i; + globalRegNumbers[cg->getGlobalRegister(grn)] = grn; + } + + // Initialize linkage reg arrays + TR::RVLinkageProperties linkageProperties = cg->getProperties(); + for (i = 0; i < linkageProperties.getNumIntArgRegs(); i++) + _gprLinkageGlobalRegisterNumbers[i] = globalRegNumbers[linkageProperties.getIntegerArgumentRegister(i)]; + for (i = 0; i < linkageProperties.getNumFloatArgRegs(); i++) + _fprLinkageGlobalRegisterNumbers[i] = globalRegNumbers[linkageProperties.getFloatArgumentRegister(i)]; + + if (comp->getOption(TR_TraceRA)) + { + cg->setGPRegisterIterator(new (cg->trHeapMemory()) TR::RegisterIterator(cg->machine(), TR::RealRegister::FirstGPR, TR::RealRegister::LastGPR)); + cg->setFPRegisterIterator(new (cg->trHeapMemory()) TR::RegisterIterator(cg->machine(), TR::RealRegister::FirstFPR, TR::RealRegister::LastFPR)); + } + } + OMR::RV::CodeGenerator::CodeGenerator() : OMR::CodeGenerator(), _constantData(NULL), @@ -455,7 +550,7 @@ void OMR::RV::CodeGenerator::apply16BitLabelRelativeRelocation(int32_t *cursor, *cursor |= ENCODE_SBTYPE_IMM(distance); } -void OMR::RV::CodeGenerator::apply16BitLabelRelativeRelocation(int32_t *cursor, TR::LabelSymbol *label, int8_t d, bool isInstrOffset) +void OMR::RV::CodeGenerator::apply16BitLabelRelativeRelocation(int32_t *cursor, TR::LabelSymbol *label, int8_t d, bool isInstrOffset) { apply16BitLabelRelativeRelocation(cursor, label); } @@ -477,13 +572,13 @@ void OMR::RV::CodeGenerator::apply32BitLabelRelativeRelocation(int32_t *cursor, } int64_t OMR::RV::CodeGenerator::getLargestNegConstThatMustBeMaterialized() - { - TR_ASSERT(0, "Not Implemented on AArch64"); - return 0; + { + TR_ASSERT(0, "Not Implemented on AArch64"); + return 0; } int64_t OMR::RV::CodeGenerator::getSmallestPosConstThatMustBeMaterialized() - { - TR_ASSERT(0, "Not Implemented on AArch64"); - return 0; + { + TR_ASSERT(0, "Not Implemented on AArch64"); + return 0; } diff --git a/compiler/riscv/codegen/OMRCodeGenerator.hpp b/compiler/riscv/codegen/OMRCodeGenerator.hpp index d4240c7df24..0a5e0e77b47 100644 --- a/compiler/riscv/codegen/OMRCodeGenerator.hpp +++ b/compiler/riscv/codegen/OMRCodeGenerator.hpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019, 2019 IBM Corp. and others + * Copyright (c) 2019, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -70,10 +70,16 @@ namespace RV class OMR_EXTENSIBLE CodeGenerator : public OMR::CodeGenerator { - public: +protected: + + CodeGenerator(TR::Compilation *comp); + +public: CodeGenerator(); + initialize(); + /** * @brief AArch64 hook to begin instruction selection */ diff --git a/compiler/x/amd64/codegen/OMRCodeGenerator.cpp b/compiler/x/amd64/codegen/OMRCodeGenerator.cpp index 81d3ab08eaf..4d9f39e85ea 100644 --- a/compiler/x/amd64/codegen/OMRCodeGenerator.cpp +++ b/compiler/x/amd64/codegen/OMRCodeGenerator.cpp @@ -45,6 +45,94 @@ #include "infra/BitVector.hpp" #include "x/codegen/X86Ops.hpp" + +OMR::X86::AMD64::CodeGenerator::CodeGenerator(TR::Compilation *comp) : + OMR::X86::CodeGenerator(comp) + { + } + + +void OMR::X86::AMD64::CodeGenerator::initialize() + { + self()->OMR::X86::CodeGenerator::initialize(); + + TR::CodeGenerator *cg = self(); + TR::Compilation *comp = self()->comp(); + + if (comp->getOption(TR_DisableTraps)) + { + _numberBytesReadInaccessible = 0; + _numberBytesWriteInaccessible = 0; + } + else + { + _numberBytesReadInaccessible = 4096; + _numberBytesWriteInaccessible = 4096; + cg->setHasResumableTrapHandler(); + cg->setEnableImplicitDivideCheck(); + } + + cg->setSupportsDivCheck(); + + static char *c = feGetEnv("TR_disableAMD64ValueProfiling"); + if (c) + comp->setOption(TR_DisableValueProfiling); + + static char *accessStaticsIndirectly = feGetEnv("TR_AccessStaticsIndirectly"); + if (accessStaticsIndirectly) + cg->setAccessStaticsIndirectly(true); + + cg->setSupportsDoubleWordCAS(); + cg->setSupportsDoubleWordSet(); + + cg->setSupportsGlRegDepOnFirstBlock(); + cg->setConsiderAllAutosAsTacticalGlobalRegisterCandidates(); + + // Interpreter frame shape requires all autos to occupy an 8-byte slot on 64-bit. + // + if (comp->getOption(TR_MimicInterpreterFrameShape)) + cg->setMapAutosTo8ByteSlots(); + + // Common X86 initialization + // + cg->initializeX86(comp); + + cg->initLinkageToGlobalRegisterMap(); + + cg->setRealVMThreadRegister(cg->machine()->getRealRegister(TR::RealRegister::ebp)); + + // GRA-related initialization is done after calling initializeX86() so we can + // use such things as getNumberOfGlobal[FG]PRs(). + + _globalGPRsPreservedAcrossCalls.init(cg->getNumberOfGlobalRegisters(), cg->trMemory()); + _globalFPRsPreservedAcrossCalls.init(cg->getNumberOfGlobalRegisters(), cg->trMemory()); + + int16_t i; + TR_GlobalRegisterNumber grn; + for (i=0; i < cg->getNumberOfGlobalGPRs(); i++) + { + grn = cg->getFirstGlobalGPR() + i; + if (cg->getProperties().isPreservedRegister((TR::RealRegister::RegNum)cg->getGlobalRegister(grn))) + _globalGPRsPreservedAcrossCalls.set(grn); + } + for (i=0; i < cg->getNumberOfGlobalFPRs(); i++) + { + grn = cg->getFirstGlobalFPR() + i; + if (cg->getProperties().isPreservedRegister((TR::RealRegister::RegNum)cg->getGlobalRegister(grn))) + _globalFPRsPreservedAcrossCalls.set(grn); + } + + // Reduce the maxObjectSizeGuaranteedNotToOverflow value on 64-bit such that the + // runtime comparison does not sign extend (saves an instruction on array allocations). + // INT_MAX should be sufficiently large. + // + if ((uint32_t)_maxObjectSizeGuaranteedNotToOverflow > (uint32_t)INT_MAX) + { + _maxObjectSizeGuaranteedNotToOverflow = (uint32_t)INT_MAX; + } + } + + OMR::X86::AMD64::CodeGenerator::CodeGenerator() : OMR::X86::CodeGenerator() { diff --git a/compiler/x/amd64/codegen/OMRCodeGenerator.hpp b/compiler/x/amd64/codegen/OMRCodeGenerator.hpp index 1ef59a18e29..fe3d88a4e38 100644 --- a/compiler/x/amd64/codegen/OMRCodeGenerator.hpp +++ b/compiler/x/amd64/codegen/OMRCodeGenerator.hpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2019 IBM Corp. and others + * Copyright (c) 2000, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -52,7 +52,14 @@ namespace AMD64 class OMR_EXTENSIBLE CodeGenerator : public OMR::X86::CodeGenerator { - public: + +protected: + + CodeGenerator(TR::Compilation *comp); + +public: + + void initialize(); CodeGenerator(); diff --git a/compiler/x/codegen/OMRCodeGenerator.cpp b/compiler/x/codegen/OMRCodeGenerator.cpp index 610944c84d5..916bdba29a2 100644 --- a/compiler/x/codegen/OMRCodeGenerator.cpp +++ b/compiler/x/codegen/OMRCodeGenerator.cpp @@ -509,6 +509,34 @@ OMR::X86::CodeGenerator::initializeX86(TR::Compilation *comp) } +OMR::X86::CodeGenerator::CodeGenerator(TR::Compilation *comp) : + OMR::CodeGenerator(comp), + _nanoTimeTemp(NULL), + _assignmentDirection(Backward), + _lastCatchAppendInstruction(NULL), + _betterSpillPlacements(NULL), + _dataSnippetList(getTypedAllocator(comp->allocator())), + _spilledIntRegisters(getTypedAllocator(comp->allocator())), + _liveDiscardableRegisters(getTypedAllocator(comp->allocator())), + _dependentDiscardableRegisters(getTypedAllocator(comp->allocator())), + _clobberingInstructions(getTypedAllocator(comp->allocator())), + _outlinedInstructionsList(getTypedAllocator(comp->allocator())), + _numReservedIPICTrampolines(0), + _flags(0) + { + _clobIterator = _clobberingInstructions.begin(); + } + + +void +OMR::X86::CodeGenerator::initialize() + { + self()->OMR::CodeGenerator::initialize(); + + _clobIterator = _clobberingInstructions.begin(); + } + + OMR::X86::CodeGenerator::CodeGenerator() : OMR::CodeGenerator(), _nanoTimeTemp(NULL), diff --git a/compiler/x/codegen/OMRCodeGenerator.hpp b/compiler/x/codegen/OMRCodeGenerator.hpp index 6f162f4b4e6..276cacc35f8 100644 --- a/compiler/x/codegen/OMRCodeGenerator.hpp +++ b/compiler/x/codegen/OMRCodeGenerator.hpp @@ -675,7 +675,11 @@ class OMR_EXTENSIBLE CodeGenerator : public OMR::CodeGenerator */ bool directCallRequiresTrampoline(intptr_t targetAddress, intptr_t sourceAddress); - protected: + void initialize(); + +protected: + + CodeGenerator(TR::Compilation *comp); CodeGenerator(); diff --git a/compiler/x/i386/codegen/OMRCodeGenerator.cpp b/compiler/x/i386/codegen/OMRCodeGenerator.cpp index 4801ca0ed31..6e5a77e87e5 100644 --- a/compiler/x/i386/codegen/OMRCodeGenerator.cpp +++ b/compiler/x/i386/codegen/OMRCodeGenerator.cpp @@ -57,6 +57,83 @@ #include "x/codegen/X86Instruction.hpp" #include "x/codegen/X86Ops.hpp" + +OMR::X86::I386::CodeGenerator::CodeGenerator(TR::Compilation *comp) : + OMR::X86::CodeGenerator(comp) + { + } + + +void +OMR::X86::I386::CodeGenerator::initialize() + { + self()->OMR::X86::CodeGenerator::initialize(); + + TR::CodeGenerator *cg = self(); + TR::Compilation *comp = self()->comp(); + + // Common X86 initialization + // + cg->initializeX86(comp); + + cg->setUsesRegisterPairsForLongs(); + + if (debug("supportsArrayTranslateAndTest")) + cg->setSupportsArrayTranslateAndTest(); + if (debug("supportsArrayCmp")) + cg->setSupportsArrayCmp(); + + cg->setSupportsDoubleWordCAS(); + cg->setSupportsDoubleWordSet(); + + if (comp->target().isWindows()) + { + if (comp->getOption(TR_DisableTraps)) + { + _numberBytesReadInaccessible = 0; + _numberBytesWriteInaccessible = 0; + } + else + { + _numberBytesReadInaccessible = 4096; + _numberBytesWriteInaccessible = 4096; + cg->setHasResumableTrapHandler(); + cg->setEnableImplicitDivideCheck(); + } + cg->setSupportsDivCheck(); + cg->setJNILinkageCalleeCleanup(); + cg->setRealVMThreadRegister(cg->machine()->getRealRegister(TR::RealRegister::ebp)); + } + else if (comp->target().isLinux()) + { + if (comp->getOption(TR_DisableTraps)) + { + _numberBytesReadInaccessible = 0; + _numberBytesWriteInaccessible = 0; + } + else + { + _numberBytesReadInaccessible = 4096; + _numberBytesWriteInaccessible = 4096; + cg->setHasResumableTrapHandler(); + cg->setEnableImplicitDivideCheck(); + } + cg->setRealVMThreadRegister(cg->machine()->getRealRegister(TR::RealRegister::ebp)); + cg->setSupportsDivCheck(); + } + else + { + TR_ASSERT(0, "unknown target"); + } + + cg->setSupportsInlinedAtomicLongVolatiles(); + + static char *dontConsiderAllAutosForGRA = feGetEnv("TR_dontConsiderAllAutosForGRA"); + if (!dontConsiderAllAutosForGRA) + cg->setConsiderAllAutosAsTacticalGlobalRegisterCandidates(); + } + + OMR::X86::I386::CodeGenerator::CodeGenerator() : OMR::X86::CodeGenerator() { diff --git a/compiler/x/i386/codegen/OMRCodeGenerator.hpp b/compiler/x/i386/codegen/OMRCodeGenerator.hpp index 87f6eea59fe..8f25cc2ede8 100644 --- a/compiler/x/i386/codegen/OMRCodeGenerator.hpp +++ b/compiler/x/i386/codegen/OMRCodeGenerator.hpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2019 IBM Corp. and others + * Copyright (c) 2000, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -54,7 +54,13 @@ namespace I386 class OMR_EXTENSIBLE CodeGenerator : public OMR::X86::CodeGenerator { - public: +protected: + + CodeGenerator(TR::Compilation *comp); + +public: + + void initialize(); CodeGenerator(); diff --git a/compiler/z/codegen/OMRCodeGenerator.cpp b/compiler/z/codegen/OMRCodeGenerator.cpp index c83477c6f4d..f2a6057c795 100644 --- a/compiler/z/codegen/OMRCodeGenerator.cpp +++ b/compiler/z/codegen/OMRCodeGenerator.cpp @@ -394,6 +394,230 @@ bool OMR::Z::CodeGenerator::supportsDirectIntegralLoadStoresFromLiteralPool() return true; } +OMR::Z::CodeGenerator::CodeGenerator(TR::Compilation *comp) + : OMR::CodeGenerator(comp), + _extentOfLitPool(-1), + _recompPatchInsnList(getTypedAllocator(comp->allocator())), + _constantHash(comp->allocator()), + _constantHashCur(_constantHash), + _constantList(getTypedAllocator(comp->allocator())), + _writableList(getTypedAllocator(comp->allocator())), + _transientLongRegisters(comp->trMemory()), + _snippetDataList(getTypedAllocator(comp->allocator())), + _outOfLineCodeSectionList(getTypedAllocator(comp->allocator())), + _returnTypeInfoInstruction(NULL), + _interfaceSnippetToPICsListHashTab(NULL), + _currentCheckNode(NULL), + _currentBCDCHKHandlerLabel(NULL), + _nodesToBeEvaluatedInRegPairs(comp->allocator()), + _ccInstruction(NULL), + _previouslyAssignedTo(comp->allocator("LocalRA")), + _firstTimeLiveOOLRegisterList(NULL), + _methodBegin(NULL), + _methodEnd(NULL), + _afterRA(false) + { + } + +void +OMR::Z::CodeGenerator::initialize() + { + self()->OMR::CodeGenerator::initialize(); + + TR::CodeGenerator *cg = self(); + TR::Compilation *comp = self()->comp(); + + _cgFlags = 0; + + // Initialize Linkage for Code Generator + cg->initializeLinkage(); + + _unlatchedRegisterList = (TR::RealRegister**)cg->trMemory()->allocateHeapMemory(sizeof(TR::RealRegister*)*(TR::RealRegister::NumRegisters)); + _unlatchedRegisterList[0] = 0; // mark that list is empty + + bool enableBranchPreload = comp->getOption(TR_EnableBranchPreload); + bool disableBranchPreload = comp->getOption(TR_DisableBranchPreload); + + if (enableBranchPreload || (!disableBranchPreload && comp->isOptServer() && comp->target().cpu.isAtLeast(OMR_PROCESSOR_S390_ZEC12))) + cg->setEnableBranchPreload(); + else + cg->setDisableBranchPreload(); + + static bool bpp = (feGetEnv("TR_BPRP")!=NULL); + + if ((enableBranchPreload && bpp) || (bpp && !disableBranchPreload && comp->isOptServer() && comp->target().cpu.isAtLeast(OMR_PROCESSOR_S390_ZEC12))) + cg->setEnableBranchPreloadForCalls(); + else + cg->setDisableBranchPreloadForCalls(); + + if (cg->supportsBranchPreloadForCalls()) + { + _callsForPreloadList = new (cg->trHeapMemory()) TR::list(getTypedAllocator(comp->allocator())); + } + + cg->setOnDemandLiteralPoolRun(true); + cg->setGlobalStaticBaseRegisterOn(false); + + cg->setGlobalPrivateStaticBaseRegisterOn(false); + + cg->setMultiplyIsDestructive(); + + cg->setSupportsSelect(); + + cg->setSupportsByteswap(); + + cg->setIsOutOfLineHotPath(false); + + cg->setUsesRegisterPairsForLongs(); + cg->setSupportsDivCheck(); + cg->setSupportsLoweringConstIDiv(); + cg->setSupportsTestUnderMask(); + + // Initialize to be 8 bytes for bodyInfo / methodInfo + cg->setPreJitMethodEntrySize(8); + + // Support divided by power of 2 logic in ldivSimplifier + cg->setSupportsLoweringConstLDivPower2(); + + //enable LM/STM for volatile longs in 32 bit + cg->setSupportsInlinedAtomicLongVolatiles(); + + cg->setSupportsConstantOffsetInAddressing(); + + static char * noVGNOP = feGetEnv("TR_NOVGNOP"); + if (noVGNOP == NULL) + { + cg->setSupportsVirtualGuardNOPing(); + } + if (!comp->getOption(TR_DisableArraySetOpts)) + { + cg->setSupportsArraySet(); + } + cg->setSupportsArrayCmp(); + cg->setSupportsArrayCmpSign(); + if (!comp->compileRelocatableCode()) + { + cg->setSupportsArrayTranslateTRxx(); + } + + cg->setSupportsTestCharComparisonControl(); // TRXX instructions on Danu have mask to disable test char comparison. + cg->setSupportsReverseLoadAndStore(); + cg->setSupportsSearchCharString(); // CISC Transformation into SRSTU loop - only on z9. + cg->setSupportsTranslateAndTestCharString(); // CISC Transformation into TRTE loop - only on z6. + + if (!comp->getOption(TR_DisableTraps) && TR::Compiler->vm.hasResumableTrapHandler(comp)) + { + cg->setHasResumableTrapHandler(); + } + + if (comp->target().cpu.isAtLeast(OMR_PROCESSOR_S390_Z196)) + { + cg->setSupportsAtomicLoadAndAdd(); + } + else + { + // Max min optimization uses the maxMinHelper evaluator which + // requires conditional loads that are not supported below z196 + comp->setOption(TR_DisableMaxMinOptimization); + } + + if (comp->target().cpu.isAtLeast(OMR_PROCESSOR_S390_ZEC12)) + { + cg->setSupportsZonedDFPConversions(); + if (comp->target().cpu.supportsFeature(OMR_FEATURE_S390_TE) && !comp->getOption(TR_DisableTM)) + cg->setSupportsTM(); + } + + if (comp->target().cpu.isAtLeast(OMR_PROCESSOR_S390_Z13) && !comp->getOption(TR_DisableArch11PackedToDFP)) + cg->setSupportsFastPackedDFPConversions(); + + if (!comp->target().cpu.isAtLeast(OMR_PROCESSOR_S390_Z14)) + { + comp->setOption(TR_DisableVectorBCD); + } + + // Be pessimistic until we can prove we don't exit after doing code-generation + cg->setExitPointsInMethod(true); + +#ifdef DEBUG + // Clear internal counters for internal profiling of + // register allocation + cg->clearTotalSpills(); + cg->clearTotalRegisterXfers(); + cg->clearTotalRegisterMoves(); +#endif + + // Set up vector register support for machine after zEC12. + // This should also happen before prepareForGRA + if (comp->getOption(TR_DisableSIMD)) + { + comp->setOption(TR_DisableAutoSIMD); + comp->setOption(TR_DisableSIMDArrayCompare); + comp->setOption(TR_DisableSIMDArrayTranslate); + comp->setOption(TR_DisableSIMDUTF16BEEncoder); + comp->setOption(TR_DisableSIMDUTF16LEEncoder); + comp->setOption(TR_DisableSIMDStringHashCode); + comp->setOption(TR_DisableVectorRegGRA); + } + + cg->setSupportsRecompilation(); + + // This enables the tactical GRA + cg->setSupportsGlRegDeps(); + + cg->addSupportedLiveRegisterKind(TR_GPR); + cg->addSupportedLiveRegisterKind(TR_FPR); + cg->addSupportedLiveRegisterKind(TR_VRF); + + cg->setLiveRegisters(new (cg->trHeapMemory()) TR_LiveRegisters(comp), TR_GPR); + cg->setLiveRegisters(new (cg->trHeapMemory()) TR_LiveRegisters(comp), TR_FPR); + cg->setLiveRegisters(new (cg->trHeapMemory()) TR_LiveRegisters(comp), TR_VRF); + + cg->setSupportsPrimitiveArrayCopy(); + cg->setSupportsReferenceArrayCopy(); + + cg->setSupportsPartialInlineOfMethodHooks(); + + cg->setSupportsInliningOfTypeCoersionMethods(); + + cg->setPerformsChecksExplicitly(); + + _numberBytesReadInaccessible = 4096; + _numberBytesWriteInaccessible = 4096; + + // zLinux sTR requires this as well, otherwise cp00f054.C testcase fails in TR_FPStoreReloadElimination. + cg->setSupportsJavaFloatSemantics(); + + _localF2ISpill = NULL; + _localD2LSpill = NULL; + + _nextAvailableBlockIndex = -1; + _currentBlockIndex = -1; + + if (comp->getOption(TR_TraceRA)) + { + cg->setGPRegisterIterator(new (cg->trHeapMemory()) TR::RegisterIterator(cg->machine(), TR::RealRegister::FirstGPR, TR::RealRegister::LastAssignableGPR)); + cg->setFPRegisterIterator(new (cg->trHeapMemory()) TR::RegisterIterator(cg->machine(), TR::RealRegister::FirstFPR, TR::RealRegister::LastFPR)); + cg->setVRFRegisterIterator(new (cg->trHeapMemory()) TR::RegisterIterator(cg->machine(), TR::RealRegister::FirstVRF, TR::RealRegister::LastVRF)); + } + + if (!comp->getOption(TR_DisableTLHPrefetch) && !comp->compileRelocatableCode()) + { + cg->setEnableTLHPrefetching(); + } + + _reusableTempSlot = NULL; + cg->freeReusableTempSlot(); + + cg->setSupportsProfiledInlining(); + + cg->getS390Linkage()->setParameterLinkageRegisterIndex(comp->getJittedMethodSymbol()); + + cg->getS390Linkage()->initS390RealRegisterLinkage(); + cg->setAccessStaticsIndirectly(true); + } + + OMR::Z::CodeGenerator::CodeGenerator() : OMR::CodeGenerator(), _extentOfLitPool(-1), diff --git a/compiler/z/codegen/OMRCodeGenerator.hpp b/compiler/z/codegen/OMRCodeGenerator.hpp index 71efd16fe7e..40ca7535666 100644 --- a/compiler/z/codegen/OMRCodeGenerator.hpp +++ b/compiler/z/codegen/OMRCodeGenerator.hpp @@ -259,7 +259,16 @@ class OMR_EXTENSIBLE CodeGenerator : public OMR::CodeGenerator void lowerTreesPropagateBlockToNode(TR::Node *node); +protected: + + CodeGenerator(TR::Compilation *comp); + +public: + CodeGenerator(); + + void initialize(); + TR::Linkage *createLinkage(TR_LinkageConventions lc); bool anyNonConstantSnippets();