ldc
ldc copied to clipboard
Pointer comparisons no longer work with opaque pointers, code review needed
With opaque pointers, we can no longer check if types are the same by comparing pointer types. It lead to a miscompilation bug here: https://github.com/ldc-developers/ldc/pull/4257#issuecomment-1312846914 , fixed in same PR.
I think we need to review all uses of ->getType() == (and more of this type of code)
Potential bugs with opaque pointers (the list is longer):
gen/irstate.cpp:
137 LLConstant *initializer,
138 Dsymbol *symbolForLinkageAndVisibility) {
139: if (initializer->getType() == globalVar->getValueType()) {
140 defineGlobal(globalVar, initializer, symbolForLinkageAndVisibility);
gen/llvmhelpers.cpp:
462 }
463 #else
464: assert(r->getType() == lit);
465 #endif
466 }
...
514
515 LLValue *rval = DtoRVal(val);
516: if (rval->getType() == tolltype) {
517 return new DImValue(_to, rval);
518 }
...
615 if (fromsz == tosz) {
616 rval = DtoRVal(val);
617: assert(rval->getType() == tolltype);
618 } else if (fromsz < tosz) {
619 rval = new llvm::FPExtInst(DtoRVal(val), tolltype, "", gIR->scopebb());
...
798 LLType *tll = DtoType(tb);
799
800: if (rval->getType() == tll) {
801 return new DImValue(to, rval);
802 }
Assert bugs:
gen/dvalue.cpp:
77
78 DConstValue::DConstValue(Type *t, LLConstant *con) : DRValue(t, con) {
79: assert(con->getType() == DtoType(t));
80 }
...
158
159 DSpecialRefValue::DSpecialRefValue(Type *t, LLValue *v) : DLValue(v, t) {
160: assert(v->getType() == DtoPtrToType(t)->getPointerTo());
161 }
gen/functions.cpp:
896 // The argument is an appropriate lvalue passed by reference.
897 // Use the passed pointer as parameter storage.
898: assert(irparam->value->getType() == DtoPtrToType(paramType));
I think a good overall check is to verify that compilation output did not change --opaque-pointers=true/false (works with LLVM15). If we release with LLVM15, I think it is best to default to --opaque-pointers==false.
That only kicks the can down the road to LLVM16, where --opaque-pointers=true is not an option. I think our release should with --opaque-pointers=false, but I think betas should be with --opaque-pointers=true with a release note/forum posts stating that miscompilation bugs are likely, and if you encounter one, try --opaque-pointers=false and see if it still happens.
Ouch! Such a hassle that whole opaque pointers stuff. And probably hard to detect such bugs in user code, so I don't think it's even an option for a beta.
I think a good overall check is to verify that compilation output did not change --opaque-pointers=true/false (works with LLVM15).
You mean checking the asm/machine code? I guess that could work indeed (possibly with -O to get rid of potentially small diffs), if we did that for the entire test suite.
I'm using this script to check the binary output of object files .o of compiling druntime:
# build druntime with and without opaque pointers
set -e
LDC_BUILDDIR=/Users/johan/ldc/build15
DRUNTIME_SRC_DIR=/Users/johan/ldc/ldc/runtime/druntime/src
DRUNTIME_SRC="core/atomic.d core/attribute.d core/bitop.d core/builtins.d core/checkedint.d core/cpuid.d core/demangle.d core/exception.d core/gc/config.d core/gc/gcinterface.d core/gc/registry.d core/int128.d core/internal/abort.d core/internal/array/appending.d core/internal/array/capacity.d core/internal/array/casting.d core/internal/array/comparison.d core/internal/array/concatenation.d core/internal/array/construction.d core/internal/array/equality.d core/internal/array/operations.d core/internal/array/utils.d core/internal/atomic.d core/internal/attributes.d core/internal/backtrace/dwarf.d core/internal/backtrace/elf.d core/internal/backtrace/handler.d core/internal/backtrace/libunwind.d core/internal/backtrace/macho.d core/internal/backtrace/unwind.d core/internal/container/array.d core/internal/container/common.d core/internal/container/hashtab.d core/internal/container/treap.d core/internal/convert.d core/internal/dassert.d core/internal/destruction.d core/internal/elf/dl.d core/internal/elf/io.d core/internal/entrypoint.d core/internal/execinfo.d core/internal/gc/bits.d core/internal/gc/impl/conservative/gc.d core/internal/gc/impl/manual/gc.d core/internal/gc/impl/proto/gc.d core/internal/gc/os.d core/internal/gc/pooltable.d core/internal/gc/proxy.d core/internal/hash.d core/internal/lifetime.d core/internal/moving.d core/internal/parseoptions.d core/internal/postblit.d core/internal/qsort.d core/internal/spinlock.d core/internal/string.d core/internal/switch_.d core/internal/traits.d core/internal/utf.d core/internal/util/array.d core/internal/util/math.d core/internal/vararg/aarch64.d core/internal/vararg/sysv_x64.d core/lifetime.d core/math.d core/memory.d core/runtime.d core/simd.d core/stdc/assert_.d core/stdc/complex.d core/stdc/config.d core/stdc/ctype.d core/stdc/errno.d core/stdc/fenv.d core/stdc/float_.d core/stdc/inttypes.d core/stdc/limits.d core/stdc/locale.d core/stdc/math.d core/stdc/signal.d core/stdc/stdarg.d core/stdc/stddef.d core/stdc/stdint.d core/stdc/stdio.d core/stdc/stdlib.d core/stdc/string.d core/stdc/tgmath.d core/stdc/time.d core/stdc/wchar_.d core/stdc/wctype.d core/stdcpp/allocator.d core/stdcpp/array.d core/stdcpp/exception.d core/stdcpp/memory.d core/stdcpp/new_.d core/stdcpp/string.d core/stdcpp/string_view.d core/stdcpp/type_traits.d core/stdcpp/typeinfo.d core/stdcpp/utility.d core/stdcpp/vector.d core/stdcpp/xutility.d core/sync/barrier.d core/sync/condition.d core/sync/config.d core/sync/event.d core/sync/exception.d core/sync/mutex.d core/sync/rwmutex.d core/sync/semaphore.d core/thread/context.d core/thread/fiber.d core/thread/osthread.d core/thread/package.d core/thread/threadbase.d core/thread/threadgroup.d core/thread/types.d core/time.d core/vararg.d core/volatile.d ldc/asan.d ldc/attributes.d ldc/dcompute.d ldc/eh_msvc.d ldc/sanitizer_common.d ldc/sanitizers_optionally_linked.d object.d rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d rt/arraycat.d rt/cast_.d rt/config.d rt/cover.d rt/critical_.d rt/deh.d rt/deh_win64_posix.d rt/dmain2.d rt/dso.d rt/dwarfeh.d rt/ehalloc.d rt/invariant.d rt/lifetime.d rt/memory.d rt/minfo.d rt/monitor_.d rt/msvc.d rt/msvc_math.d rt/profilegc.d rt/sections.d rt/sections_android.d rt/sections_darwin_64.d rt/sections_elf_shared.d rt/sections_ldc.d rt/sections_win64.d rt/tlsgc.d rt/trace.d rt/tracegc.d rt/util/typeinfo.d rt/util/utility.d core/sys/posix/aio.d core/sys/posix/arpa/inet.d core/sys/posix/config.d core/sys/posix/dirent.d core/sys/posix/dlfcn.d core/sys/posix/fcntl.d core/sys/posix/grp.d core/sys/posix/iconv.d core/sys/posix/inttypes.d core/sys/posix/libgen.d core/sys/posix/locale.d core/sys/posix/mqueue.d core/sys/posix/net/if_.d core/sys/posix/netdb.d core/sys/posix/netinet/in_.d core/sys/posix/netinet/tcp.d core/sys/posix/poll.d core/sys/posix/pthread.d core/sys/posix/pwd.d core/sys/posix/sched.d core/sys/posix/semaphore.d core/sys/posix/setjmp.d core/sys/posix/signal.d core/sys/posix/spawn.d core/sys/posix/stdc/time.d core/sys/posix/stdio.d core/sys/posix/stdlib.d core/sys/posix/string.d core/sys/posix/strings.d core/sys/posix/sys/filio.d core/sys/posix/sys/ioccom.d core/sys/posix/sys/ioctl.d core/sys/posix/sys/ipc.d core/sys/posix/sys/mman.d core/sys/posix/sys/msg.d core/sys/posix/sys/resource.d core/sys/posix/sys/select.d core/sys/posix/sys/shm.d core/sys/posix/sys/socket.d core/sys/posix/sys/stat.d core/sys/posix/sys/statvfs.d core/sys/posix/sys/time.d core/sys/posix/sys/ttycom.d core/sys/posix/sys/types.d core/sys/posix/sys/uio.d core/sys/posix/sys/un.d core/sys/posix/sys/utsname.d core/sys/posix/sys/wait.d core/sys/posix/syslog.d core/sys/posix/termios.d core/sys/posix/time.d core/sys/posix/ucontext.d core/sys/posix/unistd.d core/sys/posix/utime.d core/sys/darwin/crt_externs.d core/sys/darwin/dlfcn.d core/sys/darwin/err.d core/sys/darwin/execinfo.d core/sys/darwin/fcntl.d core/sys/darwin/ifaddrs.d core/sys/darwin/mach/dyld.d core/sys/darwin/mach/getsect.d core/sys/darwin/mach/kern_return.d core/sys/darwin/mach/loader.d core/sys/darwin/mach/nlist.d core/sys/darwin/mach/port.d core/sys/darwin/mach/semaphore.d core/sys/darwin/mach/stab.d core/sys/darwin/mach/thread_act.d core/sys/darwin/netinet/in_.d core/sys/darwin/pthread.d core/sys/darwin/stdlib.d core/sys/darwin/string.d core/sys/darwin/sys/attr.d core/sys/darwin/sys/cdefs.d core/sys/darwin/sys/event.d core/sys/darwin/sys/mman.d core/sys/darwin/sys/sysctl.d"
pushd $DRUNTIME_SRC_DIR
$LDC_BUILDDIR/bin/ldc2 -c --output-o -conf= -w -de -preview=dip1000 -preview=dtorfields -preview=fieldwise -d-version=SupportSanitizers -I$DRUNTIME_SRC_DIR -od=$LDC_BUILDDIR/runtime/objects-opaque --opaque-pointers=true -op $DRUNTIME_SRC
$LDC_BUILDDIR/bin/ldc2 -c --output-o -conf= -w -de -preview=dip1000 -preview=dtorfields -preview=fieldwise -d-version=SupportSanitizers -I$DRUNTIME_SRC_DIR -od=$LDC_BUILDDIR/runtime/objects-not-opaque --opaque-pointers=false -op $DRUNTIME_SRC
popd
# Check if the object files differ
for fd in $DRUNTIME_SRC
do
# replace '.d' with '.o'
fo="${fd:0:${#fd}-2}"".o"
diff -q $LDC_BUILDDIR/runtime/objects-opaque/$fo $LDC_BUILDDIR/runtime/objects-not-opaque/$fo || :
done
The output with LLVM14 and LLVM15 on macOS arm64 :
Files /Users/johan/ldc/build15/runtime/objects-opaque/core/thread/fiber.o and /Users/johan/ldc/build15/runtime/objects-not-opaque/core/thread/fiber.o differ
Files /Users/johan/ldc/build15/runtime/objects-opaque/core/thread/osthread.o and /Users/johan/ldc/build15/runtime/objects-not-opaque/core/thread/osthread.o differ
Files /Users/johan/ldc/build15/runtime/objects-opaque/core/thread/threadbase.o and /Users/johan/ldc/build15/runtime/objects-not-opaque/core/thread/threadbase.o differ
Files /Users/johan/ldc/build15/runtime/objects-opaque/rt/monitor_.o and /Users/johan/ldc/build15/runtime/objects-not-opaque/rt/monitor_.o differ
Not too bad :)
Edit: you will need at least this PR to test it: https://github.com/ldc-developers/ldc/pull/4263
For Phobos:
# build druntime with and without opaque pointers
set -e
LDC_BUILDDIR=/Users/johan/ldc/build15
DRUNTIME_SRC_DIR=/Users/johan/ldc/ldc/runtime/druntime/src
DRUNTIME_SRC="core/atomic.d core/attribute.d core/bitop.d core/builtins.d core/checkedint.d core/cpuid.d core/demangle.d core/exception.d core/gc/config.d core/gc/gcinterface.d core/gc/registry.d core/int128.d core/internal/abort.d core/internal/array/appending.d core/internal/array/capacity.d core/internal/array/casting.d core/internal/array/comparison.d core/internal/array/concatenation.d core/internal/array/construction.d core/internal/array/equality.d core/internal/array/operations.d core/internal/array/utils.d core/internal/atomic.d core/internal/attributes.d core/internal/backtrace/dwarf.d core/internal/backtrace/elf.d core/internal/backtrace/handler.d core/internal/backtrace/libunwind.d core/internal/backtrace/macho.d core/internal/backtrace/unwind.d core/internal/container/array.d core/internal/container/common.d core/internal/container/hashtab.d core/internal/container/treap.d core/internal/convert.d core/internal/dassert.d core/internal/destruction.d core/internal/elf/dl.d core/internal/elf/io.d core/internal/entrypoint.d core/internal/execinfo.d core/internal/gc/bits.d core/internal/gc/impl/conservative/gc.d core/internal/gc/impl/manual/gc.d core/internal/gc/impl/proto/gc.d core/internal/gc/os.d core/internal/gc/pooltable.d core/internal/gc/proxy.d core/internal/hash.d core/internal/lifetime.d core/internal/moving.d core/internal/parseoptions.d core/internal/postblit.d core/internal/qsort.d core/internal/spinlock.d core/internal/string.d core/internal/switch_.d core/internal/traits.d core/internal/utf.d core/internal/util/array.d core/internal/util/math.d core/internal/vararg/aarch64.d core/internal/vararg/sysv_x64.d core/lifetime.d core/math.d core/memory.d core/runtime.d core/simd.d core/stdc/assert_.d core/stdc/complex.d core/stdc/config.d core/stdc/ctype.d core/stdc/errno.d core/stdc/fenv.d core/stdc/float_.d core/stdc/inttypes.d core/stdc/limits.d core/stdc/locale.d core/stdc/math.d core/stdc/signal.d core/stdc/stdarg.d core/stdc/stddef.d core/stdc/stdint.d core/stdc/stdio.d core/stdc/stdlib.d core/stdc/string.d core/stdc/tgmath.d core/stdc/time.d core/stdc/wchar_.d core/stdc/wctype.d core/stdcpp/allocator.d core/stdcpp/array.d core/stdcpp/exception.d core/stdcpp/memory.d core/stdcpp/new_.d core/stdcpp/string.d core/stdcpp/string_view.d core/stdcpp/type_traits.d core/stdcpp/typeinfo.d core/stdcpp/utility.d core/stdcpp/vector.d core/stdcpp/xutility.d core/sync/barrier.d core/sync/condition.d core/sync/config.d core/sync/event.d core/sync/exception.d core/sync/mutex.d core/sync/rwmutex.d core/sync/semaphore.d core/thread/context.d core/thread/fiber.d core/thread/osthread.d core/thread/package.d core/thread/threadbase.d core/thread/threadgroup.d core/thread/types.d core/time.d core/vararg.d core/volatile.d ldc/asan.d ldc/attributes.d ldc/dcompute.d ldc/eh_msvc.d ldc/sanitizer_common.d ldc/sanitizers_optionally_linked.d object.d rt/aApply.d rt/aApplyR.d rt/aaA.d rt/adi.d rt/arrayassign.d rt/arraycat.d rt/cast_.d rt/config.d rt/cover.d rt/critical_.d rt/deh.d rt/deh_win64_posix.d rt/dmain2.d rt/dso.d rt/dwarfeh.d rt/ehalloc.d rt/invariant.d rt/lifetime.d rt/memory.d rt/minfo.d rt/monitor_.d rt/msvc.d rt/msvc_math.d rt/profilegc.d rt/sections.d rt/sections_android.d rt/sections_darwin_64.d rt/sections_elf_shared.d rt/sections_ldc.d rt/sections_win64.d rt/tlsgc.d rt/trace.d rt/tracegc.d rt/util/typeinfo.d rt/util/utility.d core/sys/posix/aio.d core/sys/posix/arpa/inet.d core/sys/posix/config.d core/sys/posix/dirent.d core/sys/posix/dlfcn.d core/sys/posix/fcntl.d core/sys/posix/grp.d core/sys/posix/iconv.d core/sys/posix/inttypes.d core/sys/posix/libgen.d core/sys/posix/locale.d core/sys/posix/mqueue.d core/sys/posix/net/if_.d core/sys/posix/netdb.d core/sys/posix/netinet/in_.d core/sys/posix/netinet/tcp.d core/sys/posix/poll.d core/sys/posix/pthread.d core/sys/posix/pwd.d core/sys/posix/sched.d core/sys/posix/semaphore.d core/sys/posix/setjmp.d core/sys/posix/signal.d core/sys/posix/spawn.d core/sys/posix/stdc/time.d core/sys/posix/stdio.d core/sys/posix/stdlib.d core/sys/posix/string.d core/sys/posix/strings.d core/sys/posix/sys/filio.d core/sys/posix/sys/ioccom.d core/sys/posix/sys/ioctl.d core/sys/posix/sys/ipc.d core/sys/posix/sys/mman.d core/sys/posix/sys/msg.d core/sys/posix/sys/resource.d core/sys/posix/sys/select.d core/sys/posix/sys/shm.d core/sys/posix/sys/socket.d core/sys/posix/sys/stat.d core/sys/posix/sys/statvfs.d core/sys/posix/sys/time.d core/sys/posix/sys/ttycom.d core/sys/posix/sys/types.d core/sys/posix/sys/uio.d core/sys/posix/sys/un.d core/sys/posix/sys/utsname.d core/sys/posix/sys/wait.d core/sys/posix/syslog.d core/sys/posix/termios.d core/sys/posix/time.d core/sys/posix/ucontext.d core/sys/posix/unistd.d core/sys/posix/utime.d core/sys/darwin/crt_externs.d core/sys/darwin/dlfcn.d core/sys/darwin/err.d core/sys/darwin/execinfo.d core/sys/darwin/fcntl.d core/sys/darwin/ifaddrs.d core/sys/darwin/mach/dyld.d core/sys/darwin/mach/getsect.d core/sys/darwin/mach/kern_return.d core/sys/darwin/mach/loader.d core/sys/darwin/mach/nlist.d core/sys/darwin/mach/port.d core/sys/darwin/mach/semaphore.d core/sys/darwin/mach/stab.d core/sys/darwin/mach/thread_act.d core/sys/darwin/netinet/in_.d core/sys/darwin/pthread.d core/sys/darwin/stdlib.d core/sys/darwin/string.d core/sys/darwin/sys/attr.d core/sys/darwin/sys/cdefs.d core/sys/darwin/sys/event.d core/sys/darwin/sys/mman.d core/sys/darwin/sys/sysctl.d"
pushd $DRUNTIME_SRC_DIR
$LDC_BUILDDIR/bin/ldc2 -c --output-o -conf= -w -de -preview=dip1000 -preview=dtorfields -preview=fieldwise -d-version=SupportSanitizers -I$DRUNTIME_SRC_DIR -od=$LDC_BUILDDIR/runtime/objects-opaque --opaque-pointers=true -op $DRUNTIME_SRC
$LDC_BUILDDIR/bin/ldc2 -c --output-o -conf= -w -de -preview=dip1000 -preview=dtorfields -preview=fieldwise -d-version=SupportSanitizers -I$DRUNTIME_SRC_DIR -od=$LDC_BUILDDIR/runtime/objects-not-opaque --opaque-pointers=false -op $DRUNTIME_SRC
popd
# Check if the object files differ
for fd in $DRUNTIME_SRC
do
# replace '.d' with '.o'
fo="${fd:0:${#fd}-2}"".o"
diff -q $LDC_BUILDDIR/runtime/objects-opaque/$fo $LDC_BUILDDIR/runtime/objects-not-opaque/$fo || :
done
Only 2 files differ:
Files /Users/johan/ldc/build15/runtime/objects-opaque/std/net/curl.o and /Users/johan/ldc/build15/runtime/objects-not-opaque/std/net/curl.o differ
Files /Users/johan/ldc/build15/runtime/objects-opaque/std/numeric.o and /Users/johan/ldc/build15/runtime/objects-not-opaque/std/numeric.o differ
You mean checking the asm/machine code? I guess that could work indeed (possibly with
-Oto get rid of potentially small diffs), if we did that for the entire test suite.
With -O there are more binary differences than without (LLVM15). I think this is because of exactly the reason opaque pointers were introduced: it makes optimization easier. LLVM14 optimization cannot be tested with opaque pointers, because some optimization passes do not support opaque pointers (crashes).
Update: TL;DR: binary comparison shows false positives. There are subtle differences in asm/object file output that do not constitute actual differences in code behavior.
druntime compilation looks fine for AArch64 on macOS, only 3 files show different assembly output (master 58524baee2dbacb3db0387521ba980f20272ff69, -O0):
rt/_monitor.d, core/thread/osthread.d, and core/thread/threadbase.d. They all show the same kind of delta, for IR code like this that results from an in(delegate) function pre-condition:
TYPED PTR
define %core.thread.threadbase.ThreadBase* @_D4core6thread10threadbase10ThreadBase6__ctorMFNaNbNiNeDFZvmZCQCiQCgQCcQBt(%core.thread.threadbase.ThreadBase* nonnull returned %.this_arg, [2 x i64] %dg_arg, i64 %sz_arg) #0 {
%this = alloca %core.thread.threadbase.ThreadBase*, align 8 ; [#uses = 5, size/byte = 8]
%dg = alloca { i8*, void (i8*)* }, align 8 ; [#uses = 3, size/byte = 16]
%sz = alloca i64, align 8 ; [#uses = 2, size/byte = 8]
store %core.thread.threadbase.ThreadBase* %.this_arg, %core.thread.threadbase.ThreadBase** %this, align 8
%1 = bitcast { i8*, void (i8*)* }* %dg to [2 x i64]* ; [#uses = 1]
store [2 x i64] %dg_arg, [2 x i64]* %1, align 8
store i64 %sz_arg, i64* %sz, align 8
%2 = load { i8*, void (i8*)* }, { i8*, void (i8*)* }* %dg, align 8 ; [#uses = 2]
%3 = extractvalue { i8*, void (i8*)* } %2, 0 ; [#uses = 1]
%4 = extractvalue { i8*, void (i8*)* } %2, 1 ; [#uses = 1]
%5 = icmp ne i8* %3, null ; [#uses = 1]
%6 = icmp ne void (i8*)* %4, null ; [#uses = 1]
%7 = or i1 %5, %6 ; [#uses = 1]
br i1 %7, label %assertPassed, label %assertFailed
OPAQUE PTR
define ptr @_D4core6thread10threadbase10ThreadBase6__ctorMFNaNbNiNeDFZvmZCQCiQCgQCcQBt(ptr nonnull returned %.this_arg, [2 x i64] %dg_arg, i64 %sz_arg) #0 {
%this = alloca ptr, align 8 ; [#uses = 5, size/byte = 8]
%dg = alloca { ptr, ptr }, align 8 ; [#uses = 3, size/byte = 16]
%sz = alloca i64, align 8 ; [#uses = 2, size/byte = 8]
store ptr %.this_arg, ptr %this, align 8
store [2 x i64] %dg_arg, ptr %dg, align 8
store i64 %sz_arg, ptr %sz, align 8
%1 = load { ptr, ptr }, ptr %dg, align 8 ; [#uses = 2]
%2 = extractvalue { ptr, ptr } %1, 0 ; [#uses = 1]
%3 = extractvalue { ptr, ptr } %1, 1 ; [#uses = 1]
%4 = icmp ne ptr %2, null ; [#uses = 1]
%5 = icmp ne ptr %3, null ; [#uses = 1]
%6 = or i1 %4, %5 ; [#uses = 1]
br i1 %6, label %assertPassed, label %assertFailed
At -O0, the machine codegen is able to convert
%4 = icmp ne ptr %2, null ; [#uses = 1]
%5 = icmp ne ptr %3, null ; [#uses = 1]
%6 = or i1 %4, %5 ; [#uses = 1]
br i1 %6, label %assertPassed, label %assertFailed
into something like
a = and ptr %2, ptr%3
branch on (a)
whereas
%5 = icmp ne i8* %3, null ; [#uses = 1]
%6 = icmp ne void (i8*)* %4, null ; [#uses = 1]
%7 = or i1 %5, %6 ; [#uses = 1]
br i1 %7, label %assertPassed, label %assertFailed
becomes
if (ptr %2 == null) ...
if (ptr %3 == null) ...
Note: this is for AArch64 compilation on macOS.
For --mtriple=x86_64-linux I get many more different object files. But although threadbase.o is different, the --output-s assembly output is identical... And for e.g. core/demangle.d, the asm diff shows this. It's different but same behavior.
diff --git a/opaque.s b/typed.s
index c0fac3a..d1e36f8 100644
--- a/opaque.s
+++ b/typed.s
@@ -1185,8 +1185,8 @@ _D4core8demangle15reencodeMangledFNaNbNfNkMAxaZ12PrependHooks10parseLNameMFNaNlN
addq 32(%rcx), %rdx
movq %rdx, 32(%rcx)
movq 24(%rax), %rdi
- movq _D12TypeInfo_Axa6__initZ@GOTPCREL(%rip), %rsi
leaq -152(%rbp), %rdx
+ movq _D12TypeInfo_Axa6__initZ@GOTPCREL(%rip), %rsi
callq _aaInX@PLT
movq %rax, -160(%rbp)
cmpq $0, -160(%rbp)
@@ -1247,9 +1247,9 @@ _D4core8demangle15reencodeMangledFNaNbNfNkMAxaZ12PrependHooks10parseLNameMFNaNlN
leaq -16(%rbp), %rax
movq %rax, -200(%rbp)
addq $24, %rdi
+ leaq -152(%rbp), %rcx
movq _D14TypeInfo_HAxam6__initZ@GOTPCREL(%rip), %rsi
movl $8, %edx
- leaq -152(%rbp), %rcx
callq _aaGetY@PLT
movq -216(%rbp), %rcx
movq %rax, %rdx
@@ -6740,9 +6740,9 @@ _D4core8demangle__T8DemangleTSQBcQBa7NoHooksZQBa9parseTypeMFNaNjNlNfAaZQd:
movzbl %al, %eax
cmpl $81, %eax
jne .LBB73_65
- leaq _D4core8demangle__T8DemangleTSQBcQBa7NoHooksZQBa9parseTypeMFNaNjNlNfAaZ10__lambda11MFNaNfZQw(%rip), %rdx
leaq -40(%rbp), %rsi
- leaq -40(%rbp), %rdi
+ movq %rsi, %rdi
+ leaq _D4core8demangle__T8DemangleTSQBcQBa7NoHooksZQBa9parseTypeMFNaNjNlNfAaZ10__lambda11MFNaNfZQw(%rip), %rdx
callq _D4core8demangle__T8DemangleTSQBcQBa7NoHooksZQBa9parseTypeMFNaNjNlNfAaZ16parseBackrefTypeMFNaNfMDFNaNfZQBjZQBn@PLT
jmp .LBB73_66
.LBB73_65:
@@ -16066,9 +16066,9 @@ _D4core8demangle__T8DemangleTSQBcQBa15reencodeMangledFNaNbNfNkMAxaZ12PrependHook
movzbl %al, %eax
cmpl $81, %eax
jne .LBB133_67
- leaq _D4core8demangle__T8DemangleTSQBcQBa15reencodeMangledFNaNbNfNkMAxaZ12PrependHooksZQCl9parseTypeMFNaNjNlNfAaZ10__lambda12MFNaNfZQw(%rip), %rdx
leaq -40(%rbp), %rsi
- leaq -40(%rbp), %rdi
+ movq %rsi, %rdi
+ leaq _D4core8demangle__T8DemangleTSQBcQBa15reencodeMangledFNaNbNfNkMAxaZ12PrependHooksZQCl9parseTypeMFNaNjNlNfAaZ10__lambda12MFNaNfZQw(%rip), %rdx
callq _D4core8demangle__T8DemangleTSQBcQBa15reencodeMangledFNaNbNfNkMAxaZ12PrependHooksZQCl9parseTypeMFNaNjNlNfAaZ16parseBackrefTypeMFNaNfMDFNaNfZQBjZQBn@PLT
jmp .LBB133_68
.LBB133_67:
I don't see any unittest regressions with v1.36.0-beta1 for a large chunk of the Symmetry code base; neither when enabling optimizations everywhere. So looking good!