1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit/EffectiveAddressAnalysis.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,116 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "jit/EffectiveAddressAnalysis.h" 1.11 +#include "jit/MIR.h" 1.12 +#include "jit/MIRGraph.h" 1.13 + 1.14 +using namespace js; 1.15 +using namespace jit; 1.16 + 1.17 +static void 1.18 +AnalyzeLsh(TempAllocator &alloc, MLsh *lsh) 1.19 +{ 1.20 + if (lsh->specialization() != MIRType_Int32) 1.21 + return; 1.22 + 1.23 + MDefinition *index = lsh->lhs(); 1.24 + JS_ASSERT(index->type() == MIRType_Int32); 1.25 + 1.26 + MDefinition *shift = lsh->rhs(); 1.27 + if (!shift->isConstant()) 1.28 + return; 1.29 + 1.30 + Value shiftValue = shift->toConstant()->value(); 1.31 + if (!shiftValue.isInt32() || !IsShiftInScaleRange(shiftValue.toInt32())) 1.32 + return; 1.33 + 1.34 + Scale scale = ShiftToScale(shiftValue.toInt32()); 1.35 + 1.36 + int32_t displacement = 0; 1.37 + MInstruction *last = lsh; 1.38 + MDefinition *base = nullptr; 1.39 + while (true) { 1.40 + if (!last->hasOneUse()) 1.41 + break; 1.42 + 1.43 + MUseIterator use = last->usesBegin(); 1.44 + if (!use->consumer()->isDefinition() || !use->consumer()->toDefinition()->isAdd()) 1.45 + break; 1.46 + 1.47 + MAdd *add = use->consumer()->toDefinition()->toAdd(); 1.48 + if (add->specialization() != MIRType_Int32 || !add->isTruncated()) 1.49 + break; 1.50 + 1.51 + MDefinition *other = add->getOperand(1 - use->index()); 1.52 + 1.53 + if (other->isConstant()) { 1.54 + displacement += other->toConstant()->value().toInt32(); 1.55 + } else { 1.56 + if (base) 1.57 + break; 1.58 + base = other; 1.59 + } 1.60 + 1.61 + last = add; 1.62 + } 1.63 + 1.64 + if (!base) { 1.65 + uint32_t elemSize = 1 << ScaleToShift(scale); 1.66 + if (displacement % elemSize != 0) 1.67 + return; 1.68 + 1.69 + if (!last->hasOneUse()) 1.70 + return; 1.71 + 1.72 + MUseIterator use = last->usesBegin(); 1.73 + if (!use->consumer()->isDefinition() || !use->consumer()->toDefinition()->isBitAnd()) 1.74 + return; 1.75 + 1.76 + MBitAnd *bitAnd = use->consumer()->toDefinition()->toBitAnd(); 1.77 + MDefinition *other = bitAnd->getOperand(1 - use->index()); 1.78 + if (!other->isConstant() || !other->toConstant()->value().isInt32()) 1.79 + return; 1.80 + 1.81 + uint32_t bitsClearedByShift = elemSize - 1; 1.82 + uint32_t bitsClearedByMask = ~uint32_t(other->toConstant()->value().toInt32()); 1.83 + if ((bitsClearedByShift & bitsClearedByMask) != bitsClearedByMask) 1.84 + return; 1.85 + 1.86 + bitAnd->replaceAllUsesWith(last); 1.87 + return; 1.88 + } 1.89 + 1.90 + MEffectiveAddress *eaddr = MEffectiveAddress::New(alloc, base, index, scale, displacement); 1.91 + last->replaceAllUsesWith(eaddr); 1.92 + last->block()->insertAfter(last, eaddr); 1.93 +} 1.94 + 1.95 +// This analysis converts patterns of the form: 1.96 +// truncate(x + (y << {0,1,2,3})) 1.97 +// truncate(x + (y << {0,1,2,3}) + imm32) 1.98 +// into a single lea instruction, and patterns of the form: 1.99 +// asmload(x + imm32) 1.100 +// asmload(x << {0,1,2,3}) 1.101 +// asmload((x << {0,1,2,3}) + imm32) 1.102 +// asmload((x << {0,1,2,3}) & mask) (where mask is redundant with shift) 1.103 +// asmload(((x << {0,1,2,3}) + imm32) & mask) (where mask is redundant with shift + imm32) 1.104 +// into a single asmload instruction (and for asmstore too). 1.105 +// 1.106 +// Additionally, we should consider the general forms: 1.107 +// truncate(x + y + imm32) 1.108 +// truncate((y << {0,1,2,3}) + imm32) 1.109 +bool 1.110 +EffectiveAddressAnalysis::analyze() 1.111 +{ 1.112 + for (ReversePostorderIterator block(graph_.rpoBegin()); block != graph_.rpoEnd(); block++) { 1.113 + for (MInstructionIterator i = block->begin(); i != block->end(); i++) { 1.114 + if (i->isLsh()) 1.115 + AnalyzeLsh(graph_.alloc(), i->toLsh()); 1.116 + } 1.117 + } 1.118 + return true; 1.119 +}