void EffectiveAddressAnalysis::analyzeAsmHeapAccess(MAsmJSHeapAccessType* ins) { MDefinition* ptr = ins->ptr(); if (ptr->isConstantValue()) { // Look for heap[i] where i is a constant offset, and fold the offset. // By doing the folding now, we simplify the task of codegen; the offset // is always the address mode immediate. This also allows it to avoid // a situation where the sum of a constant pointer value and a non-zero // offset doesn't actually fit into the address mode immediate. int32_t imm = ptr->constantValue().toInt32(); if (imm != 0 && tryAddDisplacement(ins, imm)) { MInstruction* zero = MConstant::New(graph_.alloc(), Int32Value(0)); ins->block()->insertBefore(ins, zero); ins->replacePtr(zero); } } else if (ptr->isAdd()) { // Look for heap[a+i] where i is a constant offset, and fold the offset. // Alignment masks have already been moved out of the way by the // Alignment Mask Analysis pass. MDefinition* op0 = ptr->toAdd()->getOperand(0); MDefinition* op1 = ptr->toAdd()->getOperand(1); if (op0->isConstantValue()) mozilla::Swap(op0, op1); if (op1->isConstantValue()) { int32_t imm = op1->constantValue().toInt32(); if (tryAddDisplacement(ins, imm)) ins->replacePtr(op0); } } }
void LIRGeneratorMIPS::visitAsmJSStoreHeap(MAsmJSStoreHeap *ins) { MDefinition *ptr = ins->ptr(); MOZ_ASSERT(ptr->type() == MIRType_Int32); LAllocation ptrAlloc; if (ptr->isConstantValue() && !ins->needsBoundsCheck()) { MOZ_ASSERT(ptr->constantValue().toInt32() >= 0); ptrAlloc = LAllocation(ptr->constantVp()); } else ptrAlloc = useRegisterAtStart(ptr); add(new(alloc()) LAsmJSStoreHeap(ptrAlloc, useRegisterAtStart(ins->value())), ins); }
void LIRGeneratorMIPS::visitAsmJSLoadHeap(MAsmJSLoadHeap *ins) { MDefinition *ptr = ins->ptr(); MOZ_ASSERT(ptr->type() == MIRType_Int32); LAllocation ptrAlloc; // For MIPS it is best to keep the 'ptr' in a register if a bounds check // is needed. if (ptr->isConstantValue() && !ins->needsBoundsCheck()) { // A bounds check is only skipped for a positive index. MOZ_ASSERT(ptr->constantValue().toInt32() >= 0); ptrAlloc = LAllocation(ptr->constantVp()); } else ptrAlloc = useRegisterAtStart(ptr); define(new(alloc()) LAsmJSLoadHeap(ptrAlloc), ins); }
static void AnalyzeLsh(TempAllocator& alloc, MLsh* lsh) { if (lsh->specialization() != MIRType_Int32) return; if (lsh->isRecoveredOnBailout()) return; MDefinition* index = lsh->lhs(); MOZ_ASSERT(index->type() == MIRType_Int32); MDefinition* shift = lsh->rhs(); if (!shift->isConstantValue()) return; Value shiftValue = shift->constantValue(); if (!shiftValue.isInt32() || !IsShiftInScaleRange(shiftValue.toInt32())) return; Scale scale = ShiftToScale(shiftValue.toInt32()); int32_t displacement = 0; MInstruction* last = lsh; MDefinition* base = nullptr; while (true) { if (!last->hasOneUse()) break; MUseIterator use = last->usesBegin(); if (!use->consumer()->isDefinition() || !use->consumer()->toDefinition()->isAdd()) break; MAdd* add = use->consumer()->toDefinition()->toAdd(); if (add->specialization() != MIRType_Int32 || !add->isTruncated()) break; MDefinition* other = add->getOperand(1 - add->indexOf(*use)); if (other->isConstantValue()) { displacement += other->constantValue().toInt32(); } else { if (base) break; base = other; } last = add; if (last->isRecoveredOnBailout()) return; } if (!base) { uint32_t elemSize = 1 << ScaleToShift(scale); if (displacement % elemSize != 0) return; if (!last->hasOneUse()) return; MUseIterator use = last->usesBegin(); if (!use->consumer()->isDefinition() || !use->consumer()->toDefinition()->isBitAnd()) return; MBitAnd* bitAnd = use->consumer()->toDefinition()->toBitAnd(); if (bitAnd->isRecoveredOnBailout()) return; MDefinition* other = bitAnd->getOperand(1 - bitAnd->indexOf(*use)); if (!other->isConstantValue() || !other->constantValue().isInt32()) return; uint32_t bitsClearedByShift = elemSize - 1; uint32_t bitsClearedByMask = ~uint32_t(other->constantValue().toInt32()); if ((bitsClearedByShift & bitsClearedByMask) != bitsClearedByMask) return; bitAnd->replaceAllUsesWith(last); return; } if (base->isRecoveredOnBailout()) return; MEffectiveAddress* eaddr = MEffectiveAddress::New(alloc, base, index, scale, displacement); last->replaceAllUsesWith(eaddr); last->block()->insertAfter(last, eaddr); }