ldc icon indicating copy to clipboard operation
ldc copied to clipboard

Pointer comparisons no longer work with opaque pointers, code review needed

Open JohanEngelen opened this issue 3 years ago • 8 comments
trafficstars

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));

JohanEngelen avatar Nov 13 '22 23:11 JohanEngelen

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.

JohanEngelen avatar Nov 13 '22 23:11 JohanEngelen

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.

thewilsonator avatar Nov 13 '22 23:11 thewilsonator

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.

kinke avatar Nov 14 '22 02:11 kinke

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

JohanEngelen avatar Nov 14 '22 22:11 JohanEngelen

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

JohanEngelen avatar Nov 14 '22 23:11 JohanEngelen

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.

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).

JohanEngelen avatar Nov 14 '22 23:11 JohanEngelen

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:

JohanEngelen avatar Nov 20 '22 21:11 JohanEngelen

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!

kinke avatar Dec 06 '23 20:12 kinke