static TR::Register *addOrSubInteger(TR::Node *node, TR::CodeGenerator *cg) { TR::Node *firstChild = node->getFirstChild(); TR::Register *src1Reg = cg->evaluate(firstChild); TR::Node *secondChild = node->getSecondChild(); TR::Register *trgReg = cg->allocateRegister(); bool isAdd = node->getOpCode().isAdd(); if (secondChild->getOpCode().isLoadConst() && secondChild->getRegister() == NULL) { int32_t value = secondChild->getInt(); if (constantIsUnsignedImm12(value)) { generateTrg1Src1ImmInstruction(cg, isAdd ? TR::InstOpCode::addimmw : TR::InstOpCode::subimmw, node, trgReg, src1Reg, value); } else { TR::Register *tmpReg = cg->allocateRegister(); loadConstant32(cg, node, value, tmpReg); generateTrg1Src2Instruction(cg, isAdd ? TR::InstOpCode::addw : TR::InstOpCode::subw, node, trgReg, src1Reg, tmpReg); cg->stopUsingRegister(tmpReg); } } else { TR::Register *src2Reg = cg->evaluate(secondChild); generateTrg1Src2Instruction(cg, isAdd ? TR::InstOpCode::addw : TR::InstOpCode::subw, node, trgReg, src1Reg, src2Reg); } node->setRegister(trgReg); firstChild->decReferenceCount(); secondChild->decReferenceCount(); return trgReg; }
TR::Register * OMR::ARM64::TreeEvaluator::lmulhEvaluator(TR::Node *node, TR::CodeGenerator *cg) { TR::Node *firstChild = node->getFirstChild(); TR::Register *src1Reg = cg->evaluate(firstChild); TR::Node *secondChild = node->getSecondChild(); TR::Register *src2Reg; TR::Register *trgReg = cg->allocateRegister(); TR::Register *tmpReg = NULL; // lmulh is generated for constant ldiv and the second child is the magic number // assume magic number is usually a large odd number with little optimization opportunity if (secondChild->getOpCode().isLoadConst() && secondChild->getRegister() == NULL) { int64_t value = secondChild->getLongInt(); src2Reg = tmpReg = cg->allocateRegister(); loadConstant64(cg, node, value, src2Reg); } else { src2Reg = cg->evaluate(secondChild); } generateTrg1Src2Instruction(cg, TR::InstOpCode::smulh, node, trgReg, src1Reg, src2Reg); if (tmpReg) { cg->stopUsingRegister(tmpReg); } firstChild->decReferenceCount(); secondChild->decReferenceCount(); node->setRegister(trgReg); return trgReg; }
TR::Register * OMR::ARM64::TreeEvaluator::imulEvaluator(TR::Node *node, TR::CodeGenerator *cg) { TR::Node *firstChild = node->getFirstChild(); TR::Register *src1Reg = cg->evaluate(firstChild); TR::Node *secondChild = node->getSecondChild(); TR::Register *trgReg; if (secondChild->getOpCode().isLoadConst() && secondChild->getRegister() == NULL) { int32_t value = secondChild->getInt(); if (value > 0 && cg->convertMultiplyToShift(node)) { // The multiply has been converted to a shift. trgReg = cg->evaluate(node); return trgReg; } else { trgReg = cg->allocateRegister(); mulConstant32(node, trgReg, src1Reg, value, cg); } } else { TR::Register *src2Reg = cg->evaluate(secondChild); trgReg = cg->allocateRegister(); generateMulInstruction(cg, node, trgReg, src1Reg, src2Reg); } firstChild->decReferenceCount(); secondChild->decReferenceCount(); node->setRegister(trgReg); return trgReg; }
static TR::Register *shiftHelper(TR::Node *node, TR::ARM64ShiftCode shiftType, TR::CodeGenerator *cg) { TR::Node *firstChild = node->getFirstChild(); TR::Node *secondChild = node->getSecondChild(); TR::ILOpCodes secondOp = secondChild->getOpCodeValue(); TR::Register *srcReg = cg->evaluate(firstChild); TR::Register *trgReg = cg->allocateRegister(); bool is64bit = node->getDataType().isInt64(); TR::InstOpCode::Mnemonic op; if (secondOp == TR::iconst || secondOp == TR::iuconst) { int32_t value = secondChild->getInt(); uint32_t shift = is64bit ? (value & 0x3F) : (value & 0x1F); switch (shiftType) { case TR::SH_LSL: generateLogicalShiftLeftImmInstruction(cg, node, trgReg, srcReg, shift); break; case TR::SH_LSR: generateLogicalShiftRightImmInstruction(cg, node, trgReg, srcReg, shift); break; case TR::SH_ASR: generateArithmeticShiftRightImmInstruction(cg, node, trgReg, srcReg, shift); break; default: TR_ASSERT(false, "Unsupported shift type."); } } else { TR::Register *shiftAmountReg = cg->evaluate(secondChild); switch (shiftType) { case TR::SH_LSL: op = is64bit ? TR::InstOpCode::lslvx : TR::InstOpCode::lslvw; break; case TR::SH_LSR: op = is64bit ? TR::InstOpCode::lsrvx : TR::InstOpCode::lsrvw; break; case TR::SH_ASR: op = is64bit ? TR::InstOpCode::asrvx : TR::InstOpCode::asrvw; break; default: TR_ASSERT(false, "Unsupported shift type."); } generateTrg1Src2Instruction(cg, op, node, trgReg, srcReg, shiftAmountReg); } node->setRegister(trgReg); firstChild->decReferenceCount(); secondChild->decReferenceCount(); return trgReg; }
static TR::Register *idivHelper(TR::Node *node, bool is64bit, TR::CodeGenerator *cg) { // TODO: Add checks for special cases TR::Node *firstChild = node->getFirstChild(); TR::Register *src1Reg = cg->evaluate(firstChild); TR::Node *secondChild = node->getSecondChild(); TR::Register *src2Reg = cg->evaluate(secondChild); TR::Register *trgReg = cg->allocateRegister(); generateTrg1Src2Instruction(cg, is64bit ? TR::InstOpCode::sdivx : TR::InstOpCode::sdivw, node, trgReg, src1Reg, src2Reg); firstChild->decReferenceCount(); secondChild->decReferenceCount(); node->setRegister(trgReg); return trgReg; }
TR::Register * OMR::ARM64::TreeEvaluator::imulhEvaluator(TR::Node *node, TR::CodeGenerator *cg) { TR::Node *firstChild = node->getFirstChild(); TR::Register *src1Reg = cg->evaluate(firstChild); TR::Node *secondChild = node->getSecondChild(); TR::Register *src2Reg; TR::Register *trgReg = cg->allocateRegister(); TR::Register *tmpReg = NULL; TR::Register *zeroReg = cg->allocateRegister(); TR::RegisterDependencyConditions *cond = new (cg->trHeapMemory()) TR::RegisterDependencyConditions(1, 1, cg->trMemory()); addDependency(cond, zeroReg, TR::RealRegister::xzr, TR_GPR, cg); // imulh is generated for constant idiv and the second child is the magic number // assume magic number is usually a large odd number with little optimization opportunity if (secondChild->getOpCode().isLoadConst() && secondChild->getRegister() == NULL) { int32_t value = secondChild->getInt(); src2Reg = tmpReg = cg->allocateRegister(); loadConstant32(cg, node, value, src2Reg); } else { src2Reg = cg->evaluate(secondChild); } generateTrg1Src3Instruction(cg, TR::InstOpCode::smaddl, node, trgReg, src1Reg, src2Reg, zeroReg, cond); cg->stopUsingRegister(zeroReg); /* logical shift right by 32 bits */ uint32_t imm = 0x183F; // N=1, immr=32, imms=63 generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::ubfmx, node, trgReg, trgReg, imm); if (tmpReg) { cg->stopUsingRegister(tmpReg); } firstChild->decReferenceCount(); secondChild->decReferenceCount(); node->setRegister(trgReg); return trgReg; }
void OMR::TreeTop::removeDeadTrees(TR::Compilation * comp, TR::TreeTop* first, TR::TreeTop* last) { for (TR::TreeTop* cur = first; cur != last; cur = cur->getNextTreeTop()) { int numChildren = cur->getNode()->getNumChildren(); for (int child = numChildren-1; child>0; --child) { TR::Node * node = cur->getNode()->getChild(child); cur->insertAfter(TR::TreeTop::create(comp, TR::Node::create(TR::treetop, 1, node))); node->decReferenceCount(); } if (numChildren != 0) { TR::Node * node = cur->getNode()->getChild(0); cur->setNode(TR::Node::create(TR::treetop, 1, node)); node->decReferenceCount(); } } }
void OMR::TreeTop::removeDeadTrees(TR::Compilation * comp, TR::TreeTop* list[]) { for (int i=0; list[i] != NULL; ++i) { int numChildren = list[i]->getNode()->getNumChildren(); for (int child = numChildren-1; child>0; --child) { TR::Node * node = list[i]->getNode()->getChild(child); list[i]->insertAfter(TR::TreeTop::create(comp, TR::Node::create(TR::treetop, 1, node))); node->decReferenceCount(); } if (numChildren != 0) { TR::Node * node = list[i]->getNode()->getChild(0); list[i]->setNode(TR::Node::create(TR::treetop, 1, node)); node->decReferenceCount(); } } }
// also handles lrol TR::Register * OMR::ARM64::TreeEvaluator::irolEvaluator(TR::Node *node, TR::CodeGenerator *cg) { TR::Node *firstChild = node->getFirstChild(); TR::Node *secondChild = node->getSecondChild(); TR::Register *trgReg = cg->gprClobberEvaluate(firstChild); bool is64bit = node->getDataType().isInt64(); TR::InstOpCode::Mnemonic op; if (secondChild->getOpCode().isLoadConst()) { int32_t value = secondChild->getInt(); uint32_t shift = is64bit ? (value & 0x3F) : (value & 0x1F); if (shift != 0) { shift = is64bit ? (64 - shift) : (32 - shift); // change ROL to ROR op = is64bit ? TR::InstOpCode::extrx : TR::InstOpCode::extrw; // ROR is an alias of EXTR generateTrg1Src2ShiftedInstruction(cg, op, node, trgReg, trgReg, trgReg, TR::SH_LSL, shift); } } else { TR::Register *shiftAmountReg = cg->evaluate(secondChild); generateNegInstruction(cg, node, shiftAmountReg, shiftAmountReg); // change ROL to ROR if (is64bit) { // 32->64 bit sign extension: SXTW is alias of SBFM uint32_t imm = 0x101F; // N=1, immr=0, imms=31 generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::sbfmx, node, shiftAmountReg, shiftAmountReg, imm); } op = is64bit ? TR::InstOpCode::rorvx : TR::InstOpCode::rorvw; generateTrg1Src2Instruction(cg, op, node, trgReg, trgReg, shiftAmountReg); } node->setRegister(trgReg); firstChild->decReferenceCount(); secondChild->decReferenceCount(); return trgReg; }