@@ -5109,215 +5109,79 @@ inline UNATIVE_OFFSET emitter::emitInsSizeSVCalcDisp(instrDesc* id, code_t code,
51095109{
51105110 instruction ins = id->idIns();
51115111 UNATIVE_OFFSET size = emitInsSize(id, code, /* includeRexPrefixSize */ true);
5112- UNATIVE_OFFSET offs;
5113- bool offsIsUpperBound = true;
5114- bool EBPbased = true;
51155112
5116- /* Is this a temporary? */
5113+ int adr;
5114+ bool EBPbased;
5115+ bool dspInByte;
5116+ bool dspIsZero;
51175117
5118- if (var < 0)
5119- {
5120- /* An address off of ESP takes an extra byte */
5118+ adr = emitComp->lvaFrameAddress(var, &EBPbased);
5119+ dsp = adr + id->idAddr()->iiaLclVar.lvaOffset();
51215120
5122- if (!emitHasFramePtr)
5123- {
5124- size++;
5125- }
5121+ dspIsZero = (dsp == 0);
51265122
5127- // The offset is already assigned. Find the temp.
5128- TempDsc* tmp = codeGen->regSet.tmpFindNum(var, RegSet::TEMP_USAGE_USED);
5129- if (tmp == nullptr)
5130- {
5131- // It might be in the free lists, if we're working on zero initializing the temps.
5132- tmp = codeGen->regSet.tmpFindNum(var, RegSet::TEMP_USAGE_FREE);
5133- }
5134- assert(tmp != nullptr);
5135- offs = tmp->tdTempOffs();
5123+ bool tryCompress = true;
51365124
5137- // We only care about the magnitude of the offset here, to determine instruction size.
5138- if (emitComp->isFramePointerUsed())
5139- {
5140- if ((int)offs < 0)
5141- {
5142- offs = -(int)offs;
5143- }
5144- }
5145- else
5146- {
5147- // SP-based offsets must already be positive.
5148- assert((int)offs >= 0);
5149- }
5125+ if (EBPbased)
5126+ {
5127+ // EBP always requires a displacement
5128+ dspIsZero = false;
51505129 }
51515130 else
51525131 {
5153-
5154- /* Get the frame offset of the (non-temp) variable */
5155-
5156- offs = dsp + emitComp->lvaFrameAddress(var, &EBPbased);
5157-
5158- /* An address off of ESP takes an extra byte */
5159-
5160- if (!EBPbased)
5161- {
5162- ++size;
5163- }
5164-
5165- /* Is this a stack parameter reference? */
5166-
5167- if ((emitComp->lvaIsParameter(var) && !emitComp->lvaParamHasLocalStackSpace(var)) ||
5168- (static_cast<unsigned>(var) == emitComp->lvaRetAddrVar))
5169- {
5170- /* If no EBP frame, arguments and ret addr are off of ESP, above temps */
5171-
5172- if (!EBPbased)
5173- {
5174- assert((int)offs >= 0);
5175- }
5176- }
5177- else
5178- {
5179- /* Locals off of EBP are at negative offsets */
5180-
5181- if (EBPbased)
5182- {
5183- #if defined(TARGET_AMD64) && !defined(UNIX_AMD64_ABI)
5184- // If localloc is not used, then ebp chaining is done and hence
5185- // offset of locals will be at negative offsets, Otherwise offsets
5186- // will be positive. In future, when RBP gets positioned in the
5187- // middle of the frame so as to optimize instruction encoding size,
5188- // the below asserts needs to be modified appropriately.
5189- // However, for Unix platforms, we always do frame pointer chaining,
5190- // so offsets from the frame pointer will always be negative.
5191- if (emitComp->compLocallocUsed || emitComp->opts.compDbgEnC)
5192- {
5193- noway_assert((int)offs >= 0);
5194- }
5195- else
5196- #endif
5197- {
5198- // Dev10 804810 - failing this assert can lead to bad codegen and runtime crashes
5199-
5200- #ifdef UNIX_AMD64_ABI
5201- const LclVarDsc* varDsc = emitComp->lvaGetDesc(var);
5202- bool isRegPassedArg = varDsc->lvIsParam && varDsc->lvIsRegArg;
5203- // Register passed args could have a stack offset of 0.
5204- noway_assert((int)offs < 0 || isRegPassedArg || emitComp->opts.IsOSR());
5205- #else // !UNIX_AMD64_ABI
5206-
5207- // OSR transitioning to RBP frame currently can have mid-frame FP
5208- noway_assert(((int)offs < 0) || emitComp->opts.IsOSR());
5209- #endif // !UNIX_AMD64_ABI
5210- }
5211-
5212- assert(emitComp->lvaTempsHaveLargerOffsetThanVars());
5213-
5214- if (IsEvexEncodableInstruction(ins) || IsApxExtendedEvexInstruction(ins))
5215- {
5216- ssize_t compressedDsp;
5217- bool fitsInByte;
5218-
5219- if (TryEvexCompressDisp8Byte(id, int(offs), &compressedDsp, &fitsInByte))
5220- {
5221- if (!TakesEvexPrefix(id))
5222- {
5223- // We mispredicted the adjusted size since we didn't know we'd use the EVEX
5224- // encoding due to comprssed displacement. So we need an additional adjustment
5225- size += emitGetEvexPrefixSize(id) - emitGetVexPrefixSize(id);
5226- }
5227- SetEvexCompressedDisplacement(id);
5228- }
5229-
5230- return size + (fitsInByte ? sizeof(char) : sizeof(int));
5231- }
5232- else if ((int)offs < 0)
5233- {
5234- // offset is negative
5235- return size + ((int(offs) >= SCHAR_MIN) ? sizeof(char) : sizeof(int));
5236- }
5237- #ifdef TARGET_AMD64
5238- else
5239- {
5240- // This case arises for localloc frames
5241- return size + ((offs <= SCHAR_MAX) ? sizeof(char) : sizeof(int));
5242- }
5243- #endif // TARGET_AMD64
5244- }
5245- }
5246- }
5247-
5248- assert((int)offs >= 0);
5132+ // An address off of ESP takes an extra byte
5133+ size++;
52495134
52505135#if !FEATURE_FIXED_OUT_ARGS
5136+ // Adjust the offset by the amount currently pushed on the CPU stack
5137+ dsp += emitCurStackLvl;
52515138
5252- /* Are we addressing off of ESP? */
5253-
5254- if (!emitHasFramePtr)
5255- {
5256- /* Adjust the effective offset if necessary */
5257-
5258- if (emitCntStackDepth)
5259- offs += emitCurStackLvl;
5260-
5261- // we could (and used to) check for the special case [sp] here but the stack offset
5262- // estimator was off, and there is very little harm in overestimating for such a
5263- // rare case.
5264- }
5265-
5139+ // At this point, the amount pushed onto the stack is an estimate and
5140+ // so we cannot reliably predict if it will be zero or if compression
5141+ // can occur. So we'll pessimize to not compressing and not using zero
5142+ // displacement here, potentially resulting in over-allocation of bytes
5143+ tryCompress = false;
5144+ dspIsZero = false;
52665145#endif // !FEATURE_FIXED_OUT_ARGS
5267-
5268- bool useSmallEncoding = false;
5146+ }
52695147
52705148 if (IsEvexEncodableInstruction(ins) || IsApxExtendedEvexInstruction(ins))
52715149 {
5272- ssize_t compressedDsp;
5273-
5274- #if !FEATURE_FIXED_OUT_ARGS
5275- if (!emitHasFramePtr)
5150+ if (tryCompress)
52765151 {
5277- // We cannot use compressed displacement because the stack offset estimator
5278- // can be off and the compression is only usable in very precise scenarios
5279- //
5280- // But we can still predict small encoding for VEX encodable instructions
5152+ ssize_t compressedDsp;
52815153
5282- if (!TakesEvexPrefix (id))
5154+ if (TryEvexCompressDisp8Byte (id, dsp, &compressedDsp, &dspInByte ))
52835155 {
5284- #ifdef TARGET_AMD64
5285- useSmallEncoding = (SCHAR_MIN <= (int)offs) && ((int)offs <= SCHAR_MAX);
5286- #else
5287- useSmallEncoding = (offs <= size_t(SCHAR_MAX));
5288- #endif
5156+ SetEvexCompressedDisplacement(id);
52895157 }
52905158 }
5159+ else if (TakesEvexPrefix(id))
5160+ {
5161+ // EVEX requires compressed displacement to fit in a byte
5162+ dspInByte = false;
5163+ }
52915164 else
5292- #endif // FEATURE_FIXED_OUT_ARGS
5293- if (TryEvexCompressDisp8Byte(id, int(offs), &compressedDsp, &useSmallEncoding))
5294- {
5295- if (!TakesEvexPrefix(id))
5296- {
5297- // We mispredicted the adjusted size since we didn't know we'd use the EVEX
5298- // encoding due to compressed displacement. So we need an additional adjustment
5299- size += emitGetEvexPrefixSize(id) - emitGetVexPrefixSize(id);
5300- }
5301- SetEvexCompressedDisplacement(id);
5302- }
5165+ {
5166+ dspInByte = ((signed char)dsp == (ssize_t)dsp);
5167+ }
53035168 }
53045169 else
53055170 {
5306- #ifdef TARGET_AMD64
5307- useSmallEncoding = (SCHAR_MIN <= (int)offs) && ((int)offs <= SCHAR_MAX);
5308- #else
5309- useSmallEncoding = (offs <= size_t(SCHAR_MAX));
5310- #endif
5171+ dspInByte = ((signed char)dsp == (ssize_t)dsp);
53115172 }
53125173
5313- // If it is ESP based, and the offset is zero, we will not encode the disp part.
5314- if (!EBPbased && (offs == 0))
5174+ if (dspIsZero)
53155175 {
53165176 return size;
53175177 }
5178+ else if (dspInByte)
5179+ {
5180+ return size + sizeof(char);
5181+ }
53185182 else
53195183 {
5320- return size + (useSmallEncoding ? sizeof(char) : sizeof( int) );
5184+ return size + sizeof(int);
53215185 }
53225186}
53235187
@@ -5326,24 +5190,24 @@ inline UNATIVE_OFFSET emitter::emitInsSizeSV(instrDesc* id, code_t code, int var
53265190 assert(id->idIns() != INS_invalid);
53275191 instruction ins = id->idIns();
53285192 emitAttr attrSize = id->idOpSize();
5329- UNATIVE_OFFSET prefix = emitGetAdjustedSize(id, code);
5193+ UNATIVE_OFFSET size = emitInsSizeSVCalcDisp(id, code, var, dsp);
5194+
5195+ size += emitGetAdjustedSize(id, code);
53305196
53315197 // REX prefix
53325198 if (TakesRexWPrefix(id) || IsExtendedReg(id->idReg1(), attrSize) || IsExtendedReg(id->idReg2(), attrSize))
53335199 {
5334- prefix += emitGetRexPrefixSize(id, ins);
5200+ size += emitGetRexPrefixSize(id, ins);
53355201 }
53365202
5337- return prefix + emitInsSizeSVCalcDisp(id, code, var, dsp) ;
5203+ return size ;
53385204}
53395205
53405206inline UNATIVE_OFFSET emitter::emitInsSizeSV(instrDesc* id, code_t code, int var, int dsp, int val)
53415207{
53425208 assert(id->idIns() != INS_invalid);
53435209 instruction ins = id->idIns();
5344- emitAttr attrSize = id->idOpSize();
5345- UNATIVE_OFFSET valSize = EA_SIZE_IN_BYTES(attrSize);
5346- UNATIVE_OFFSET prefix = emitGetAdjustedSize(id, code);
5210+ UNATIVE_OFFSET valSize = EA_SIZE_IN_BYTES(id->idOpSize());
53475211 bool valInByte = ((signed char)val == val) && (ins != INS_mov) && (ins != INS_test);
53485212
53495213#ifdef TARGET_AMD64
@@ -5372,13 +5236,7 @@ inline UNATIVE_OFFSET emitter::emitInsSizeSV(instrDesc* id, code_t code, int var
53725236 assert(!IsSSEOrAVXInstruction(ins));
53735237 }
53745238
5375- // 64-bit operand instructions will need a REX.W prefix
5376- if (TakesRexWPrefix(id) || IsExtendedReg(id->idReg1(), attrSize) || IsExtendedReg(id->idReg2(), attrSize))
5377- {
5378- prefix += emitGetRexPrefixSize(id, ins);
5379- }
5380-
5381- return prefix + valSize + emitInsSizeSVCalcDisp(id, code, var, dsp);
5239+ return valSize + emitInsSizeSV(id, code, var, dsp);
53825240}
53835241
53845242/*****************************************************************************/
0 commit comments