Example #1
0
// StackSym::GetIntConstValue
int32
StackSym::GetIntConstValue() const
{
    Assert(this->IsIntConst());
    IR::Instr *defInstr = this->m_instrDef;
    IR::Opnd *src1 = defInstr->GetSrc1();

    if (src1->IsIntConstOpnd())
    {
        Assert(defInstr->m_opcode == Js::OpCode::Ld_I4 || defInstr->m_opcode == Js::OpCode::LdC_A_I4 || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn || LowererMD::IsAssign(defInstr));
        return src1->AsIntConstOpnd()->AsInt32();
    }

    if (src1->IsAddrOpnd())
    {
        Assert(defInstr->m_opcode == Js::OpCode::Ld_A || LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
        IR::AddrOpnd *addr = src1->AsAddrOpnd();
        Assert(addr->IsVar());
        Js::Var var = src1->AsAddrOpnd()->m_address;
        if (Js::TaggedInt::Is(var))
        {
            return Js::TaggedInt::ToInt32(var);
        }
        int32 value;
        const bool isInt32 = Js::JavascriptNumber::TryGetInt32Value(Js::JavascriptNumber::GetValue(var), &value);
        Assert(isInt32);
        return value;
    }
    Assert(src1->IsRegOpnd());
    return src1->AsRegOpnd()->m_sym->GetIntConstValue();
}
Example #2
0
BailoutConstantValue StackSym::GetConstValueForBailout() const
{
    Assert(this->IsConst());
    IR::Instr *defInstr = this->m_instrDef;
    IR::Opnd *src1 = defInstr->GetSrc1();

    return src1->GetConstValue();
}
Example #3
0
Js::Var StackSym::GetFloatConstValueAsVar_PostGlobOpt() const
{
    Assert(this->IsConst());
    IR::Instr *defInstr = this->m_instrDef;
    IR::Opnd *src1 = defInstr->GetSrc1();

    StackSym * stackSym = nullptr;

    if (src1->IsRegOpnd())
    {
        stackSym = src1->AsRegOpnd()->m_sym;
        Assert(!stackSym->m_isEncodedConstant);
        if (stackSym->m_isSingleDef)
        {
            //In ARM constant load is always legalized. Try to get the constant from src def
            defInstr = stackSym->m_instrDef;
            src1 = defInstr->GetSrc1();
        }
    }

    Assert(this->IsFloatConst() || (stackSym && stackSym->IsFloatConst()));

    IR::AddrOpnd *addrOpnd;
    if (src1->IsAddrOpnd())
    {
        Assert(defInstr->m_opcode == Js::OpCode::Ld_A);
        addrOpnd = src1->AsAddrOpnd();
    }
    else
    {
        Assert(src1->IsFloatConstOpnd());
        Assert(defInstr->m_opcode == Js::OpCode::LdC_A_R8);

        addrOpnd = src1->AsFloatConstOpnd()->GetAddrOpnd(defInstr->m_func);

        // This is just to prevent creating multiple numbers when the sym is used multiple times. We can only do this
        // post-GlobOpt, as otherwise it violates some invariants assumed in GlobOpt.
        defInstr->ReplaceSrc1(addrOpnd);
        defInstr->m_opcode = Js::OpCode::Ld_A;
    }

    const Js::Var address = addrOpnd->m_address;
    Assert(Js::JavascriptNumber::Is(address));
    return address;
}
Example #4
0
IR::Opnd *
StackSym::GetConstOpnd() const
{
    Assert(IsConst());
    IR::Instr *defInstr = this->m_instrDef;
    IR::Opnd *src1 = defInstr->GetSrc1();
    if (!src1)
    {
#if defined(_M_IX86) || defined(_M_X64)
        Assert(defInstr->m_opcode == Js::OpCode::MOVSD_ZERO);
#else
        Assert(UNREACHED);
#endif
    }
    else if (src1->IsIntConstOpnd())
    {
        Assert(this->IsIntConst());
        if (defInstr->m_opcode == Js::OpCode::LdC_A_I4)
        {
            src1 = IR::AddrOpnd::NewFromNumber(src1->AsIntConstOpnd()->GetValue(), defInstr->m_func);
            defInstr->ReplaceSrc1(src1);
            defInstr->m_opcode = Js::OpCode::Ld_A;
        }
        else
        {
            Assert(defInstr->m_opcode == Js::OpCode::Ld_I4 || LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
        }
    }
    else if (src1->IsFloatConstOpnd())
    {
        Assert(this->IsFloatConst());
        Assert(defInstr->m_opcode == Js::OpCode::LdC_A_R8);

        src1 = src1->AsFloatConstOpnd()->GetAddrOpnd(defInstr->m_func);
        defInstr->ReplaceSrc1(src1);
        defInstr->m_opcode = Js::OpCode::Ld_A;

    }
    else if (src1->IsAddrOpnd())
    {
        Assert(defInstr->m_opcode == Js::OpCode::Ld_A || LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
    }
    else if (src1->IsMemRefOpnd())
    {
        Assert(this->IsFloatConst() || this->IsSimd128Const());
    }
    else
    {
        AssertMsg(UNREACHED, "Invalid const value");
    }
    return src1;
}
Example #5
0
void *StackSym::GetConstAddress() const
{
    Assert(this->IsConst());
    IR::Instr *defInstr = this->m_instrDef;
    IR::Opnd *src1 = defInstr->GetSrc1();

    StackSym * stackSym = nullptr;

    if (src1->IsRegOpnd())
    {
        stackSym = src1->AsRegOpnd()->m_sym;
        Assert(!stackSym->m_isEncodedConstant);
        if (stackSym->m_isSingleDef)
        {
            //In ARM constant load is always legalized. Try to get the constant from src def
            defInstr = stackSym->m_instrDef;
            src1 = defInstr->GetSrc1();
        }
    }

    Assert(src1->IsAddrOpnd());
    Assert(defInstr->m_opcode == Js::OpCode::Ld_A || defInstr->m_opcode == Js::OpCode::LdStr || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn || LowererMD::IsAssign(defInstr));
    return src1->AsAddrOpnd()->m_address;
}
Example #6
0
bool
GlobOpt::Simd128DoTypeSpec(IR::Instr *instr, const Value *src1Val, const Value *src2Val, const Value *dstVal)
{
    bool doTypeSpec = true;

    // TODO: Some operations require additional opnd constraints (e.g. shuffle/swizzle).
    if (Js::IsSimd128Opcode(instr->m_opcode))
    {
        ThreadContext::SimdFuncSignature simdFuncSignature;
        instr->m_func->GetScriptContext()->GetThreadContext()->GetSimdFuncSignatureFromOpcode(instr->m_opcode, simdFuncSignature);
        if (!simdFuncSignature.valid)
        {
            // not implemented yet.
            return false;
        }
        // special handling for Load/Store
        if (Js::IsSimd128Load(instr->m_opcode) || Js::IsSimd128Store(instr->m_opcode))
        {
            return Simd128DoTypeSpecLoadStore(instr, src1Val, src2Val, dstVal, &simdFuncSignature);
        }

        const uint argCount = simdFuncSignature.argCount;
        switch (argCount)
        {
        case 2:
            Assert(src2Val);
            doTypeSpec = doTypeSpec && Simd128CanTypeSpecOpnd(src2Val->GetValueInfo()->Type(), simdFuncSignature.args[1]) && Simd128ValidateIfLaneIndex(instr, instr->GetSrc2(), 1);
            // fall-through
        case 1:
            Assert(src1Val);
            doTypeSpec = doTypeSpec && Simd128CanTypeSpecOpnd(src1Val->GetValueInfo()->Type(), simdFuncSignature.args[0]) && Simd128ValidateIfLaneIndex(instr, instr->GetSrc1(), 0);
            break;
        default:
        {
            // extended args
            Assert(argCount > 2);
            // Check if all args have been type specialized.

            int arg = argCount - 1;
            IR::Instr * eaInstr = GetExtendedArg(instr);

            while (arg>=0)
            {
                Assert(eaInstr);
                Assert(eaInstr->m_opcode == Js::OpCode::ExtendArg_A);

                ValueType expectedType = simdFuncSignature.args[arg];
                IR::Opnd * opnd = eaInstr->GetSrc1();
                StackSym * sym = opnd->GetStackSym();

                // In Forward Prepass: Check liveness through liveness bits, not IR type, since in prepass no actual type-spec happens.
                // In the Forward Pass: Check IRType since Sym can be null, because of const prop.
                if (expectedType.IsSimd128Float32x4())
                {
                    if (sym && !IsSimd128F4TypeSpecialized(sym, &currentBlock->globOptData) ||
                        !sym && opnd->GetType() != TySimd128F4)
                    {
                        return false;
                    }
                }
                else if (expectedType.IsSimd128Int32x4())
                {
                    if (sym && !IsSimd128I4TypeSpecialized(sym, &currentBlock->globOptData) ||
                        !sym && opnd->GetType() != TySimd128I4)
                    {
                        return false;
                    }
                }
                else if (expectedType.IsFloat())
                {
                    if (sym && !IsFloat64TypeSpecialized(sym, &currentBlock->globOptData) ||
                        !sym&& opnd->GetType() != TyFloat64)
                    {
                        return false;
                    }

                }
                else if (expectedType.IsInt())
                {
                    if ((sym && !IsInt32TypeSpecialized(sym, &currentBlock->globOptData) && !currentBlock->globOptData.liveLossyInt32Syms->Test(sym->m_id)) ||
                        !sym && opnd->GetType() != TyInt32)
                    {
                        return false;
                    }
                    // Extra check if arg is a lane index
                    if (!Simd128ValidateIfLaneIndex(instr, opnd, arg))
                    {
                        return false;
                    }
                }
                else
                {
                    Assert(UNREACHED);
                }

                eaInstr = GetExtendedArg(eaInstr);
                arg--;
            }
            // all args are type-spec'd
            doTypeSpec = true;
        }
        }
    }
    else
    {
        Assert(instr->m_opcode == Js::OpCode::ExtendArg_A);
        // For ExtendArg, the expected type is encoded in the dst(link) operand.
        doTypeSpec = doTypeSpec && Simd128CanTypeSpecOpnd(src1Val->GetValueInfo()->Type(), instr->GetDst()->GetValueType());
    }

    return doTypeSpec;
}
Example #7
0
intptr_t StackSym::GetLiteralConstValue_PostGlobOpt() const
{
    Assert(this->IsConst());
    IR::Instr *defInstr = this->m_instrDef;
    IR::Opnd *src1 = defInstr->GetSrc1();

    StackSym * stackSym = nullptr;

    if (src1->IsRegOpnd())
    {
        stackSym = src1->AsRegOpnd()->m_sym;
        if (stackSym->m_isEncodedConstant)
        {
            Assert(!stackSym->m_isSingleDef);
            Assert(LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
            return stackSym->constantValue;
        }

        if (stackSym->m_isSingleDef)
        {
            //In ARM constant load is always legalized. Try to get the constant from src def
            defInstr = stackSym->m_instrDef;
            src1 = defInstr->GetSrc1();
        }
    }

    if (src1->IsAddrOpnd())
    {
        Assert(defInstr->m_opcode == Js::OpCode::Ld_A || defInstr->m_opcode == Js::OpCode::LdStr || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn || LowererMD::IsAssign(defInstr));
        return reinterpret_cast<intptr_t>(src1->AsAddrOpnd()->m_address);
    }
    if (src1->IsIntConstOpnd())
    {
        Assert(this->IsIntConst() || (stackSym && stackSym->IsIntConst()));
        if (defInstr->m_opcode == Js::OpCode::LdC_A_I4)
        {
            IR::AddrOpnd *const addrOpnd = IR::AddrOpnd::NewFromNumber(src1->AsIntConstOpnd()->GetValue(), defInstr->m_func);
            const Js::Var address = addrOpnd->m_address;

            // This is just to prevent creating multiple numbers when the sym is used multiple times. We can only do this
            // post-GlobOpt, as otherwise it violates some invariants assumed in GlobOpt.
            defInstr->ReplaceSrc1(addrOpnd);
            defInstr->m_opcode = Js::OpCode::Ld_A;
            return reinterpret_cast<intptr_t>(address);
        }
        Assert(defInstr->m_opcode == Js::OpCode::Ld_I4 || LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
        return src1->AsIntConstOpnd()->GetValue();
    }
    if (src1->IsFloatConstOpnd())
    {
        Assert(this->IsFloatConst() || (stackSym && stackSym->IsFloatConst()));
        Assert(defInstr->m_opcode == Js::OpCode::LdC_A_R8);

        IR::AddrOpnd *const addrOpnd = src1->AsFloatConstOpnd()->GetAddrOpnd(defInstr->m_func);
        const Js::Var address = addrOpnd->m_address;

        // This is just to prevent creating multiple numbers when the sym is used multiple times. We can only do this
        // post-GlobOpt, as otherwise it violates some invariants assumed in GlobOpt.
        defInstr->ReplaceSrc1(addrOpnd);
        defInstr->m_opcode = Js::OpCode::Ld_A;
        return reinterpret_cast<intptr_t>(address);
    }

    AssertMsg(UNREACHED, "Unknown const value");
    return 0;
}