optimize constant length `memorynew` intrinsic (take 2) (#56847)
replaces https://github.com/JuliaLang/julia/pull/55913 (the rebase was
more annoying than starting from scratch)
This allows the compiler to better understand what's going on for
`memorynew` with compile-time constant length, allowing for LLVM level
escape analysis in some cases. There is more room to grow this
(currently this only optimizes for fairly small Memory since bigger ones
would require writing some more LLVM code, and we probably want a size
limit on putting Memory on the stack to avoid stackoverflow. For larger
ones, we could potentially inline the free so the Memory doesn't have to
be swept by the GC, etc.
```
julia> function g()
m = Memory{Int}(undef, 2)
for i in 1:2
m[i] = i
end
m[1]+m[2]
end
julia> @btime g()
9.735 ns (1 allocation: 48 bytes) #before
1.719 ns (0 allocations: 0 bytes) #after
```