diff options
author | Ayke van Laethem <[email protected]> | 2024-06-27 20:25:33 +0200 |
---|---|---|
committer | Ron Evans <[email protected]> | 2024-07-03 07:31:37 +0200 |
commit | 571447c7c14774dd4fe4342a35eee024aca2578a (patch) | |
tree | b28341ddb6fbc5f08861ff25e3d69834d84cb696 | |
parent | 9cb263479c4b98f2d28889ca1acc297454e0d875 (diff) | |
download | tinygo-571447c7c14774dd4fe4342a35eee024aca2578a.tar.gz tinygo-571447c7c14774dd4fe4342a35eee024aca2578a.zip |
compiler: add 'align' attribute to runtime.alloc calls
This adds something like 'align 4' to the runtime.alloc calls, so that
the compiler knows the alignment of the allocation and can optimize
accordingly.
The optimization is very small, only 0.01% in my small test. However, my
plan is to read the value in the heap-to-stack transform pass to make it
more correct and let it produce slightly more optimal code.
-rw-r--r-- | compiler/compiler.go | 4 | ||||
-rw-r--r-- | compiler/llvm.go | 2 | ||||
-rw-r--r-- | compiler/testdata/gc.ll | 32 | ||||
-rw-r--r-- | compiler/testdata/goroutine-cortex-m-qemu-tasks.ll | 8 | ||||
-rw-r--r-- | compiler/testdata/goroutine-wasm-asyncify.ll | 8 | ||||
-rw-r--r-- | compiler/testdata/slice.ll | 12 |
6 files changed, 36 insertions, 30 deletions
diff --git a/compiler/compiler.go b/compiler/compiler.go index 004dfcaa3..e9697fae2 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -2017,6 +2017,8 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) { sizeValue := llvm.ConstInt(b.uintptrType, size, false) layoutValue := b.createObjectLayout(typ, expr.Pos()) buf := b.createRuntimeCall("alloc", []llvm.Value{sizeValue, layoutValue}, expr.Comment) + align := b.targetData.ABITypeAlignment(typ) + buf.AddCallSiteAttribute(0, b.ctx.CreateEnumAttribute(llvm.AttributeKindID("align"), uint64(align))) return buf, nil } else { buf := llvmutil.CreateEntryBlockAlloca(b.Builder, typ, expr.Comment) @@ -2223,6 +2225,7 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) { sliceType := expr.Type().Underlying().(*types.Slice) llvmElemType := b.getLLVMType(sliceType.Elem()) elemSize := b.targetData.TypeAllocSize(llvmElemType) + elemAlign := b.targetData.ABITypeAlignment(llvmElemType) elemSizeValue := llvm.ConstInt(b.uintptrType, elemSize, false) maxSize := b.maxSliceSize(llvmElemType) @@ -2246,6 +2249,7 @@ func (b *builder) createExpr(expr ssa.Value) (llvm.Value, error) { sliceSize := b.CreateBinOp(llvm.Mul, elemSizeValue, sliceCapCast, "makeslice.cap") layoutValue := b.createObjectLayout(llvmElemType, expr.Pos()) slicePtr := b.createRuntimeCall("alloc", []llvm.Value{sliceSize, layoutValue}, "makeslice.buf") + slicePtr.AddCallSiteAttribute(0, b.ctx.CreateEnumAttribute(llvm.AttributeKindID("align"), uint64(elemAlign))) // Extend or truncate if necessary. This is safe as we've already done // the bounds check. diff --git a/compiler/llvm.go b/compiler/llvm.go index d693f6ed7..5d4eaaa64 100644 --- a/compiler/llvm.go +++ b/compiler/llvm.go @@ -127,12 +127,14 @@ func (b *builder) emitPointerPack(values []llvm.Value) llvm.Value { // Packed data is bigger than a pointer, so allocate it on the heap. sizeValue := llvm.ConstInt(b.uintptrType, size, false) + align := b.targetData.ABITypeAlignment(packedType) alloc := b.mod.NamedFunction("runtime.alloc") packedAlloc := b.CreateCall(alloc.GlobalValueType(), alloc, []llvm.Value{ sizeValue, llvm.ConstNull(b.dataPtrType), llvm.Undef(b.dataPtrType), // unused context parameter }, "") + packedAlloc.AddCallSiteAttribute(0, b.ctx.CreateEnumAttribute(llvm.AttributeKindID("align"), uint64(align))) if b.NeedsStackObjects { b.trackPointer(packedAlloc) } diff --git a/compiler/testdata/gc.ll b/compiler/testdata/gc.ll index a696ee409..82260fbf4 100644 --- a/compiler/testdata/gc.ll +++ b/compiler/testdata/gc.ll @@ -39,16 +39,16 @@ entry: define hidden void @main.newScalar(ptr %context) unnamed_addr #2 { entry: %stackalloc = alloca i8, align 1 - %new = call dereferenceable(1) ptr @runtime.alloc(i32 1, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 + %new = call align 1 dereferenceable(1) ptr @runtime.alloc(i32 1, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3 store ptr %new, ptr @main.scalar1, align 4 - %new1 = call dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 + %new1 = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef) #3 store ptr %new1, ptr @main.scalar2, align 4 - %new2 = call dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 + %new2 = call align 8 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef) #3 store ptr %new2, ptr @main.scalar3, align 4 - %new3 = call dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 + %new3 = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new3, ptr nonnull %stackalloc, ptr undef) #3 store ptr %new3, ptr @main.scalar4, align 4 ret void @@ -58,13 +58,13 @@ entry: define hidden void @main.newArray(ptr %context) unnamed_addr #2 { entry: %stackalloc = alloca i8, align 1 - %new = call dereferenceable(3) ptr @runtime.alloc(i32 3, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 + %new = call align 1 dereferenceable(3) ptr @runtime.alloc(i32 3, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3 store ptr %new, ptr @main.array1, align 4 - %new1 = call dereferenceable(71) ptr @runtime.alloc(i32 71, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 + %new1 = call align 1 dereferenceable(71) ptr @runtime.alloc(i32 71, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef) #3 store ptr %new1, ptr @main.array2, align 4 - %new2 = call dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #3 + %new2 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef) #3 store ptr %new2, ptr @main.array3, align 4 ret void @@ -74,16 +74,16 @@ entry: define hidden void @main.newStruct(ptr %context) unnamed_addr #2 { entry: %stackalloc = alloca i8, align 1 - %new = call ptr @runtime.alloc(i32 0, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 + %new = call align 1 ptr @runtime.alloc(i32 0, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3 store ptr %new, ptr @main.struct1, align 4 - %new1 = call dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 + %new1 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new1, ptr nonnull %stackalloc, ptr undef) #3 store ptr %new1, ptr @main.struct2, align 4 - %new2 = call dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-2000000000000001", ptr undef) #3 + %new2 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-2000000000000001", ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new2, ptr nonnull %stackalloc, ptr undef) #3 store ptr %new2, ptr @main.struct3, align 4 - %new3 = call dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-0001", ptr undef) #3 + %new3 = call align 4 dereferenceable(248) ptr @runtime.alloc(i32 248, ptr nonnull @"runtime/gc.layout:62-0001", ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new3, ptr nonnull %stackalloc, ptr undef) #3 store ptr %new3, ptr @main.struct4, align 4 ret void @@ -93,7 +93,7 @@ entry: define hidden ptr @main.newFuncValue(ptr %context) unnamed_addr #2 { entry: %stackalloc = alloca i8, align 1 - %new = call dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 197 to ptr), ptr undef) #3 + %new = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr nonnull inttoptr (i32 197 to ptr), ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %new, ptr nonnull %stackalloc, ptr undef) #3 ret ptr %new } @@ -102,17 +102,17 @@ entry: define hidden void @main.makeSlice(ptr %context) unnamed_addr #2 { entry: %stackalloc = alloca i8, align 1 - %makeslice = call dereferenceable(5) ptr @runtime.alloc(i32 5, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 + %makeslice = call align 1 dereferenceable(5) ptr @runtime.alloc(i32 5, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %makeslice, ptr nonnull %stackalloc, ptr undef) #3 store ptr %makeslice, ptr @main.slice1, align 4 store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice1, i32 0, i32 1), align 4 store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice1, i32 0, i32 2), align 4 - %makeslice1 = call dereferenceable(20) ptr @runtime.alloc(i32 20, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #3 + %makeslice1 = call align 4 dereferenceable(20) ptr @runtime.alloc(i32 20, ptr nonnull inttoptr (i32 67 to ptr), ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %makeslice1, ptr nonnull %stackalloc, ptr undef) #3 store ptr %makeslice1, ptr @main.slice2, align 4 store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice2, i32 0, i32 1), align 4 store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice2, i32 0, i32 2), align 4 - %makeslice3 = call dereferenceable(60) ptr @runtime.alloc(i32 60, ptr nonnull inttoptr (i32 71 to ptr), ptr undef) #3 + %makeslice3 = call align 4 dereferenceable(60) ptr @runtime.alloc(i32 60, ptr nonnull inttoptr (i32 71 to ptr), ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %makeslice3, ptr nonnull %stackalloc, ptr undef) #3 store ptr %makeslice3, ptr @main.slice3, align 4 store i32 5, ptr getelementptr inbounds ({ ptr, i32, i32 }, ptr @main.slice3, i32 0, i32 1), align 4 @@ -124,7 +124,7 @@ entry: define hidden %runtime._interface @main.makeInterface(double %v.r, double %v.i, ptr %context) unnamed_addr #2 { entry: %stackalloc = alloca i8, align 1 - %0 = call dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #3 + %0 = call align 8 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #3 store double %v.r, ptr %0, align 8 %.repack1 = getelementptr inbounds { double, double }, ptr %0, i32 0, i32 1 diff --git a/compiler/testdata/goroutine-cortex-m-qemu-tasks.ll b/compiler/testdata/goroutine-cortex-m-qemu-tasks.ll index 6918e7be6..f0a692c0f 100644 --- a/compiler/testdata/goroutine-cortex-m-qemu-tasks.ll +++ b/compiler/testdata/goroutine-cortex-m-qemu-tasks.ll @@ -63,9 +63,9 @@ entry: ; Function Attrs: nounwind define hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #1 { entry: - %n = call dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #9 + %n = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #9 store i32 3, ptr %n, align 4 - %0 = call dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9 + %0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9 store i32 5, ptr %0, align 4 %1 = getelementptr inbounds { i32, ptr }, ptr %0, i32 0, i32 1 store ptr %n, ptr %1, align 4 @@ -98,7 +98,7 @@ declare void @runtime.printint32(i32, ptr) #2 ; Function Attrs: nounwind define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #1 { entry: - %0 = call dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9 + %0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9 store i32 5, ptr %0, align 4 %1 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 1 store ptr %fn.context, ptr %1, align 4 @@ -148,7 +148,7 @@ declare void @runtime.chanClose(ptr dereferenceable_or_null(32), ptr) #2 ; Function Attrs: nounwind define hidden void @main.startInterfaceMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #1 { entry: - %0 = call dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9 + %0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9 store ptr %itf.value, ptr %0, align 4 %1 = getelementptr inbounds { ptr, %runtime._string, ptr }, ptr %0, i32 0, i32 1 store ptr @"main$string", ptr %1, align 4 diff --git a/compiler/testdata/goroutine-wasm-asyncify.ll b/compiler/testdata/goroutine-wasm-asyncify.ll index db7ce187f..1281857d3 100644 --- a/compiler/testdata/goroutine-wasm-asyncify.ll +++ b/compiler/testdata/goroutine-wasm-asyncify.ll @@ -66,12 +66,12 @@ entry: define hidden void @main.closureFunctionGoroutine(ptr %context) unnamed_addr #2 { entry: %stackalloc = alloca i8, align 1 - %n = call dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #9 + %n = call align 4 dereferenceable(4) ptr @runtime.alloc(i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #9 call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef) #9 store i32 3, ptr %n, align 4 call void @runtime.trackPointer(ptr nonnull %n, ptr nonnull %stackalloc, ptr undef) #9 call void @runtime.trackPointer(ptr nonnull @"main.closureFunctionGoroutine$1", ptr nonnull %stackalloc, ptr undef) #9 - %0 = call dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9 + %0 = call align 4 dereferenceable(8) ptr @runtime.alloc(i32 8, ptr null, ptr undef) #9 call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9 store i32 5, ptr %0, align 4 %1 = getelementptr inbounds { i32, ptr }, ptr %0, i32 0, i32 1 @@ -106,7 +106,7 @@ declare void @runtime.printint32(i32, ptr) #1 define hidden void @main.funcGoroutine(ptr %fn.context, ptr %fn.funcptr, ptr %context) unnamed_addr #2 { entry: %stackalloc = alloca i8, align 1 - %0 = call dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9 + %0 = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr null, ptr undef) #9 call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9 store i32 5, ptr %0, align 4 %1 = getelementptr inbounds { i32, ptr, ptr }, ptr %0, i32 0, i32 1 @@ -158,7 +158,7 @@ declare void @runtime.chanClose(ptr dereferenceable_or_null(32), ptr) #1 define hidden void @main.startInterfaceMethod(ptr %itf.typecode, ptr %itf.value, ptr %context) unnamed_addr #2 { entry: %stackalloc = alloca i8, align 1 - %0 = call dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9 + %0 = call align 4 dereferenceable(16) ptr @runtime.alloc(i32 16, ptr null, ptr undef) #9 call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #9 store ptr %itf.value, ptr %0, align 4 %1 = getelementptr inbounds { ptr, %runtime._string, ptr }, ptr %0, i32 0, i32 1 diff --git a/compiler/testdata/slice.ll b/compiler/testdata/slice.ll index 29d5ed8a4..092dabbff 100644 --- a/compiler/testdata/slice.ll +++ b/compiler/testdata/slice.ll @@ -48,7 +48,7 @@ declare void @runtime.lookupPanic(ptr) #1 define hidden { ptr, i32, i32 } @main.sliceAppendValues(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %context) unnamed_addr #2 { entry: %stackalloc = alloca i8, align 1 - %varargs = call dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 + %varargs = call align 4 dereferenceable(12) ptr @runtime.alloc(i32 12, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %varargs, ptr nonnull %stackalloc, ptr undef) #3 store i32 1, ptr %varargs, align 4 %0 = getelementptr inbounds [3 x i32], ptr %varargs, i32 0, i32 1 @@ -100,7 +100,7 @@ entry: br i1 %slice.maxcap, label %slice.throw, label %slice.next slice.next: ; preds = %entry - %makeslice.buf = call ptr @runtime.alloc(i32 %len, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 + %makeslice.buf = call align 1 ptr @runtime.alloc(i32 %len, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0 %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1 %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2 @@ -123,7 +123,7 @@ entry: slice.next: ; preds = %entry %makeslice.cap = shl nuw i32 %len, 1 - %makeslice.buf = call ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 + %makeslice.buf = call align 2 ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0 %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1 %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2 @@ -144,7 +144,7 @@ entry: slice.next: ; preds = %entry %makeslice.cap = mul i32 %len, 3 - %makeslice.buf = call ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 + %makeslice.buf = call align 1 ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0 %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1 %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2 @@ -165,7 +165,7 @@ entry: slice.next: ; preds = %entry %makeslice.cap = shl nuw i32 %len, 2 - %makeslice.buf = call ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 + %makeslice.buf = call align 4 ptr @runtime.alloc(i32 %makeslice.cap, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %0 = insertvalue { ptr, i32, i32 } undef, ptr %makeslice.buf, 0 %1 = insertvalue { ptr, i32, i32 } %0, i32 %len, 1 %2 = insertvalue { ptr, i32, i32 } %1, i32 %len, 2 @@ -216,7 +216,7 @@ declare void @runtime.sliceToArrayPointerPanic(ptr) #1 define hidden ptr @main.SliceToArrayConst(ptr %context) unnamed_addr #2 { entry: %stackalloc = alloca i8, align 1 - %makeslice = call dereferenceable(24) ptr @runtime.alloc(i32 24, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 + %makeslice = call align 4 dereferenceable(24) ptr @runtime.alloc(i32 24, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 call void @runtime.trackPointer(ptr nonnull %makeslice, ptr nonnull %stackalloc, ptr undef) #3 br i1 false, label %slicetoarray.throw, label %slicetoarray.next |