HLInst* X86Compiler::emit(uint32_t code, const Operand& o0, const Operand& o1, int o2_) { Imm o2(o2_); HLInst* node = newInst(code, o0, o1, o2); if (node == NULL) return NULL; return static_cast<HLInst*>(addNode(node)); }
HLInst* X86Compiler::emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, uint64_t o3_) { Imm o3(o3_); HLInst* node = newInst(code, o0, o1, o2, o3); if (node == NULL) return NULL; return static_cast<HLInst*>(addNode(node)); }
HLInst* X86Compiler::emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, uint64_t o3_) noexcept { Imm o3(o3_); HLInst* node = newInst(code, o0, o1, o2, o3); if (node == nullptr) return nullptr; return static_cast<HLInst*>(addNode(node)); }
HLInst* X86Compiler::emit(uint32_t code, uint64_t o0_) { Imm o0(o0_); HLInst* node = newInst(code, o0); if (node == NULL) return NULL; return static_cast<HLInst*>(addNode(node)); }
HLInst* X86Compiler::emit(uint32_t code, const Operand& o0, int o1_) noexcept { Imm o1(o1_); HLInst* node = newInst(code, o0, o1); if (node == nullptr) return nullptr; return static_cast<HLInst*>(addNode(node)); }
HLInst* X86Compiler::emit(uint32_t code, uint64_t o0_) noexcept { Imm o0(o0_); HLInst* node = newInst(code, o0); if (node == nullptr) return nullptr; return static_cast<HLInst*>(addNode(node)); }
void LocalAccessChainConvertPass::BuildAndAppendInst( SpvOp opcode, uint32_t typeId, uint32_t resultId, const std::vector<Operand>& in_opnds, std::vector<std::unique_ptr<Instruction>>* newInsts) { std::unique_ptr<Instruction> newInst( new Instruction(context(), opcode, typeId, resultId, in_opnds)); get_def_use_mgr()->AnalyzeInstDefUse(&*newInst); newInsts->emplace_back(std::move(newInst)); }
Inst* SubCfgBuilderUtils::newInst( Mnemonic mn, Opnd* op0, Opnd* op1, Opnd*op2) { if (mn == Mnemonic_MOV) { // special handling in another newInst() return newInst(mn, 0, op0, op1, op2); } Inst* inst = m_irManager->newInst(mn, op0, op1, op2); m_currNode->appendInst(inst); return inst; }
HLInst* X86Compiler::emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, const Operand& o3, const Operand& o4) { HLInst* node = newInst(code, o0, o1, o2, o3, o4); if (node == NULL) return NULL; return static_cast<HLInst*>(addNode(node)); }
HLInst* X86Compiler::emit(uint32_t code) { HLInst* node = newInst(code); if (node == NULL) return NULL; return static_cast<HLInst*>(addNode(node)); }
HLInst* X86Compiler::emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, const Operand& o3, const Operand& o4) noexcept { HLInst* node = newInst(code, o0, o1, o2, o3, o4); if (node == nullptr) return nullptr; return static_cast<HLInst*>(addNode(node)); }
HLInst* X86Compiler::emit(uint32_t code) noexcept { HLInst* node = newInst(code); if (node == nullptr) return nullptr; return static_cast<HLInst*>(addNode(node)); }
PeepHoleOpt::Changed PeepHoleOpt::handleInst_Convert_F2I_D2I(Inst* inst) { // // Inline 'int_value = (int)(float_value or double_value)' // Opnd* dst = inst->getOpnd(0); Opnd* src = inst->getOpnd(2); Type* srcType = src->getType(); assert(srcType->isSingle() || srcType->isDouble()); assert(dst->getType()->isInt4()); const bool is_dbl = srcType->isDouble(); // Here, we might have to deal with 3 cases with src (_value): // 1. Unassigned operand - act as if were operating with XMM // 2. Assigned to FPU - convert to FPU operations, to // avoid long FPU->mem->XMM chain // 3. Assigned to XMM - see #1 const bool xmm_way = !(src->hasAssignedPhysicalLocation() && src->isPlacedIn(OpndKind_FPReg)); if (!xmm_way) { //TODO: will add FPU later if measurements show it worths trying return Changed_Nothing; } // // /* movss xmm0, val // presuming the corner cases (NaN, overflow) // normally happen rare, do conversion first, // and check for falls later -- convertNode cvttss2si eax, xmm0 -- ovfTestNode // did overflow happen ? cmp eax, 0x80000000 jne _done // no - go return result -- testAgainstZeroNode // test SRC against zero comiss xmm0, [fp_zero] // isNaN ? jp _nan // yes - go load 0 -- testIfBelowNode // xmm < 0 ? jb _done // yes - go load MIN_INT. EAX already has it - simply return. -- loadMaxIntNode // ok. at this point, XMM is positive and > MAX_INT // must load MAX_INT which is 0x7fffffff. // As EAX has 0x80000000, then simply substract 1 sub eax, 1 jmp _done -- loadZeroNode _nan: xor eax, eax -- nodeNode _done: mov result, eax } */ Opnd* fpZeroOpnd = getZeroConst(srcType); Type* int32type = irManager->getTypeManager().getInt32Type(); Opnd* oneOpnd = irManager->newImmOpnd(int32type, 1); Opnd* intZeroOpnd = getIntZeroConst(); // 0x8..0 here is not the INT_MIN, but comes from the COMISS // opcode description instead. Opnd* minIntOpnd = irManager->newImmOpnd(int32type, 0x80000000); newSubGFG(); Node* entryNode = getSubCfgEntryNode(); Node* convertNode = newBB(); Node* ovfTestNode = newBB(); Node* testAgainstZeroNode = newBB(); Node* testIfBelowNode = newBB(); Node* loadMaxIntNode = newBB(); Node* loadZeroNode = newBB(); Node* doneNode = newBB(); // // presuming the corner cases (NaN, overflow) // normally happen rare, do conversion first, // and check for falls later // connectNodes(entryNode, convertNode); // // convert // setCurrentNode(convertNode) ; Mnemonic mn_cvt = is_dbl ? Mnemonic_CVTTSD2SI : Mnemonic_CVTTSS2SI; /*cvttss2si r32, xmm*/ newInst(mn_cvt, 1, dst, src); connectNodeTo(ovfTestNode); setCurrentNode(NULL); // // check whether overflow happened // setCurrentNode(ovfTestNode); /*cmp r32, MIN_INT*/ newInst(Mnemonic_CMP, dst, minIntOpnd); /*jne _done */ newBranch(Mnemonic_JNE, doneNode, testAgainstZeroNode, 0.9, 0.1); // setCurrentNode(NULL); // test SRC against zero // setCurrentNode(testAgainstZeroNode); Mnemonic mn_cmp = is_dbl ? Mnemonic_UCOMISD : Mnemonic_UCOMISS; /*comiss src, 0. */ newInst(mn_cmp, src, fpZeroOpnd); /*jp _nan:result=0*/ newBranch(Mnemonic_JP, loadZeroNode, testIfBelowNode); setCurrentNode(NULL); // // // setCurrentNode(loadZeroNode); /*mov r32, 0*/ newInst(Mnemonic_MOV, dst, intZeroOpnd); /*jmp _done*/ connectNodeTo(doneNode); setCurrentNode(NULL); // // test if we have a huge negative in SRC // setCurrentNode(testIfBelowNode); /*jb _done:*/ newBranch(Mnemonic_JB, doneNode, loadMaxIntNode); setCurrentNode(NULL); // // // setCurrentNode(loadMaxIntNode); /* sub dst, 1*/ newInst(Mnemonic_SUB, dst, oneOpnd); connectNodeTo(doneNode); setCurrentNode(NULL); // connectNodes(doneNode, getSubCfgReturnNode()); // propagateSubCFG(inst); return Changed_Node; }