Beispiel #1
0
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));
}
Beispiel #2
0
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));
}
Beispiel #3
0
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));
}
Beispiel #4
0
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));
}
Beispiel #5
0
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));
}
Beispiel #6
0
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));
}
Beispiel #8
0
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;
}
Beispiel #9
0
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));
}
Beispiel #10
0
HLInst* X86Compiler::emit(uint32_t code) {
  HLInst* node = newInst(code);
  if (node == NULL)
    return NULL;
  return static_cast<HLInst*>(addNode(node));
}
Beispiel #11
0
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));
}
Beispiel #12
0
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;
}