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

x86: Code Generation Helpers #7632

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions compiler/x/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ compiler_library(x
${CMAKE_CURRENT_LIST_DIR}/codegen/OMRSnippetDelegate.cpp
${CMAKE_CURRENT_LIST_DIR}/codegen/X86SystemLinkage.cpp
${CMAKE_CURRENT_LIST_DIR}/codegen/OMRCodeGenerator.cpp
${CMAKE_CURRENT_LIST_DIR}/codegen/CodegenUtils.cpp
${CMAKE_CURRENT_LIST_DIR}/env/OMRCPU.cpp
${CMAKE_CURRENT_LIST_DIR}/env/OMRDebugEnv.cpp
)
Expand Down
5 changes: 3 additions & 2 deletions compiler/x/amd64/codegen/OMRTreeEvaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include "x/codegen/ConstantDataSnippet.hpp"
#include "x/codegen/OutlinedInstructions.hpp"
#include "x/codegen/X86Instruction.hpp"
#include "x/codegen/CodegenUtils.hpp"
#include "codegen/InstOpCode.hpp"

TR::Register*
Expand Down Expand Up @@ -2264,15 +2265,15 @@ OMR::X86::AMD64::TreeEvaluator::lbitpermuteEvaluator(TR::Node *node, TR::CodeGen

TR::Register *OMR::X86::AMD64::TreeEvaluator::aconstEvaluator(TR::Node *node, TR::CodeGenerator *cg)
{
TR::Register *targetRegister = TR::TreeEvaluator::loadConstant(node, node->getLongInt(), TR_RematerializableAddress, cg);
TR::Register *targetRegister = OMR::X86::loadConstant(node, node->getLongInt(), TR_RematerializableAddress, cg);

node->setRegister(targetRegister);
return targetRegister;
}

TR::Register *OMR::X86::AMD64::TreeEvaluator::lconstEvaluator(TR::Node *node, TR::CodeGenerator *cg)
{
TR::Register *targetRegister = TR::TreeEvaluator::loadConstant(node, node->getLongInt(), TR_RematerializableLong, cg);
TR::Register *targetRegister = OMR::X86::loadConstant(node, node->getLongInt(), TR_RematerializableLong, cg);

node->setRegister(targetRegister);
return targetRegister;
Expand Down
523 changes: 523 additions & 0 deletions compiler/x/codegen/CodegenUtils.cpp

Large diffs are not rendered by default.

382 changes: 382 additions & 0 deletions compiler/x/codegen/CodegenUtils.hpp

Large diffs are not rendered by default.

13 changes: 7 additions & 6 deletions compiler/x/codegen/ControlFlowEvaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
#include "x/codegen/CompareAnalyser.hpp"
#include "x/codegen/FPTreeEvaluator.hpp"
#include "x/codegen/X86Instruction.hpp"
#include "x/codegen/CodegenUtils.hpp"
#include "codegen/InstOpCode.hpp"

class TR_OpaqueClassBlock;
Expand Down Expand Up @@ -708,7 +709,7 @@ void OMR::X86::TreeEvaluator::compareIntegersForEquality(TR::Node *node, TR::Cod
else if(andSecondChild->getSize() == 2)
{
TR::Register *tempReg = cg->allocateRegister();
TR::TreeEvaluator::loadConstant(node, mask, TR_RematerializableShort, cg, tempReg);
OMR::X86::loadConstant(node, mask, TR_RematerializableShort, cg, tempReg);
generateMemRegInstruction(TR::InstOpCode::TEST2MemReg, node, tempMR, tempReg, cg);
cg->stopUsingRegister(tempReg);
}
Expand Down Expand Up @@ -827,7 +828,7 @@ void OMR::X86::TreeEvaluator::compareIntegersForEquality(TR::Node *node, TR::Cod
{
//shouldn't use Imm2 instructions
TR::Register *tempReg = cg->allocateRegister();
TR::TreeEvaluator::loadConstant(node, 0, TR_RematerializableShort, cg, tempReg);
OMR::X86::loadConstant(node, 0, TR_RematerializableShort, cg, tempReg);
generateMemRegInstruction(TR::InstOpCode::CMP2MemReg, node, tempMR, tempReg, cg);
cg->stopUsingRegister(tempReg);
}
Expand Down Expand Up @@ -889,7 +890,7 @@ void OMR::X86::TreeEvaluator::compareIntegersForEquality(TR::Node *node, TR::Cod
{
//shouldn't use Imm2 instructions
TR::Register *tempReg = cg->allocateRegister();
TR::TreeEvaluator::loadConstant(node, constValue, TR_RematerializableShort, cg, tempReg);
OMR::X86::loadConstant(node, constValue, TR_RematerializableShort, cg, tempReg);
generateMemRegInstruction(TR::InstOpCode::CMP2MemReg, node, tempMR, tempReg, cg);
cg->stopUsingRegister(tempReg);
}
Expand Down Expand Up @@ -1054,7 +1055,7 @@ void OMR::X86::TreeEvaluator::compareIntegersForOrder(
{
//shouldn't use Imm2 instructions
TR::Register *tempReg = cg->allocateRegister();
TR::TreeEvaluator::loadConstant(node, constValue, TR_RematerializableShort, cg, tempReg);
OMR::X86::loadConstant(node, constValue, TR_RematerializableShort, cg, tempReg);
generateMemRegInstruction(TR::InstOpCode::CMP2MemReg, node, tempMR, tempReg, cg);
cg->stopUsingRegister(tempReg);
}
Expand Down Expand Up @@ -1150,7 +1151,7 @@ void OMR::X86::TreeEvaluator::compare2BytesForOrder(TR::Node *node, TR::CodeGene
else
{
TR::Register *tempReg = cg->allocateRegister();
TR::TreeEvaluator::loadConstant(node, value, TR_RematerializableShort, cg, tempReg);
OMR::X86::loadConstant(node, value, TR_RematerializableShort, cg, tempReg);
generateMemRegInstruction(TR::InstOpCode::CMP2MemReg, node, tempMR, tempReg, cg);
cg->stopUsingRegister(tempReg);
}
Expand Down Expand Up @@ -1905,7 +1906,7 @@ TR::Register *OMR::X86::TreeEvaluator::ifscmpeqEvaluator(TR::Node *node, TR::Cod
{
//try to avoid Imm2 instructions
TR::Register *tempReg = cg->allocateRegister();
TR::TreeEvaluator::loadConstant(node, value, TR_RematerializableShort, cg, tempReg);
OMR::X86::loadConstant(node, value, TR_RematerializableShort, cg, tempReg);
generateMemRegInstruction(TR::InstOpCode::CMP2MemReg, node, tempMR, tempReg, cg);
cg->stopUsingRegister(tempReg);
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/x/codegen/OMRMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#include "codegen/X86Instruction.hpp"
#include "codegen/InstOpCode.hpp"
#include "x/codegen/X86Register.hpp"
#include "x/codegen/CodegenUtils.hpp"

extern bool existsNextInstructionToTestFlags(TR::Instruction *startInstr,
uint8_t testMask);
Expand Down Expand Up @@ -838,7 +839,7 @@ TR::RealRegister *OMR::X86::Machine::freeBestGPRegister(TR::Instruction
}
else
{
instr = TR::TreeEvaluator::insertLoadConstant(0, best, info->getConstant(), info->getDataType(), self()->cg(), currentInstruction);
instr = OMR::X86::insertLoadConstant(0, best, info->getConstant(), info->getDataType(), self()->cg(), currentInstruction);
}
}

Expand Down
226 changes: 0 additions & 226 deletions compiler/x/codegen/OMRTreeEvaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,232 +174,6 @@ void OMR::X86::TreeEvaluator::compareGPRegisterToImmediateForEquality(TR::Node
generateRegImmInstruction(cmpOp, node, cmpRegister, value, cg);
}

TR::Instruction *OMR::X86::TreeEvaluator::insertLoadConstant(TR::Node *node,
TR::Register *target,
intptr_t value,
TR_RematerializableTypes type,
TR::CodeGenerator *cg,
TR::Instruction *currentInstruction)
{
TR::Compilation *comp = cg->comp();
static const TR::InstOpCode::Mnemonic ops[TR_NumRematerializableTypes+1][3] =
// load 0 load -1 load c
{ { TR::InstOpCode::UD2, TR::InstOpCode::UD2, TR::InstOpCode::UD2 }, // LEA; should not seen here
{ TR::InstOpCode::XOR4RegReg, TR::InstOpCode::OR4RegImms, TR::InstOpCode::MOV4RegImm4 }, // Byte constant
{ TR::InstOpCode::XOR4RegReg, TR::InstOpCode::OR4RegImms, TR::InstOpCode::MOV4RegImm4 }, // Short constant
{ TR::InstOpCode::XOR4RegReg, TR::InstOpCode::OR4RegImms, TR::InstOpCode::MOV4RegImm4 }, // Char constant
{ TR::InstOpCode::XOR4RegReg, TR::InstOpCode::OR4RegImms, TR::InstOpCode::MOV4RegImm4 }, // Int constant
{ TR::InstOpCode::XOR4RegReg, TR::InstOpCode::OR4RegImms, TR::InstOpCode::MOV4RegImm4 }, // 32-bit address constant
{ TR::InstOpCode::XOR4RegReg, TR::InstOpCode::OR8RegImms, TR::InstOpCode::UD2 } }; // Long address constant; MOVs handled specially

enum { XOR = 0, OR = 1, MOV = 2 };

bool is64Bit = false;

int opsRow = type;
if (cg->comp()->target().is64Bit())
{
if (type == TR_RematerializableAddress)
{
// Treat 64-bit addresses as longs
opsRow++;
is64Bit = true;
}
else
{
is64Bit = (type == TR_RematerializableLong);
}
}
else
{
TR_ASSERT(type != TR_RematerializableLong, "Longs are rematerialized as pairs of ints on IA32");
}

TR_ExternalRelocationTargetKind reloKind = TR_NoRelocation;
if (cg->profiledPointersRequireRelocation() && node && node->getOpCodeValue() == TR::aconst &&
(node->isClassPointerConstant() || node->isMethodPointerConstant()))
{
if (node->isClassPointerConstant())
reloKind = TR_ClassPointer;
else if (node->isMethodPointerConstant())
reloKind = TR_MethodPointer;
else
TR_ASSERT(0, "Unexpected node, don't know how to relocate");
}

if (currentInstruction)
{
// Optimized loads inserted arbitrarily into the instruction stream must be checked
// to ensure they don't modify any eflags needed by surrounding instructions.
//
if ((value == 0 || value == -1))
{
uint8_t EFlags = TR::InstOpCode::getModifiedEFlags(ops[opsRow][((value == 0) ? XOR : OR)]);

if (existsNextInstructionToTestFlags(currentInstruction, EFlags) || cg->requiresCarry())
{
// Can't alter flags, so must use MOV. Fall through.
}
else if (value == 0)
return generateRegRegInstruction(currentInstruction, ops[opsRow][XOR], target, target, cg);
else if (value == -1)
return generateRegImmInstruction(currentInstruction, ops[opsRow][OR], target, (uint32_t)-1, cg);
}

// No luck optimizing this. Just use a MOV
//
TR::Instruction *movInstruction = NULL;
if (is64Bit)
{
if (cg->constantAddressesCanChangeSize(node) && node && node->getOpCodeValue() == TR::aconst &&
(node->isClassPointerConstant() || node->isMethodPointerConstant()))
{
movInstruction = generateRegImm64Instruction(currentInstruction, TR::InstOpCode::MOV8RegImm64, target, value, cg, reloKind);
}
else if (IS_32BIT_UNSIGNED(value))
{
// zero-extended 4-byte MOV
movInstruction = generateRegImmInstruction(currentInstruction, TR::InstOpCode::MOV4RegImm4, target, static_cast<int32_t>(value), cg, reloKind);
}
else if (IS_32BIT_SIGNED(value)) // TODO:AMD64: Is there some way we could get RIP too?
{
movInstruction = generateRegImmInstruction(currentInstruction, TR::InstOpCode::MOV8RegImm4, target, static_cast<int32_t>(value), cg, reloKind);
}
else
{
movInstruction = generateRegImm64Instruction(currentInstruction, TR::InstOpCode::MOV8RegImm64, target, value, cg, reloKind);
}
}
else
{
movInstruction = generateRegImmInstruction(currentInstruction, ops[opsRow][MOV], target, static_cast<int32_t>(value), cg, reloKind);
}

if (target && node &&
node->getOpCodeValue() == TR::aconst &&
node->isClassPointerConstant() &&
(cg->fe()->isUnloadAssumptionRequired((TR_OpaqueClassBlock *) node->getAddress(),
comp->getCurrentMethod()) ||
cg->profiledPointersRequireRelocation()))
{
comp->getStaticPICSites()->push_front(movInstruction);
}

if (target && node &&
node->getOpCodeValue() == TR::aconst &&
node->isMethodPointerConstant() &&
(cg->fe()->isUnloadAssumptionRequired(cg->fe()->createResolvedMethod(cg->trMemory(), (TR_OpaqueMethodBlock *) node->getAddress(), comp->getCurrentMethod())->classOfMethod(), comp->getCurrentMethod()) ||
cg->profiledPointersRequireRelocation()))
{
traceMsg(comp, "Adding instr %p to MethodPICSites for node %p\n", movInstruction, node);
comp->getStaticMethodPICSites()->push_front(movInstruction);
}

return movInstruction;
}
else
{
// constant loads between a compare and a branch cannot clobber the EFLAGS register
bool canClobberEFLAGS = !(cg->getCurrentEvaluationTreeTop()->getNode()->getOpCode().isIf() || cg->requiresCarry());

if (value == 0 && canClobberEFLAGS)
{
return generateRegRegInstruction(ops[opsRow][XOR], node, target, target, cg);
}
else if (value == -1 && canClobberEFLAGS)
{
return generateRegImmInstruction(ops[opsRow][OR], node, target, (uint32_t)-1, cg);
}
else
{
TR::Instruction *movInstruction = NULL;
if (is64Bit)
{
if (cg->constantAddressesCanChangeSize(node) && node && node->getOpCodeValue() == TR::aconst &&
(node->isClassPointerConstant() || node->isMethodPointerConstant()))
{
movInstruction = generateRegImm64Instruction(TR::InstOpCode::MOV8RegImm64, node, target, value, cg, reloKind);
}
else if (IS_32BIT_UNSIGNED(value))
{
// zero-extended 4-byte MOV
movInstruction = generateRegImmInstruction(TR::InstOpCode::MOV4RegImm4, node, target, static_cast<int32_t>(value), cg, reloKind);
}
else if (IS_32BIT_SIGNED(value)) // TODO:AMD64: Is there some way we could get RIP too?
{
movInstruction = generateRegImmInstruction(TR::InstOpCode::MOV8RegImm4, node, target, static_cast<int32_t>(value), cg, reloKind);
}
else
{
movInstruction = generateRegImm64Instruction(TR::InstOpCode::MOV8RegImm64, node, target, value, cg, reloKind);
}
}
else
{
movInstruction = generateRegImmInstruction(ops[opsRow][MOV], node, target, static_cast<int32_t>(value), cg, reloKind);
}

// HCR register PIC site in TR::TreeEvaluator::insertLoadConstant
TR::Symbol *symbol = NULL;
if (node && node->getOpCode().hasSymbolReference())
symbol = node->getSymbol();
bool isPICCandidate = symbol ? target && symbol->isStatic() && symbol->isClassObject() : false;
if (isPICCandidate && comp->getOption(TR_EnableHCR))
{
comp->getStaticHCRPICSites()->push_front(movInstruction);
}

if (target &&
node &&
node->getOpCodeValue() == TR::aconst &&
node->isClassPointerConstant() &&
(cg->fe()->isUnloadAssumptionRequired((TR_OpaqueClassBlock *) node->getAddress(),
comp->getCurrentMethod()) ||
cg->profiledPointersRequireRelocation()))
{
comp->getStaticPICSites()->push_front(movInstruction);
}

if (target && node &&
node->getOpCodeValue() == TR::aconst &&
node->isMethodPointerConstant() &&
(cg->fe()->isUnloadAssumptionRequired(cg->fe()->createResolvedMethod(cg->trMemory(), (TR_OpaqueMethodBlock *) node->getAddress(), comp->getCurrentMethod())->classOfMethod(), comp->getCurrentMethod()) ||
cg->profiledPointersRequireRelocation()))
{
traceMsg(comp, "Adding instr %p to MethodPICSites for node %p\n", movInstruction, node);
comp->getStaticMethodPICSites()->push_front(movInstruction);
}

return movInstruction;
}
}
}

TR::Register *OMR::X86::TreeEvaluator::loadConstant(TR::Node * node, intptr_t value, TR_RematerializableTypes type, TR::CodeGenerator *cg, TR::Register *targetRegister)
{
if (targetRegister == NULL)
{
targetRegister = cg->allocateRegister();
}

TR::Instruction *instr = TR::TreeEvaluator::insertLoadConstant(node, targetRegister, value, type, cg);

// Do not rematerialize register for class pointer or method pointer if
// it's AOT compilation because it doesn't have node info in register
// rematerialization to create relocation record for the class pointer
// or the method pointer.
if (cg->enableRematerialisation() &&
!(cg->comp()->compileRelocatableCode() && node && node->getOpCodeValue() == TR::aconst && (node->isClassPointerConstant() || node->isMethodPointerConstant())))
{
if (node && node->getOpCode().hasSymbolReference() && node->getSymbol() && node->getSymbol()->isClassObject())
(TR::Compiler->om.generateCompressedObjectHeaders() || cg->comp()->target().is32Bit()) ? type = TR_RematerializableInt : type = TR_RematerializableLong;

setDiscardableIfPossible(type, targetRegister, node, instr, value, cg);
}

return targetRegister;
}

TR::Instruction *
OMR::X86::TreeEvaluator::insertLoadMemory(
TR::Node *node,
Expand Down
8 changes: 0 additions & 8 deletions compiler/x/codegen/OMRTreeEvaluator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,12 +449,6 @@ class OMR_EXTENSIBLE TreeEvaluator: public OMR::TreeEvaluator
static bool VMinlineCallEvaluator(TR::Node *node, bool isIndirect, TR::CodeGenerator *cg);
static TR::Instruction *VMtestForReferenceArray(TR::Node *, TR::Register *objectReg, TR::CodeGenerator *cg);
static bool genNullTestSequence(TR::Node *node, TR::Register *opReg, TR::Register *targetReg, TR::CodeGenerator *cg);
static TR::Instruction *insertLoadConstant(TR::Node *node,
TR::Register *target,
intptr_t value,
TR_RematerializableTypes type,
TR::CodeGenerator *cg,
TR::Instruction *currentInstruction = NULL);

static TR::Instruction *insertLoadMemory(TR::Node *node,
TR::Register *target,
Expand Down Expand Up @@ -515,8 +509,6 @@ class OMR_EXTENSIBLE TreeEvaluator: public OMR::TreeEvaluator

static TR::Register *performCall(TR::Node *node, bool isIndirect, bool spillFPRegs, TR::CodeGenerator *cg);

static TR::Register *loadConstant(TR::Node *node, intptr_t value, TR_RematerializableTypes t, TR::CodeGenerator *cg, TR::Register *targetRegister = NULL);

static bool setCarryBorrow(TR::Node *flagNode, bool invertValue, TR::CodeGenerator *cg);

static void arrayCopy64BitPrimitiveInlineSmallSizeWithoutREPMOVSImplRoot16(TR::Node *node,
Expand Down
Loading