Repository: dotnet/runtime
File: src/coreclr/jit/codegenarm64.cpp (C++)

Code before:
        // regCnt will be the total number of bytes to localloc
        inst_RV_IV(INS_add, regCnt, (STACK_ALIGN - 1), emitActualTypeSize(type));
        inst_RV_IV(INS_and, regCnt, ~(STACK_ALIGN - 1), emitActualTypeSize(type));
    }

    // If we have an outgoing arg area then we must adjust the SP by popping off the
    // outgoing arg area. We will restore it right before we return from this method.
    //
    // Localloc returns stack space that aligned to STACK_ALIGN bytes. The following
    // are the cases that need to be handled:
    //   i) Method has out-going arg area.
    //      It is guaranteed that size of out-going arg area is STACK_ALIGN'ed (see fgMorphArgs).
    //      Therefore, we will pop off the out-going arg area from the stack pointer before allocating the localloc
    //      space.
    //  ii) Method has no out-going arg area.
    //      Nothing to pop off from the stack.
    if (compiler->lvaOutgoingArgSpaceSize > 0)
    {
        assert((compiler->lvaOutgoingArgSpaceSize % STACK_ALIGN) == 0); // This must be true for the stack to remain
                                                                        // aligned
        genInstrWithConstant(INS_add, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, compiler->lvaOutgoingArgSpaceSize,
                             rsGetRsvdReg());
        stackAdjustment += compiler->lvaOutgoingArgSpaceSize;
    }

    if (size->IsCnsIntOrI() && size->isContained())
    {
        // We should reach here only for non-zero, constant size allocations.
        assert(amount > 0);

        const int storePairRegsWritesBytes = 2 * REGSIZE_BYTES;

        // For small allocations we will generate up to four stp instructions, to zero 16 to 64 bytes.
        static_assert(STACK_ALIGN == storePairRegsWritesBytes);
        assert(amount % storePairRegsWritesBytes == 0); // stp stores two registers at a time

        if (amount < compiler->eeGetPageSize()) // must be < not <=
        {
            // Since the size is less than a page, simply adjust the SP value.
            // The SP might already be in the guard page, so we must touch it BEFORE
            // the alloc, not after.

            // Note the we check against the lower boundary of the post-index immediate range [-256, 256)
            // since the offset is -amount.
            const bool canEncodeLoadRegPostIndexOffset = amount <= 256;

            if (canEncodeLoadRegPostIndexOffset)
            {
                GetEmitter()->emitIns_R_R_I(INS_ldr, EA_4BYTE, REG_ZR, REG_SPBASE, -(ssize_t)amount,
                                            INS_OPTS_POST_INDEX);
            }

Review comment (suggestion):
```suggestion
    if (size->isContainedIntOrIImmed())
```

Code after:
        // regCnt will be the total number of bytes to localloc
        inst_RV_IV(INS_add, regCnt, (STACK_ALIGN - 1), emitActualTypeSize(type));
        inst_RV_IV(INS_and, regCnt, ~(STACK_ALIGN - 1), emitActualTypeSize(type));
    }

    // If we have an outgoing arg area then we must adjust the SP by popping off the
    // outgoing arg area. We will restore it right before we return from this method.
    //
    // Localloc returns stack space that aligned to STACK_ALIGN bytes. The following
    // are the cases that need to be handled:
    //   i) Method has out-going arg area.
    //      It is guaranteed that size of out-going arg area is STACK_ALIGN'ed (see fgMorphArgs).
    //      Therefore, we will pop off the out-going arg area from the stack pointer before allocating the localloc
    //      space.
    //  ii) Method has no out-going arg area.
    //      Nothing to pop off from the stack.
    if (compiler->lvaOutgoingArgSpaceSize > 0)
    {
        assert((compiler->lvaOutgoingArgSpaceSize % STACK_ALIGN) == 0); // This must be true for the stack to remain
                                                                        // aligned
        genInstrWithConstant(INS_add, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, compiler->lvaOutgoingArgSpaceSize,
                             rsGetRsvdReg());
        stackAdjustment += compiler->lvaOutgoingArgSpaceSize;
    }

    if (size->isContainedIntOrIImmed())
    {
        // We should reach here only for non-zero, constant size allocations.
        assert(amount > 0);

        const int storePairRegsWritesBytes = 2 * REGSIZE_BYTES;

        // For small allocations we will generate up to four stp instructions, to zero 16 to 64 bytes.
        static_assert(STACK_ALIGN == storePairRegsWritesBytes);
        assert(amount % storePairRegsWritesBytes == 0); // stp stores two registers at a time

        if (amount < compiler->eeGetPageSize()) // must be < not <=
        {
            // Since the size is less than a page, simply adjust the SP value.
            // The SP might already be in the guard page, so we must touch it BEFORE
            // the alloc, not after.

            // Note the we check against the lower boundary of the post-index immediate range [-256, 256)
            // since the offset is -amount.
            const bool canEncodeLoadRegPostIndexOffset = amount <= 256;

            if (canEncodeLoadRegPostIndexOffset)
            {
                GetEmitter()->emitIns_R_R_I(INS_ldr, EA_4BYTE, REG_ZR, REG_SPBASE, -(ssize_t)amount,
                                            INS_OPTS_POST_INDEX);
            }