Skip to content

Commit

Permalink
AArch64: Add ScratchRegisterDependencyConditions class
Browse files Browse the repository at this point in the history
This commit adds TR_ARM64ScratchRegisterDependencyConditions class
which is a convenience class to temporarily hold register dependencies.

Signed-off-by: Akira Saitoh <saiaki@jp.ibm.com>
  • Loading branch information
Akira Saitoh committed May 12, 2021
1 parent 092787c commit a08cfb8
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 1 deletion.
91 changes: 91 additions & 0 deletions compiler/aarch64/codegen/OMRRegisterDependency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -622,3 +622,94 @@ OMR::ARM64::RegisterDependencyConditions::stopUsingDepRegs(TR::CodeGenerator *cg
if (_postConditions != NULL)
_postConditions->stopUsingDepRegs(_addCursorForPost, ret1, ret2, cg);
}

void TR_ARM64ScratchRegisterDependencyConditions::addDependency(TR::CodeGenerator *cg, TR::Register *vr, TR::RealRegister::RegNum rr, uint8_t flag)
{
TR_ASSERT_FATAL(_numGPRDeps < TR::RealRegister::LastAssignableGPR - TR::RealRegister::FirstGPR + 1, "Too many GPR dependencies");

bool isGPR = rr <= TR::RealRegister::LastAssignableGPR;
TR_ASSERT_FATAL(isGPR, "Expecting GPR only");
if (!vr)
{
vr = cg->allocateRegister(TR_GPR);
cg->stopUsingRegister(vr);
}
_gprDeps[_numGPRDeps].setRegister(vr);
_gprDeps[_numGPRDeps].assignFlags(flag);
_gprDeps[_numGPRDeps].setRealRegister(rr);
++_numGPRDeps;
}

void TR_ARM64ScratchRegisterDependencyConditions::unionDependency(TR::CodeGenerator *cg, TR::Register *vr, TR::RealRegister::RegNum rr, uint8_t flag)
{
TR_ASSERT_FATAL(_numGPRDeps < TR::RealRegister::LastAssignableGPR - TR::RealRegister::FirstGPR + 1, "Too many GPR dependencies");

bool isGPR = rr <= TR::RealRegister::LastAssignableGPR;
TR_ASSERT_FATAL(isGPR, "Expecting GPR only");
TR_ASSERT_FATAL(vr, "Expecting non-null virtual register");

for (int i = 0; i < _numGPRDeps; i++)
{
if (_gprDeps[i].getRegister() == vr)
{
// Keep the stronger of the two constraints
//
TR::RealRegister::RegNum min = std::min(rr, _gprDeps[i].getRealRegister());
TR::RealRegister::RegNum max = std::max(rr, _gprDeps[i].getRealRegister());
if (min == TR::RealRegister::NoReg)
{
// Anything is stronger than NoReg
_gprDeps[i].setRegister(vr);
_gprDeps[i].assignFlags(flag);
_gprDeps[i].setRealRegister(max);
}
else
{
TR_ASSERT_FATAL(min == max, "Specific register dependency is only compatible with itself");
// Nothing to do
}
return;
}
}

// vr is not in the deps list, add a new one
_gprDeps[_numGPRDeps].setRegister(vr);
_gprDeps[_numGPRDeps].assignFlags(flag);
_gprDeps[_numGPRDeps].setRealRegister(rr);
++_numGPRDeps;
}

void TR_ARM64ScratchRegisterDependencyConditions::addScratchRegisters(TR::CodeGenerator *cg, TR_ARM64ScratchRegisterManager *srm)
{
auto list = srm->getManagedScratchRegisterList();
ListIterator<TR_ManagedScratchRegister> iterator(&list);
TR_ManagedScratchRegister *msr = iterator.getFirst();

while (msr)
{
unionDependency(cg, msr->_reg, TR::RealRegister::NoReg);
msr = iterator.getNext();
}
}

TR::RegisterDependencyConditions* TR_ARM64ScratchRegisterDependencyConditions::createDependencyConditions(TR::CodeGenerator *cg,
TR_ARM64ScratchRegisterDependencyConditions *pre,
TR_ARM64ScratchRegisterDependencyConditions *post)
{
int32_t preCount = pre ? pre->getNumberOfDependencies() : 0;
int32_t postCount = post ? post->getNumberOfDependencies() : 0;

TR::RegisterDependencyConditions *dependencies = new (cg->trHeapMemory()) TR::RegisterDependencyConditions(preCount,
postCount,
cg->trMemory());
for (int i = 0; i < (pre ? pre->_numGPRDeps : 0); ++i)
{
dependencies->addPreCondition(pre->_gprDeps[i].getRegister(), pre->_gprDeps[i].getRealRegister(), pre->_gprDeps[i].getFlags());
}
for (int i = 0; i < (post ? post->_numGPRDeps : 0); ++i)
{
dependencies->addPostCondition(post->_gprDeps[i].getRegister(), post->_gprDeps[i].getRealRegister(), post->_gprDeps[i].getFlags());
}

return dependencies;
}
73 changes: 72 additions & 1 deletion compiler/aarch64/codegen/OMRRegisterDependency.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018, 2020 IBM Corp. and others
* Copyright (c) 2018, 2021 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
Expand Down Expand Up @@ -301,4 +301,75 @@ class RegisterDependencyConditions: public OMR::RegisterDependencyConditions
} // ARM64
} // OMR

// Convenience class to temporarily hold register dependencies.
// This class allocates space for the maximum number of GPR dependencies that an evaluator can use
// and therefore frees you from trying to determine ahead of time how many dependencies you need.
// It can create a TR::RegisterDependencyConditions object with exactly the number of dependencies currently defined.
// Therefore, objects of this class should be stack allocated so that they'll automatically be freed when no longer
// needed.
//
class TR_ARM64ScratchRegisterDependencyConditions
{
public:
// NOTE:
// No TR_Memory type defined for this class
// since current is as a stack-alloc'd object.
// To heap-alloc, update the class def with something like:
// TR_ALLOC(TR_Memory::PPCScratchRegisterDependencyConditions)

TR_ARM64ScratchRegisterDependencyConditions() : _numGPRDeps(0) {}

uint32_t getNumberOfDependencies() { return _numGPRDeps; }

/**
* @brief Add a new dependency
*
* @param[in] cg: code generator
* @param[in] vr: virtual register
* @param[in] rr: real register
* @param[in] flag: flag
*
*/
void addDependency(TR::CodeGenerator *cg, TR::Register *vr, TR::RealRegister::RegNum rr, uint8_t flag = UsesDependentRegister);

/**
* @brief Takes union of current dependencies and specified register
*
* @details If the virtual register is not in the current dependencies, simply add it to the dependencies.
* Otherwise, if either of real register (one specified as a parameter and one in the dependencies) is NoReg,
* overwrite the dependency of the virtual register with the stronger real register.
*
* @param[in] cg: code generator
* @param[in] vr: virtual register
* @param[in] rr: real register
* @param[in] flag: flag
*
*/
void unionDependency(TR::CodeGenerator *cg, TR::Register *vr, TR::RealRegister::RegNum rr, uint8_t flag = UsesDependentRegister);

/**
* @brief Takes union of current dependencies and each scratch register in the scratch register manager, using NoReg as real regisgter.
*
* @param[in] cg: code generator
* @param[in] srm: scratch register manager
*/
void addScratchRegisters(TR::CodeGenerator *cg, TR_ARM64ScratchRegisterManager *srm);

/**
* @brief Creates dependency conditions from the scratch register dependency conditions
*
* @param[in] cg: code generator
* @param[in] pre: scratch register dependency conditions for pre conditions
* @param[in] post: scratch register dependency conditions for post conditions
*
*/
static TR::RegisterDependencyConditions* createDependencyConditions(TR::CodeGenerator *cg,
TR_ARM64ScratchRegisterDependencyConditions *pre,
TR_ARM64ScratchRegisterDependencyConditions *post);

private:
uint32_t _numGPRDeps;
TR::RegisterDependency _gprDeps[TR::RealRegister::LastAssignableGPR - TR::RealRegister::FirstGPR + 1];
};

#endif

0 comments on commit a08cfb8

Please sign in to comment.