Skip to content

Commit

Permalink
AArch64: Use mov bitmask immediate instruction if possible
Browse files Browse the repository at this point in the history
This commit introduces ARM64Trg1ZeroImmInstruction class
which is required to use `mov` (bitmask immediate) instruction.
Also, loadConstant32 and loadConstant64 helper functions are
changed to use that instruction if useful.

Signed-off-by: Akira Saitoh <saiaki@jp.ibm.com>
  • Loading branch information
Akira Saitoh committed Jul 19, 2021
1 parent 88427d6 commit 153d75b
Show file tree
Hide file tree
Showing 8 changed files with 315 additions and 34 deletions.
15 changes: 15 additions & 0 deletions compiler/aarch64/codegen/ARM64BinaryEncoding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,21 @@ uint8_t *TR::ARM64Trg1ZeroSrc1Instruction::generateBinaryEncoding()
return cursor;
}

uint8_t *TR::ARM64Trg1ZeroImmInstruction::generateBinaryEncoding()
{
uint8_t *instructionStart = cg()->getBinaryBufferCursor();
uint8_t *cursor = instructionStart;
cursor = getOpCode().copyBinaryToBuffer(instructionStart);
insertTargetRegister(toARM64Cursor(cursor));
insertZeroRegister(toARM64Cursor(cursor));
insertImmediateField(toARM64Cursor(cursor));
insertNbit(toARM64Cursor(cursor));
cursor += ARM64_INSTRUCTION_LENGTH;
setBinaryLength(ARM64_INSTRUCTION_LENGTH);
setBinaryEncoding(instructionStart);
return cursor;
}

uint8_t *TR::ARM64Trg1Src1ImmInstruction::generateBinaryEncoding()
{
uint8_t *instructionStart = cg()->getBinaryBufferCursor();
Expand Down
51 changes: 51 additions & 0 deletions compiler/aarch64/codegen/ARM64Debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,9 @@ TR_Debug::print(TR::FILE *pOutFile, TR::Instruction *instr)
case OMR::Instruction::IsTrg1ZeroSrc1:
print(pOutFile, (TR::ARM64Trg1ZeroSrc1Instruction *)instr);
break;
case OMR::Instruction::IsTrg1ZeroImm:
print(pOutFile, (TR::ARM64Trg1ZeroImmInstruction *)instr);
break;
case OMR::Instruction::IsTrg1Src1:
print(pOutFile, (TR::ARM64Trg1Src1Instruction *)instr);
break;
Expand Down Expand Up @@ -1507,6 +1510,54 @@ TR_Debug::print(TR::FILE *pOutFile, TR::ARM64Trg1Src1ImmInstruction *instr)
}

void
TR_Debug::print(TR::FILE *pOutFile, TR::ARM64Trg1ZeroImmInstruction *instr)
{
printPrefix(pOutFile, instr);
TR::InstOpCode::Mnemonic op = instr->getOpCodeValue();
bool done = false;
if (op == TR::InstOpCode::orrimmx || op == TR::InstOpCode::orrimmw)
{
// mov (bitmask immediate) alias
uint32_t imm12 = instr->getSourceImmediate();
auto immr = imm12 >> 6;
auto imms = imm12 & 0x3f;
auto n = instr->getNbit();
if (op == TR::InstOpCode::orrimmx)
{
uint64_t immediate;
if (decodeBitMasks(n, immr, imms, immediate))
{
done = true;
trfprintf(pOutFile, "movx \t");
print(pOutFile, instr->getTargetRegister(), TR_WordReg);
trfprintf(pOutFile, ", 0x%llx", immediate);
}
}
else
{
uint32_t immediate;
if (decodeBitMasks(n, immr, imms, immediate))
{
done = true;
trfprintf(pOutFile, "movw \t");
print(pOutFile, instr->getTargetRegister(), TR_WordReg);
trfprintf(pOutFile, ", 0x%lx", immediate);
}
}
}
if (!done)
{
trfprintf(pOutFile, "%s \t", getOpCodeName(&instr->getOpCode()));
print(pOutFile, instr->getTargetRegister(), TR_WordReg);
trfprintf(pOutFile, ", %d", instr->getSourceImmediate());
}

if (instr->getDependencyConditions())
print(pOutFile, instr->getDependencyConditions());

trfflush(_comp->getOutFile());
}
void
TR_Debug::print(TR::FILE *pOutFile, TR::ARM64ZeroSrc1ImmInstruction *instr)
{
printPrefix(pOutFile, instr);
Expand Down
141 changes: 141 additions & 0 deletions compiler/aarch64/codegen/ARM64Instruction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1926,6 +1926,147 @@ class ARM64Trg1ZeroSrc1Instruction : public ARM64Trg1Src1Instruction
virtual uint8_t *generateBinaryEncoding();
};

/*
* This class is designated to be used for alias instruction such as movw, movx (bitmask immediate)
*/
class ARM64Trg1ZeroImmInstruction : public ARM64Trg1Instruction
{
uint32_t _source1Immediate;
bool _Nbit;

public:

/*
* @brief Constructor
* @param[in] op : instruction opcode
* @param[in] node : node
* @param[in] treg : target register
* @param[in] imm : immediate value
* @param[in] cg : CodeGenerator
*/
ARM64Trg1ZeroImmInstruction(TR::InstOpCode::Mnemonic op, TR::Node *node, TR::Register *treg,
uint32_t imm, TR::CodeGenerator *cg)
: ARM64Trg1Instruction(op, node, treg, cg), _source1Immediate(imm), _Nbit(false)
{
}

/*
* @brief Constructor
* @param[in] op : instruction opcode
* @param[in] node : node
* @param[in] treg : target register
* @param[in] N : N bit value
* @param[in] imm : immediate value
* @param[in] cg : CodeGenerator
*/
ARM64Trg1ZeroImmInstruction(TR::InstOpCode::Mnemonic op, TR::Node *node, TR::Register *treg,
bool N, uint32_t imm, TR::CodeGenerator *cg)
: ARM64Trg1Instruction(op, node, treg, cg), _source1Immediate(imm), _Nbit(N)
{
}

/*
* @brief Constructor
* @param[in] op : instruction opcode
* @param[in] node : node
* @param[in] treg : target register
* @param[in] imm : immediate value
* @param[in] precedingInstruction : preceding instruction
* @param[in] cg : CodeGenerator
*/
ARM64Trg1ZeroImmInstruction(TR::InstOpCode::Mnemonic op, TR::Node *node, TR::Register *treg,
uint32_t imm,
TR::Instruction *precedingInstruction, TR::CodeGenerator *cg)
: ARM64Trg1Instruction(op, node, treg, precedingInstruction, cg), _source1Immediate(imm), _Nbit(false)
{
}

/*
* @brief Constructor
* @param[in] op : instruction opcode
* @param[in] node : node
* @param[in] treg : target register
* @param[in] N : N bit value
* @param[in] imm : immediate value
* @param[in] precedingInstruction : preceding instruction
* @param[in] cg : CodeGenerator
*/
ARM64Trg1ZeroImmInstruction(TR::InstOpCode::Mnemonic op, TR::Node *node, TR::Register *treg,
bool N, uint32_t imm,
TR::Instruction *precedingInstruction, TR::CodeGenerator *cg)
: ARM64Trg1Instruction(op, node, treg, precedingInstruction, cg), _source1Immediate(imm), _Nbit(N)
{
}

/**
* @brief Gets instruction kind
* @return instruction kind
*/
virtual Kind getKind() { return IsTrg1ZeroImm; }

/**
* @brief Gets source immediate
* @return source immediate
*/
uint32_t getSourceImmediate() {return _source1Immediate;}
/**
* @brief Sets source immediate
* @param[in] si : immediate value
* @return source immediate
*/
uint32_t setSourceImmediate(uint32_t si) {return (_source1Immediate = si);}

/**
* @brief Gets the N bit (bit 22)
* @return N bit value
*/
bool getNbit() { return _Nbit;}
/**
* @brief Sets the N bit (bit 22)
* @param[in] n : N bit value
* @return N bit value
*/
bool setNbit(bool n) { return (_Nbit = n);}

/**
* @brief Sets zero register in binary encoding
* @param[in] instruction : instruction cursor
*/
void insertZeroRegister(uint32_t *instruction)
{
TR::RealRegister *zeroReg = cg()->machine()->getRealRegister(TR::RealRegister::xzr);
zeroReg->setRegisterFieldRN(instruction);
}

/**
* @brief Sets immediate field in binary encoding
* @param[in] instruction : instruction cursor
*/
void insertImmediateField(uint32_t *instruction)
{
*instruction |= ((_source1Immediate & 0xfff) << 10); /* imm12 */
}

/**
* @brief Sets N bit (bit 22) field in binary encoding
* @param[in] instruction : instruction cursor
*/
void insertNbit(uint32_t *instruction)
{
if (_Nbit)
{
*instruction |= (1 << 22);
}
}

/**
* @brief Generates binary encoding of the instruction
* @return instruction cursor
*/
virtual uint8_t *generateBinaryEncoding();
};


class ARM64Trg1Src1ImmInstruction : public ARM64Trg1Src1Instruction
{
uint32_t _source1Immediate;
Expand Down
11 changes: 11 additions & 0 deletions compiler/aarch64/codegen/GenerateInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,17 @@ TR::Instruction *generateNegInstruction(TR::CodeGenerator *cg, TR::Node *node,
return new (cg->trHeapMemory()) TR::ARM64Trg1ZeroSrc1Instruction(op, node, treg, sreg, cg);
}

TR::Instruction *generateMovBitMaskInstruction(TR::CodeGenerator *cg, TR::Node *node,
TR::Register *treg, bool N, uint32_t imm, bool is64bit, TR::Instruction *preced)
{
/* Alias of ORR instruction */
TR::InstOpCode::Mnemonic op = is64bit ? TR::InstOpCode::orrimmx : TR::InstOpCode::orrimmw;

if (preced)
return new (cg->trHeapMemory()) TR::ARM64Trg1ZeroImmInstruction(op, node, treg, N, imm, preced, cg);
return new (cg->trHeapMemory()) TR::ARM64Trg1ZeroImmInstruction(op, node,treg, N, imm, cg);
}

TR::Instruction *generateMulInstruction(TR::CodeGenerator *cg, TR::Node *node,
TR::Register *treg, TR::Register *s1reg, TR::Register *s2reg, TR::Instruction *preced)
{
Expand Down
20 changes: 20 additions & 0 deletions compiler/aarch64/codegen/GenerateInstructions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,26 @@ TR::Instruction *generateNegInstruction(
bool is64bit = false,
TR::Instruction *preced = NULL);

/*
* @brief Generates MOV (bitmask immediate) instruction
* @param[in] cg : CodeGenerator
* @param[in] node : node
* @param[in] treg : target register
* @param[in] N : N bit (bit 22) value
* @param[in] imm : immediate value
* @param[in] is64bit : true when it is 64-bit operation
* @param[in] preced : preceding instruction
* @return generated instruction
*/
TR::Instruction *generateMovBitMaskInstruction(
TR::CodeGenerator *cg,
TR::Node *node,
TR::Register *treg,
bool N,
uint32_t imm,
bool is64bit = true,
TR::Instruction *preced = NULL);

/*
* @brief Generates MUL (register) instruction
* @param[in] cg : CodeGenerator
Expand Down
1 change: 1 addition & 0 deletions compiler/aarch64/codegen/OMRInstructionKindEnum.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
IsTrg1Imm,
IsTrg1ImmSym,
IsTrg1ZeroSrc1,
IsTrg1ZeroImm,
IsTrg1Src1,
IsTrg1Src1Imm,
IsTrg1Src2,
Expand Down
Loading

0 comments on commit 153d75b

Please sign in to comment.