Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement binary encoding for POWER10 PC-relative loads and stores #5371

Merged
merged 2 commits into from
Jul 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions compiler/p/codegen/MemoryReference.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ class OMR_EXTENSIBLE MemoryReference : public OMR::MemoryReferenceConnector
int) :
OMR::MemoryReferenceConnector(br, disp, len, cg, 0) {}

MemoryReference(TR::LabelSymbol *label, int64_t disp, int8_t len, TR::CodeGenerator *cg) :
OMR::MemoryReferenceConnector(label, disp, len, cg) {}

public:

MemoryReference(TR::CodeGenerator *cg) :
Expand Down Expand Up @@ -72,6 +75,7 @@ class OMR_EXTENSIBLE MemoryReference : public OMR::MemoryReferenceConnector
OMR::MemoryReferenceConnector(node, mr, n, len, cg) {}

static TR::MemoryReference *withDisplacement(TR::CodeGenerator *cg, TR::Register *baseReg, int64_t displacement, int8_t length);
static TR::MemoryReference *withLabel(TR::CodeGenerator *cg, TR::LabelSymbol *label, int64_t offset, int8_t length);
};
}

Expand Down
43 changes: 38 additions & 5 deletions compiler/p/codegen/OMRMemoryReference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ TR::MemoryReference *TR::MemoryReference::withDisplacement(TR::CodeGenerator *cg
return new (cg->trHeapMemory()) TR::MemoryReference(baseReg, displacement, length, cg, 0);
}

TR::MemoryReference *TR::MemoryReference::withLabel(TR::CodeGenerator *cg, TR::LabelSymbol *label, int64_t offset, int8_t length)
{
return new (cg->trHeapMemory()) TR::MemoryReference(label, offset, length, cg);
}

OMR::Power::MemoryReference::MemoryReference(
TR::CodeGenerator *cg) :
_baseRegister(NULL),
Expand All @@ -84,12 +89,34 @@ OMR::Power::MemoryReference::MemoryReference(
_staticRelocation(NULL),
_unresolvedSnippet(NULL),
_conditions(NULL),
_flag(0)
_flag(0),
_label(NULL)
{
aviansie-ben marked this conversation as resolved.
Show resolved Hide resolved
_symbolReference = new (cg->trHeapMemory()) TR::SymbolReference(cg->comp()->getSymRefTab());
_offset = _symbolReference->getOffset();
}

OMR::Power::MemoryReference::MemoryReference(
TR::LabelSymbol *label,
int64_t disp,
uint8_t len,
TR::CodeGenerator *cg) :
_baseRegister(NULL),
_baseNode(NULL),
_indexRegister(NULL),
_indexNode(NULL),
_modBase(NULL),
_unresolvedSnippet(NULL),
_staticRelocation(NULL),
_conditions(NULL),
_length(len),
_offset(disp),
_flag(0),
_label(label)
{
_symbolReference = new (cg->trHeapMemory()) TR::SymbolReference(cg->comp()->getSymRefTab());
}

OMR::Power::MemoryReference::MemoryReference(
TR::Register *br,
TR::Register *ir,
Expand All @@ -104,7 +131,8 @@ OMR::Power::MemoryReference::MemoryReference(
_staticRelocation(NULL),
_conditions(NULL),
_length(len),
_flag(0)
_flag(0),
_label(NULL)
{
_symbolReference = new (cg->trHeapMemory()) TR::SymbolReference(cg->comp()->getSymRefTab());
_offset = _symbolReference->getOffset();
Expand Down Expand Up @@ -133,7 +161,8 @@ OMR::Power::MemoryReference::MemoryReference(
_conditions(NULL),
_length(len),
_offset(disp),
_flag(0)
_flag(0),
_label(NULL)
{
_symbolReference = new (cg->trHeapMemory()) TR::SymbolReference(cg->comp()->getSymRefTab());
}
Expand All @@ -147,7 +176,7 @@ OMR::Power::MemoryReference::MemoryReference(TR::Node *rootLoadOrStore, uint32_t
: _baseRegister(NULL), _indexRegister(NULL), _unresolvedSnippet(NULL),
_modBase(NULL), _flag(0), _baseNode(NULL), _indexNode(NULL),
_symbolReference(rootLoadOrStore->getSymbolReference()), _offset(0),
_conditions(NULL), _length(len), _staticRelocation(NULL)
_conditions(NULL), _length(len), _staticRelocation(NULL), _label(NULL)
{
TR::Compilation *comp = cg->comp();
TR::SymbolReference *ref = rootLoadOrStore->getSymbolReference();
Expand Down Expand Up @@ -223,7 +252,7 @@ OMR::Power::MemoryReference::MemoryReference(TR::Node *node, TR::SymbolReference
: _baseRegister(NULL), _indexRegister(NULL), _unresolvedSnippet(NULL),
_modBase(NULL), _flag(0), _baseNode(NULL), _indexNode(NULL),
_symbolReference(symRef), _offset(0),
_conditions(NULL), _length(len), _staticRelocation(NULL)
_conditions(NULL), _length(len), _staticRelocation(NULL), _label(NULL)
{
TR::Symbol *symbol = symRef->getSymbol();

Expand Down Expand Up @@ -266,6 +295,7 @@ OMR::Power::MemoryReference::MemoryReference(TR::Node *node, TR::MemoryReference
_staticRelocation = NULL;
_conditions = NULL;
mr._flag = 0;
_label = mr._label;

TR_ASSERT(mr.getStaticRelocation() == NULL, "Relocated memory reference should not be re-used.");

Expand Down Expand Up @@ -1197,6 +1227,9 @@ TR::Instruction *OMR::Power::MemoryReference::expandInstruction(TR::Instruction
// a memory instruction.
TR_ASSERT_FATAL(currentInstruction->getPrev(), "The first instruction cannot be a memory instruction");

if (self()->getLabel())
aviansie-ben marked this conversation as resolved.
Show resolved Hide resolved
return currentInstruction;

self()->mapOpCode(currentInstruction);

if (self()->getUnresolvedSnippet() != NULL)
Expand Down
10 changes: 10 additions & 0 deletions compiler/p/codegen/OMRMemoryReference.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class OMR_EXTENSIBLE MemoryReference : public OMR::MemoryReference
TR::Register *_indexRegister;
TR::Node *_indexNode;
TR::Register *_modBase;
TR::LabelSymbol *_label;
int64_t _offset;

TR::UnresolvedDataSnippet *_unresolvedSnippet;
Expand All @@ -90,6 +91,12 @@ class OMR_EXTENSIBLE MemoryReference : public OMR::MemoryReference
TR::CodeGenerator *cg,
int);

MemoryReference(
TR::LabelSymbol *label,
int64_t disp,
uint8_t len,
TR::CodeGenerator *cg);

public:

TR_ALLOC(TR_Memory::MemoryReference)
Expand Down Expand Up @@ -141,6 +148,9 @@ class OMR_EXTENSIBLE MemoryReference : public OMR::MemoryReference
uint32_t getLength() {return _length;}
uint32_t setLength(uint32_t len) {return (_length = len);}

TR::LabelSymbol *getLabel() {return _label;}
TR::LabelSymbol *setLabel(TR::LabelSymbol *label) {return (_label = label);}

bool useIndexedForm();

bool hasDelayedOffset()
Expand Down
41 changes: 38 additions & 3 deletions compiler/p/codegen/PPCAOTRelocation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ class PPCPairedRelocation: public TR::PPCRelocation
TR::Node *_node;
};

// This class has nothing to do with AOT, but for the lack of more appropriate locations
// this class is defined here.
//
// TODO(#5404): The classes defined below here are specific to Power, but are not actually AOT
// relocations. They are only here for lack of a better place to put them.

// PPC Specific Relocation: update the immediate fields of a pair of ppc instructions
// with the absolute address of a label (extended to 64bit as well). For example:
// lis gr3, addr_hi
Expand All @@ -109,6 +109,41 @@ class PPCPairedLabelAbsoluteRelocation : public TR::LabelRelocation
TR::Instruction *_instr4;
};

aviansie-ben marked this conversation as resolved.
Show resolved Hide resolved
/**
* \brief Represents a relocation on the D34 field of a PC-relative prefixed load/store instruction
* that should use an offset from a TR::LabelSymbol.
*/
class PPCD34LabelRelocation : public TR::LabelRelocation
{
public:

/**
* \brief
* Creates a new PPCD34LabelRelocation.
*
* \param instr
* The TR::Instruction for which this relocation was created, or \c NULL if this relocation is
* not associated with an instruction object.
*
* \param cursor
* The start of the prefixed load/store instruction to relocate.
*
* \param label
* The label relative to which the load/store should occur.
*
* \param offset
* The byte offset from the label at which the load/store should occur.
*/
PPCD34LabelRelocation(TR::Instruction *instr, uint32_t *cursor, TR::LabelSymbol *label, int64_t offset)
: TR::LabelRelocation(reinterpret_cast<uint8_t*>(cursor), label), _instr(instr), _offset(offset) {}

virtual void apply(TR::CodeGenerator *cg);

private:
TR::Instruction *_instr;
int64_t _offset;
};

}

typedef TR::PPCRelocation TR_PPCRelocation;
Expand Down
94 changes: 91 additions & 3 deletions compiler/p/codegen/PPCBinaryEncoding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "infra/Bit.hpp"
#include "infra/List.hpp"
#include "p/codegen/GenerateInstructions.hpp"
#include "p/codegen/PPCAOTRelocation.hpp"
#include "p/codegen/PPCInstruction.hpp"
#include "p/codegen/PPCOpsDefines.hpp"
#include "runtime/Runtime.hpp"
Expand Down Expand Up @@ -1402,6 +1403,36 @@ void TR::PPCSrc1Instruction::fillBinaryEncodingFields(uint32_t *cursor)
fillFieldFXM1(self(), cursor, imm);
break;

case FORMAT_RS_D34_RA_R:
aviansie-ben marked this conversation as resolved.
Show resolved Hide resolved
fillFieldRS(self(), cursor + 1, src);
fillFieldD34(self(), cursor, static_cast<int64_t>(static_cast<int32_t>(imm)));
fillFieldR(self(), cursor, 1);
break;

case FORMAT_RSP_D34_RA_R:
aviansie-ben marked this conversation as resolved.
Show resolved Hide resolved
fillFieldRSP(self(), cursor + 1, src);
fillFieldD34(self(), cursor, static_cast<int64_t>(static_cast<int32_t>(imm)));
fillFieldR(self(), cursor, 1);
break;

case FORMAT_FRS_D34_RA_R:
fillFieldFRS(self(), cursor + 1, src);
fillFieldD34(self(), cursor, static_cast<int64_t>(static_cast<int32_t>(imm)));
fillFieldR(self(), cursor, 1);
break;

case FORMAT_VRS_D34_RA_R:
fillFieldVRS(self(), cursor + 1, src);
fillFieldD34(self(), cursor, static_cast<int64_t>(static_cast<int32_t>(imm)));
fillFieldR(self(), cursor, 1);
break;

case FORMAT_XS5_D34_RA_R:
fillFieldXS5(self(), cursor + 1, src);
fillFieldD34(self(), cursor, static_cast<int64_t>(static_cast<int32_t>(imm)));
fillFieldR(self(), cursor, 1);
break;

default:
TR_ASSERT_FATAL_WITH_INSTRUCTION(self(), false, "Format %d cannot be binary encoded by PPCSrc1Instruction", getOpCode().getFormat());
}
Expand Down Expand Up @@ -1532,6 +1563,36 @@ TR::PPCTrg1ImmInstruction::fillBinaryEncodingFields(uint32_t *cursor)
fillFieldSIM(self(), cursor, imm);
break;

case FORMAT_RT_D34_RA_R:
fillFieldRT(self(), cursor + 1, trg);
fillFieldD34(self(), cursor, static_cast<int64_t>(static_cast<int32_t>(imm)));
fillFieldR(self(), cursor, 1);
break;

case FORMAT_RTP_D34_RA_R:
aviansie-ben marked this conversation as resolved.
Show resolved Hide resolved
fillFieldRTP(self(), cursor + 1, trg);
fillFieldD34(self(), cursor, static_cast<int64_t>(static_cast<int32_t>(imm)));
fillFieldR(self(), cursor, 1);
break;

case FORMAT_FRT_D34_RA_R:
fillFieldFRT(self(), cursor + 1, trg);
fillFieldD34(self(), cursor, static_cast<int64_t>(static_cast<int32_t>(imm)));
fillFieldR(self(), cursor, 1);
break;

case FORMAT_VRT_D34_RA_R:
fillFieldVRT(self(), cursor + 1, trg);
fillFieldD34(self(), cursor, static_cast<int64_t>(static_cast<int32_t>(imm)));
fillFieldR(self(), cursor, 1);
break;

case FORMAT_XT5_D34_RA_R:
fillFieldXT5(self(), cursor + 1, trg);
fillFieldD34(self(), cursor, static_cast<int64_t>(static_cast<int32_t>(imm)));
fillFieldR(self(), cursor, 1);
break;

default:
TR_ASSERT_FATAL_WITH_INSTRUCTION(self(), false, "Format %d cannot be binary encoded by PPCTrg1ImmInstruction", getOpCode().getFormat());
}
Expand Down Expand Up @@ -2077,13 +2138,15 @@ TR::RealRegister *toRealBaseRegister(TR::Instruction *instr, TR::Register *r)

void fillMemoryReferenceD16RA(TR::Instruction *instr, uint32_t *cursor, TR::MemoryReference *mr)
{
TR_ASSERT_FATAL_WITH_INSTRUCTION(instr, !mr->getLabel(), "Cannot use PC-relative load with non-prefixed instruction");
TR_ASSERT_FATAL_WITH_INSTRUCTION(instr, !mr->getIndexRegister(), "Cannot use index-form MemoryReference with non-index-form instruction");
fillFieldD16(instr, cursor, mr->getOffset());
fillFieldRA(instr, cursor, toRealBaseRegister(instr, mr->getBaseRegister()));
}

void fillMemoryReferenceDSRA(TR::Instruction *instr, uint32_t *cursor, TR::MemoryReference *mr)
{
TR_ASSERT_FATAL_WITH_INSTRUCTION(instr, !mr->getLabel(), "Cannot use PC-relative load with non-prefixed instruction");
TR_ASSERT_FATAL_WITH_INSTRUCTION(instr, !mr->getIndexRegister(), "Cannot use index-form MemoryReference with non-index-form instruction");
fillFieldDS(instr, cursor, mr->getOffset());
fillFieldRA(instr, cursor, toRealBaseRegister(instr, mr->getBaseRegister()));
Expand All @@ -2092,13 +2155,27 @@ void fillMemoryReferenceDSRA(TR::Instruction *instr, uint32_t *cursor, TR::Memor
void fillMemoryReferenceD34RAR(TR::Instruction *instr, uint32_t *cursor, TR::MemoryReference *mr)
{
TR_ASSERT_FATAL_WITH_INSTRUCTION(instr, !mr->getIndexRegister(), "Cannot use index-form MemoryReference with non-index-form instruction");
fillFieldD34(instr, cursor, mr->getOffset());
fillFieldRA(instr, cursor + 1, toRealBaseRegister(instr, mr->getBaseRegister()));
fillFieldR(instr, cursor, 0);
if (mr->getLabel())
{
TR_ASSERT_FATAL_WITH_INSTRUCTION(instr, !mr->getBaseRegister(), "Cannot have base register on PC-relative MemoryReference");

if (mr->getLabel()->getCodeLocation())
fillFieldD34(instr, cursor, static_cast<uint64_t>(mr->getLabel()->getCodeLocation() - reinterpret_cast<uint8_t*>(cursor)) + mr->getOffset());
else
instr->cg()->addRelocation(new (instr->cg()->trHeapMemory()) TR::PPCD34LabelRelocation(instr, cursor, mr->getLabel(), mr->getOffset()));
fillFieldR(instr, cursor, 1);
}
else
{
fillFieldD34(instr, cursor, mr->getOffset());
fillFieldRA(instr, cursor + 1, toRealBaseRegister(instr, mr->getBaseRegister()));
fillFieldR(instr, cursor, 0);
}
}

void fillMemoryReferenceRARB(TR::Instruction *instr, uint32_t *cursor, TR::MemoryReference *mr)
{
TR_ASSERT_FATAL_WITH_INSTRUCTION(instr, !mr->getLabel(), "Cannot use PC-relative load with non-prefixed instruction");
TR_ASSERT_FATAL_WITH_INSTRUCTION(instr, mr->getOffset() == 0, "Cannot use non-index-form MemoryReference with index-form instruction");
fillFieldRA(instr, cursor, toRealBaseRegister(instr, mr->getBaseRegister()));
fillFieldRB(instr, cursor, toRealRegister(mr->getIndexRegister()));
Expand Down Expand Up @@ -2276,6 +2353,17 @@ TR::Instruction *TR::PPCTrg1MemInstruction::expandInstruction()
return getMemoryReference()->expandInstruction(self(), cg());
}

void TR::PPCD34LabelRelocation::apply(TR::CodeGenerator *cg)
{
TR_ASSERT_FATAL_WITH_INSTRUCTION(_instr, getLabel()->getCodeLocation(), "Attempt to relocate against an unencoded label");

fillFieldD34(
_instr,
reinterpret_cast<uint32_t*>(getUpdateLocation()),
static_cast<uint64_t>(getLabel()->getCodeLocation() - getUpdateLocation()) + _offset
);
}

uint8_t *TR::PPCControlFlowInstruction::generateBinaryEncoding()
{
uint8_t *instructionStart = cg()->getBinaryBufferCursor();
Expand Down
5 changes: 5 additions & 0 deletions compiler/p/codegen/PPCDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,11 @@ TR_Debug::print(TR::FILE *pOutFile, TR::MemoryReference * mr, bool d_form)
print(pOutFile, mr->getBaseRegister());
trfprintf(pOutFile, ", ");
}
else if (mr->getLabel() != NULL)
{
print(pOutFile, mr->getLabel());
trfprintf(pOutFile, ", ");
}

if (mr->getIndexRegister() != NULL)
print(pOutFile, mr->getIndexRegister());
Expand Down
Loading