Skip to content

Commit

Permalink
Merge pull request eclipse-omr#1798 from 0dvictor/atomics
Browse files Browse the repository at this point in the history
Standardized Atomic Memory Update Helpers
  • Loading branch information
0xdaryl authored Dec 20, 2017
2 parents 3352a87 + dfc6637 commit 52a544b
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 67 deletions.
45 changes: 9 additions & 36 deletions compiler/ilgen/IlBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1779,68 +1779,41 @@ IlBuilder::genCall(TR::SymbolReference *methodSymRef, int32_t numArgs, TR::IlVal
return NULL;
}


/** \brief
* The service is used to atomically increase memory location [\p baseAddress + \p offset] by amount of \p value.
* The service is used to atomically increase memory location \p baseAddress by amount of \p value.
*
* \param value
* The amount to increase for the memory location.
*
*
* \note
* This service currently only supports Int32/Int64.
* This service currently only supports Int32/Int64.
*
* \return
* The old value at the location [\p baseAddress + \p offset].
* The old value at the location \p baseAddress.
*/
TR::IlValue *
IlBuilder::AtomicAddWithOffset(TR::IlValue * baseAddress, TR::IlValue * offset, TR::IlValue * value)
IlBuilder::AtomicAdd(TR::IlValue * baseAddress, TR::IlValue * value)
{
TR_ASSERT(comp()->cg()->supportsAtomicAdd(), "this platform doesn't support AtomicAdd() yet");
TR_ASSERT(baseAddress->getDataType() == TR::Address, "baseAddress must be TR::Address");
TR_ASSERT(offset == NULL || offset->getDataType() == TR::Int32 || offset->getDataType() == TR::Int64, "offset must be TR::Int32/64 or NULL");

//Determine the implementation type and returnType by detecting "value"'s type
TR::DataType returnType = value->getDataType();
TR_ASSERT(returnType == TR::Int32 || (returnType == TR::Int64 && TR::Compiler->target.is64Bit()), "AtomicAdd currently only supports Int32/64 values");
TraceIL("IlBuilder[ %p ]::AtomicAddWithOffset (%d, %d, %d)\n", this, baseAddress->getID(), offset == NULL ? 0 : offset->getID(), value->getID());
TraceIL("IlBuilder[ %p ]::AtomicAdd(%d, %d)\n", this, baseAddress->getID(), value->getID());

OMR::SymbolReferenceTable::CommonNonhelperSymbol atomicBitSymbol = returnType == TR::Int32 ? TR::SymbolReferenceTable::atomicAdd32BitSymbol : TR::SymbolReferenceTable::atomicAdd64BitSymbol;//lock add
TR::SymbolReference *methodSymRef = symRefTab()->findOrCreateCodeGenInlinedHelper(atomicBitSymbol);
TR::Node *callNode;
//Evaluator will handle if it's (baseAddress+offset) or baseAddress based on the number of children the call node have
callNode = TR::Node::createWithSymRef(TR::ILOpCode::getDirectCall(returnType), offset == NULL ? 2 : 3, methodSymRef);
callNode = TR::Node::createWithSymRef(TR::ILOpCode::getDirectCall(returnType), 2, methodSymRef);
callNode->setAndIncChild(0, loadValue(baseAddress));
if (offset == NULL)
{
callNode->setAndIncChild(1, loadValue(value));
}
else
{
callNode->setAndIncChild(1, loadValue(offset));
callNode->setAndIncChild(2, loadValue(value));
}
callNode->setAndIncChild(1, loadValue(value));

TR::IlValue *returnValue = newValue(callNode->getDataType(), callNode);
return returnValue;
}

/** \brief
* The service is used to atomically increase memory location \p baseAddress by amount of \p value.
*
* \param value
* The amount to increase for the memory location.
*
* \note
* This service currently only supports Int32/Int64.
*
* \return
* The old value at the location \p baseAddress.
*/
TR::IlValue *
IlBuilder::AtomicAdd(TR::IlValue * baseAddress, TR::IlValue * value)
{
return AtomicAddWithOffset(baseAddress, NULL, value);
}


/**
* \brief
Expand Down
1 change: 0 additions & 1 deletion compiler/ilgen/IlBuilder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,6 @@ class IlBuilder : public TR::IlInjector
TR::IlValue *LoadIndirect(const char *type, const char *field, TR::IlValue *object);
void StoreIndirect(const char *type, const char *field, TR::IlValue *object, TR::IlValue *value);
TR::IlValue *IndexAt(TR::IlType *dt, TR::IlValue *base, TR::IlValue *index);
TR::IlValue *AtomicAddWithOffset(TR::IlValue *baseAddress, TR::IlValue *offset, TR::IlValue *value);
TR::IlValue *AtomicAdd(TR::IlValue *baseAddress, TR::IlValue * value);
void Transaction(TR::IlBuilder **persistentFailureBuilder, TR::IlBuilder **transientFailureBuilder, TR::IlBuilder **fallThroughBuilder);
void TransactionAbort();
Expand Down
48 changes: 19 additions & 29 deletions compiler/x/codegen/OMRTreeEvaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4848,30 +4848,20 @@ static TR::Register * inlineSinglePrecisionSQRT(TR::Node *node, TR::CodeGenerato
return node->getRegister();
}

TR::Register* OMR::X86::TreeEvaluator::performSimpleAtomicMemoryUpdate(TR::Node* node, int8_t size, TR_X86OpCodes op, TR::CodeGenerator* cg)
TR::Register* OMR::X86::TreeEvaluator::performSimpleAtomicMemoryUpdate(TR::Node* node, TR_X86OpCodes op, TR::CodeGenerator* cg)
{
// There are two versions of native exchange helpers:
// 2 nodes: exchange with [address]
// 3 nodes: exchange with [address+offset]
TR::Register* object = cg->evaluate(node->getFirstChild());
TR::Register* offset = node->getNumChildren() == 2 ? NULL : cg->evaluate(node->getSecondChild());
TR::Register* value = TR::TreeEvaluator::intOrLongClobberEvaluate(node->getLastChild(), size == 8, cg);
// Assume that the offset is positive and not pathologically large (i.e., > 2^31).
if (offset && TR::Compiler->target.is32Bit() && size == 8)
{
offset = offset->getLowOrder();
}

generateMemRegInstruction(op, node, generateX86MemoryReference(object, offset, 0, cg), value, cg);

node->setRegister(value);

// Clean up children nodes
for (uint16_t i = 0; i < node->getNumChildren(); i++)
{
cg->decReferenceCount(node->getChild(i));
}
return value;
TR_ASSERT((!TR_X86OpCode(op).hasLongSource() && !TR_X86OpCode(op).hasLongTarget()) || TR::Compiler->target.is64Bit(), "64-bit instruction not supported on IA32");
TR::Register* address = cg->evaluate(node->getChild(0));
TR::Register* value = cg->evaluate(node->getChild(1));
TR::Register* result = cg->allocateRegister();

generateRegRegInstruction(MOVRegReg(), node, result, value, cg);
generateMemRegInstruction(op, node, generateX86MemoryReference(address, 0, cg), value, cg);

node->setRegister(result);
cg->decReferenceCount(node->getChild(0));
cg->decReferenceCount(node->getChild(1));
return result;
}

// TR::icall, TR::acall, TR::lcall, TR::fcall, TR::dcall, TR::call handled by directCallEvaluator
Expand All @@ -4889,27 +4879,27 @@ TR::Register *OMR::X86::TreeEvaluator::directCallEvaluator(TR::Node *node, TR::C
{
if (comp->getSymRefTab()->isNonHelper(SymRef, TR::SymbolReferenceTable::atomicAdd32BitSymbol))
{
return TR::TreeEvaluator::performSimpleAtomicMemoryUpdate(node, 4, LADD4MemReg, cg);
return TR::TreeEvaluator::performSimpleAtomicMemoryUpdate(node, LADD4MemReg, cg);
}
if (comp->getSymRefTab()->isNonHelper(SymRef, TR::SymbolReferenceTable::atomicAdd64BitSymbol))
{
return TR::TreeEvaluator::performSimpleAtomicMemoryUpdate(node, 8, LADD8MemReg, cg);
return TR::TreeEvaluator::performSimpleAtomicMemoryUpdate(node, LADD8MemReg, cg);
}
if (comp->getSymRefTab()->isNonHelper(SymRef, TR::SymbolReferenceTable::atomicFetchAndAdd32BitSymbol))
{
return TR::TreeEvaluator::performSimpleAtomicMemoryUpdate(node, 4, LXADD4MemReg, cg);
return TR::TreeEvaluator::performSimpleAtomicMemoryUpdate(node, LXADD4MemReg, cg);
}
if (comp->getSymRefTab()->isNonHelper(SymRef, TR::SymbolReferenceTable::atomicFetchAndAdd64BitSymbol))
{
return TR::TreeEvaluator::performSimpleAtomicMemoryUpdate(node, 8, LXADD8MemReg, cg);
return TR::TreeEvaluator::performSimpleAtomicMemoryUpdate(node, LXADD8MemReg, cg);
}
if (comp->getSymRefTab()->isNonHelper(SymRef, TR::SymbolReferenceTable::atomicSwap32BitSymbol))
{
return TR::TreeEvaluator::performSimpleAtomicMemoryUpdate(node, 4, XCHG4MemReg, cg);
return TR::TreeEvaluator::performSimpleAtomicMemoryUpdate(node, XCHG4MemReg, cg);
}
if (comp->getSymRefTab()->isNonHelper(SymRef, TR::SymbolReferenceTable::atomicSwap64BitSymbol))
{
return TR::TreeEvaluator::performSimpleAtomicMemoryUpdate(node, 8, XCHG8MemReg, cg);
return TR::TreeEvaluator::performSimpleAtomicMemoryUpdate(node, XCHG8MemReg, cg);
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/x/codegen/OMRTreeEvaluator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ class OMR_EXTENSIBLE TreeEvaluator: public OMR::TreeEvaluator

protected:

static TR::Register *performSimpleAtomicMemoryUpdate(TR::Node* node, int8_t size, TR_X86OpCodes op, TR::CodeGenerator* cg);
static TR::Register *performSimpleAtomicMemoryUpdate(TR::Node* node, TR_X86OpCodes op, TR::CodeGenerator* cg);
static TR::Register *performHelperCall(TR::Node *node, TR::SymbolReference *helperSymRef, TR::ILOpCodes helperCallOpCode, bool spillFPRegs, TR::CodeGenerator *cg);
static TR::Register *performIload(TR::Node *node, TR::MemoryReference *sourceMR, TR::CodeGenerator *cg);
static TR::Register *performFload(TR::Node *node, TR::MemoryReference *sourceMR, TR::CodeGenerator *cg);
Expand Down

0 comments on commit 52a544b

Please sign in to comment.