From ca823f9a0ddc2f07e9c911687155128bbba962dd Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Wed, 1 Mar 2023 22:02:17 +0100 Subject: [PATCH] compiler: remove unsafe.Pointer(uintptr(v) + idx) optimization I have checked this conversion is not needed anymore after the previous commit, by running various smoke tests of which none triggered this optimization. The only case where the optimization would have kicked in is in syscall/syscall_windows.go:76 of the Go standard library. Therefore, I prefer to remove it to reduce code complexity. --- compiler/compiler.go | 25 ------------------------- compiler/testdata/pointer.go | 15 --------------- compiler/testdata/pointer.ll | 34 ---------------------------------- 3 files changed, 74 deletions(-) diff --git a/compiler/compiler.go b/compiler/compiler.go index 8b540d35..264dfdc5 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -2900,31 +2900,6 @@ func (b *builder) createConvert(typeFrom, typeTo types.Type, value llvm.Value, p if isPtrFrom && !isPtrTo { return b.CreatePtrToInt(value, llvmTypeTo, ""), nil } else if !isPtrFrom && isPtrTo { - if !value.IsABinaryOperator().IsNil() && value.InstructionOpcode() == llvm.Add { - // This is probably a pattern like the following: - // unsafe.Pointer(uintptr(ptr) + index) - // Used in functions like memmove etc. for lack of pointer - // arithmetic. Convert it to real pointer arithmatic here. - ptr := value.Operand(0) - index := value.Operand(1) - if !index.IsAPtrToIntInst().IsNil() { - // Swap if necessary, if ptr and index are reversed. - ptr, index = index, ptr - } - if !ptr.IsAPtrToIntInst().IsNil() { - origptr := ptr.Operand(0) - if origptr.Type() == b.i8ptrType { - // This pointer can be calculated from the original - // ptrtoint instruction with a GEP. The leftover inttoptr - // instruction is trivial to optimize away. - // Making it an in bounds GEP even though it's easy to - // create a GEP that is not in bounds. However, we're - // talking about unsafe code here so the programmer has to - // be careful anyway. - return b.CreateInBoundsGEP(b.ctx.Int8Type(), origptr, []llvm.Value{index}, ""), nil - } - } - } return b.CreateIntToPtr(value, llvmTypeTo, ""), nil } diff --git a/compiler/testdata/pointer.go b/compiler/testdata/pointer.go index 84a983c3..6575dd83 100644 --- a/compiler/testdata/pointer.go +++ b/compiler/testdata/pointer.go @@ -24,18 +24,3 @@ func pointerCastToUnsafe(x *int) unsafe.Pointer { func pointerCastToUnsafeNoop(x *byte) unsafe.Pointer { return unsafe.Pointer(x) } - -// The compiler has support for a few special cast+add patterns that are -// transformed into a single GEP. - -func pointerUnsafeGEPFixedOffset(ptr *byte) *byte { - return (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(ptr)) + 10)) -} - -func pointerUnsafeGEPByteOffset(ptr *byte, offset uintptr) *byte { - return (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(ptr)) + offset)) -} - -func pointerUnsafeGEPIntOffset(ptr *int32, offset uintptr) *int32 { - return (*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(ptr)) + offset*4)) -} diff --git a/compiler/testdata/pointer.ll b/compiler/testdata/pointer.ll index ac1a4bc7..3cbf70a3 100644 --- a/compiler/testdata/pointer.ll +++ b/compiler/testdata/pointer.ll @@ -43,40 +43,6 @@ entry: ret ptr %x } -; Function Attrs: nounwind -define hidden ptr @main.pointerUnsafeGEPFixedOffset(ptr dereferenceable_or_null(1) %ptr, ptr %context) unnamed_addr #1 { -entry: - %stackalloc = alloca i8, align 1 - call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #2 - %0 = getelementptr inbounds i8, ptr %ptr, i32 10 - call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #2 - call void @runtime.trackPointer(ptr nonnull %0, ptr nonnull %stackalloc, ptr undef) #2 - ret ptr %0 -} - -; Function Attrs: nounwind -define hidden ptr @main.pointerUnsafeGEPByteOffset(ptr dereferenceable_or_null(1) %ptr, i32 %offset, ptr %context) unnamed_addr #1 { -entry: - %stackalloc = alloca i8, align 1 - call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #2 - %0 = getelementptr inbounds i8, ptr %ptr, i32 %offset - call void @runtime.trackPointer(ptr %0, ptr nonnull %stackalloc, ptr undef) #2 - call void @runtime.trackPointer(ptr %0, ptr nonnull %stackalloc, ptr undef) #2 - ret ptr %0 -} - -; Function Attrs: nounwind -define hidden ptr @main.pointerUnsafeGEPIntOffset(ptr dereferenceable_or_null(4) %ptr, i32 %offset, ptr %context) unnamed_addr #1 { -entry: - %stackalloc = alloca i8, align 1 - call void @runtime.trackPointer(ptr %ptr, ptr nonnull %stackalloc, ptr undef) #2 - %0 = shl i32 %offset, 2 - %1 = getelementptr inbounds i8, ptr %ptr, i32 %0 - call void @runtime.trackPointer(ptr %1, ptr nonnull %stackalloc, ptr undef) #2 - call void @runtime.trackPointer(ptr %1, ptr nonnull %stackalloc, ptr undef) #2 - ret ptr %1 -} - attributes #0 = { "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" } attributes #1 = { nounwind "target-features"="+bulk-memory,+nontrapping-fptoint,+sign-ext" } attributes #2 = { nounwind }