int GlobOpt::GetBoundCheckOffsetForSimd(ValueType arrValueType, const IR::Instr *instr, const int oldOffset /* = -1 */) { #ifdef ENABLE_SIMDJS if (!(Js::IsSimd128LoadStore(instr->m_opcode))) { return oldOffset; } if (!arrValueType.IsTypedArray()) { // no need to adjust for other array types, we will not type-spec (see Simd128DoTypeSpecLoadStore) return oldOffset; } Assert(instr->dataWidth == 4 || instr->dataWidth == 8 || instr->dataWidth == 12 || instr->dataWidth == 16); int numOfElems = Lowerer::SimdGetElementCountFromBytes(arrValueType, instr->dataWidth); // we want to make bound checks more conservative. We compute how many extra elements we need to add to the bound check // e.g. if original bound check is value <= Length + offset, and dataWidth is 16 bytes on Float32 array, then we need room for 4 elements. The bound check guarantees room for 1 element. // Hence, we need to ensure 3 more: value <= Length + offset - 3 // We round up since dataWidth may span a partial lane (e.g. dataWidth = 12, bpe = 8 bytes) int offsetBias = -(numOfElems - 1); // we should always make an existing bound-check more conservative. Assert(offsetBias <= 0); return oldOffset + offsetBias; #else return oldOffset; #endif }
bool GlobOpt::Simd128DoTypeSpecLoadStore(IR::Instr *instr, const Value *src1Val, const Value *src2Val, const Value *dstVal, const ThreadContext::SimdFuncSignature *simdFuncSignature) { IR::Opnd *baseOpnd = nullptr, *indexOpnd = nullptr, *valueOpnd = nullptr; IR::Opnd *src, *dst; bool doTypeSpec = true; // value = Ld [arr + index] // [arr + index] = St value src = instr->GetSrc1(); dst = instr->GetDst(); Assert(dst && src && !instr->GetSrc2()); if (Js::IsSimd128Load(instr->m_opcode)) { Assert(src->IsIndirOpnd()); baseOpnd = instr->GetSrc1()->AsIndirOpnd()->GetBaseOpnd(); indexOpnd = instr->GetSrc1()->AsIndirOpnd()->GetIndexOpnd(); valueOpnd = instr->GetDst(); } else if (Js::IsSimd128Store(instr->m_opcode)) { Assert(dst->IsIndirOpnd()); baseOpnd = instr->GetDst()->AsIndirOpnd()->GetBaseOpnd(); indexOpnd = instr->GetDst()->AsIndirOpnd()->GetIndexOpnd(); valueOpnd = instr->GetSrc1(); // St(arr, index, value). Make sure value can be Simd128 type-spec'd doTypeSpec = doTypeSpec && Simd128CanTypeSpecOpnd(FindValue(valueOpnd->AsRegOpnd()->m_sym)->GetValueInfo()->Type(), simdFuncSignature->args[2]); } else { Assert(UNREACHED); } // array and index operands should have been type-specialized in OptArraySrc: ValueTypes should be definite at this point. If not, don't type-spec. // We can be in a loop prepass, where opnd ValueInfo is not set yet. Get the ValueInfo from the Value Table instead. ValueType baseOpndType = FindValue(baseOpnd->AsRegOpnd()->m_sym)->GetValueInfo()->Type(); if (IsLoopPrePass()) { doTypeSpec = doTypeSpec && (baseOpndType.IsObject() && baseOpndType.IsTypedArray()); // indexOpnd might be missing if loading from [0] if (indexOpnd != nullptr) { ValueType indexOpndType = FindValue(indexOpnd->AsRegOpnd()->m_sym)->GetValueInfo()->Type(); doTypeSpec = doTypeSpec && indexOpndType.IsLikelyInt(); } } else { doTypeSpec = doTypeSpec && (baseOpndType.IsObject() && baseOpndType.IsTypedArray()); if (indexOpnd != nullptr) { ValueType indexOpndType = FindValue(indexOpnd->AsRegOpnd()->m_sym)->GetValueInfo()->Type(); doTypeSpec = doTypeSpec && indexOpndType.IsInt(); } } return doTypeSpec; }