[GHC] #11792: Optimised unsafe FFI call can get wrong argument

#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.3 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: Incorrect result Unknown/Multiple | at runtime Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- Attached a simple test case. It should print 7457, but the C function is called with 0 as the third argument. If I compile with -O0 or omit the unsafe keyword in the FFI import it works as it should. In gdb disassembly looks to me as edx (the place for third argument on 64-bit) is set to 7457, then the opaquify is inlined, but it doesn't preserve edx and then third_arg is called with the zeroed edx. ---------------- Specs ------------- 64-bit Archlinux with arch-haskell repo gcc -v: {{{ Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/lto- wrapper Target: x86_64-unknown-linux-gnu Configured with: /build/gcc-multilib/src/gcc-5-20160209/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with- bugurl=https://bugs.archlinux.org/ --enable- languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable- threads=posix --enable-libmpx --with-system-zlib --with-isl --enable- __cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-install- libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-multilib --disable-werror --enable-checking=release Thread model: posix gcc version 5.3.0 (GCC) }}} ghc compile output: {{{ Glasgow Haskell Compiler, Version 7.10.3, stage 2 booted by GHC version 7.10.3 Using binary package database: /usr/lib/ghc-7.10.3/package.conf.d/package.cache wired-in package ghc-prim mapped to ghc- prim-0.4.0.0-6cdc86811872333585fa98756aa7c51e wired-in package integer-gmp mapped to integer- gmp-1.0.0.0-3c8c40657a9870f5c33be17496806d8d wired-in package base mapped to base-4.8.2.0-0d6d1084fbc041e1cded9228e80e264d wired-in package rts mapped to builtin_rts wired-in package template-haskell mapped to template- haskell-2.10.0.0-3c4cb52230f347282af9b2817f013181 wired-in package ghc mapped to ghc-7.10.3-3a39f8f970ff545623196002970730d1 wired-in package dph-seq not found. wired-in package dph-par not found. Hsc static flags: wired-in package ghc-prim mapped to ghc- prim-0.4.0.0-6cdc86811872333585fa98756aa7c51e wired-in package integer-gmp mapped to integer- gmp-1.0.0.0-3c8c40657a9870f5c33be17496806d8d wired-in package base mapped to base-4.8.2.0-0d6d1084fbc041e1cded9228e80e264d wired-in package rts mapped to builtin_rts wired-in package template-haskell mapped to template- haskell-2.10.0.0-3c4cb52230f347282af9b2817f013181 wired-in package ghc mapped to ghc-7.10.3-3a39f8f970ff545623196002970730d1 wired-in package dph-seq not found. wired-in package dph-par not found. *** Chasing dependencies: Chasing modules from: *Main.hs Stable obj: [] Stable BCO: [] Ready for upsweep [NONREC ModSummary { ms_hs_date = 2016-04-05 14:24:20.801997492 UTC ms_mod = Main, ms_textual_imps = [import (implicit) Prelude, import Data.Word] ms_srcimps = [] }] *** Deleting temp files: Deleting: compile: input file Main.hs Created temporary directory: /tmp/ghc1541_0 *** Checking old interface for Main: [1 of 1] Compiling Main ( Main.hs, Main.o ) *** Parser: *** Renamer/typechecker: *** Desugar: Result size of Desugar (after optimization) = {terms: 317, types: 387, coercions: 3} *** Core Linted result of Desugar (after optimization): *** Simplifier: Result size of Simplifier iteration=1 = {terms: 261, types: 290, coercions: 14} *** Core Linted result of Simplifier: Result size of Simplifier iteration=2 = {terms: 216, types: 262, coercions: 18} *** Core Linted result of Simplifier: Result size of Simplifier = {terms: 216, types: 262, coercions: 18} *** Core Linted result of Simplifier: *** Specialise: Result size of Specialise = {terms: 216, types: 262, coercions: 18} *** Core Linted result of Specialise: *** Float out(FOS {Lam = Just 0, Consts = True, OverSatApps = False}): Result size of Float out(FOS {Lam = Just 0, Consts = True, OverSatApps = False}) = {terms: 274, types: 305, coercions: 18} *** Core Linted result of Float out(FOS {Lam = Just 0, Consts = True, OverSatApps = False}): *** Simplifier: Result size of Simplifier iteration=1 = {terms: 407, types: 388, coercions: 70} *** Core Linted result of Simplifier: Result size of Simplifier iteration=2 = {terms: 463, types: 375, coercions: 25} *** Core Linted result of Simplifier: Result size of Simplifier = {terms: 430, types: 362, coercions: 25} *** Core Linted result of Simplifier: *** Simplifier: Result size of Simplifier iteration=1 = {terms: 426, types: 363, coercions: 25} *** Core Linted result of Simplifier: Result size of Simplifier = {terms: 426, types: 363, coercions: 25} *** Core Linted result of Simplifier: *** Simplifier: Result size of Simplifier iteration=1 = {terms: 310, types: 291, coercions: 25} *** Core Linted result of Simplifier: Result size of Simplifier iteration=2 = {terms: 248, types: 217, coercions: 25} *** Core Linted result of Simplifier: Result size of Simplifier iteration=3 = {terms: 336, types: 242, coercions: 25} *** Core Linted result of Simplifier: Result size of Simplifier = {terms: 336, types: 242, coercions: 25} *** Core Linted result of Simplifier: *** Float inwards: Result size of Float inwards = {terms: 336, types: 242, coercions: 25} *** Core Linted result of Float inwards: *** Called arity analysis: Result size of Called arity analysis = {terms: 336, types: 242, coercions: 25} *** Core Linted result of Called arity analysis: *** Simplifier: Result size of Simplifier = {terms: 336, types: 242, coercions: 25} *** Core Linted result of Simplifier: *** Demand analysis: Result size of Demand analysis = {terms: 336, types: 242, coercions: 25} *** Core Linted result of Demand analysis: *** Worker Wrapper binds: Result size of Worker Wrapper binds = {terms: 369, types: 283, coercions: 25} *** Core Linted result of Worker Wrapper binds: *** Simplifier: Result size of Simplifier iteration=1 = {terms: 354, types: 266, coercions: 25} *** Core Linted result of Simplifier: Result size of Simplifier = {terms: 354, types: 266, coercions: 25} *** Core Linted result of Simplifier: *** Float out(FOS {Lam = Just 0, Consts = True, OverSatApps = True}): Result size of Float out(FOS {Lam = Just 0, Consts = True, OverSatApps = True}) = {terms: 356, types: 267, coercions: 25} *** Core Linted result of Float out(FOS {Lam = Just 0, Consts = True, OverSatApps = True}): *** Common sub-expression: Result size of Common sub-expression = {terms: 356, types: 267, coercions: 25} *** Core Linted result of Common sub-expression: *** Float inwards: Result size of Float inwards = {terms: 356, types: 267, coercions: 25} *** Core Linted result of Float inwards: *** Simplifier: Result size of Simplifier = {terms: 356, types: 267, coercions: 25} *** Core Linted result of Simplifier: *** Tidy Core: Result size of Tidy Core = {terms: 356, types: 267, coercions: 25} *** Core Linted result of Tidy Core: writeBinIface: 18 Names writeBinIface: 81 dict entries *** CorePrep: Result size of CorePrep = {terms: 654, types: 379, coercions: 25} *** Core Linted result of CorePrep: *** Stg2Stg: *** CodeGen: *** Assembler: /usr/bin/gcc -fno-stack-protector -DTABLES_NEXT_TO_CODE -I. -x assembler -c /tmp/ghc1541_0/ghc_2.s -o Main.o Upsweep completely successful. *** Deleting temp files: Deleting: /tmp/ghc1541_0/ghc_3.c /tmp/ghc1541_0/ghc_2.s /tmp/ghc1541_0/ghc_1.s Warning: deleting non-existent /tmp/ghc1541_0/ghc_3.c Warning: deleting non-existent /tmp/ghc1541_0/ghc_1.s link: linkables are ... LinkableM (2016-04-05 15:42:11.288210053 UTC) Main [DotO Main.o] Linking Main ... *** C Compiler: /usr/bin/gcc -fno-stack-protector -DTABLES_NEXT_TO_CODE -c /tmp/ghc1541_0/ghc_4.c -o /tmp/ghc1541_0/ghc_5.o -I/usr/lib/ghc-7.10.3/include *** C Compiler: /usr/bin/gcc -fno-stack-protector -DTABLES_NEXT_TO_CODE -c /tmp/ghc1541_0/ghc_7.s -o /tmp/ghc1541_0/ghc_8.o -I/usr/lib/ghc-7.10.3/include *** Linker: /usr/bin/gcc -fno-stack-protector -DTABLES_NEXT_TO_CODE '-Wl,--hash- size=31' -Wl,--reduce-memory-overheads -Wl,--no-as-needed -o Main Main.o Test.o -L/usr/lib/ghc-7.10.3/base_HQfYBxpPvuw8OunzQu6JGM -L/usr/lib/ghc-7.10.3/integ_2aU3IZNMF9a7mQ0OzsZ0dS -L/usr/lib/ghc-7.10.3/ghcpr_8TmvWUcS1U1IKHT0levwg3 -L/usr/lib/ghc-7.10.3/rts /tmp/ghc1541_0/ghc_5.o /tmp/ghc1541_0/ghc_8.o -Wl,-u,ghczmprim_GHCziTypes_Izh_static_info -Wl,-u,ghczmprim_GHCziTypes_Czh_static_info -Wl,-u,ghczmprim_GHCziTypes_Fzh_static_info -Wl,-u,ghczmprim_GHCziTypes_Dzh_static_info -Wl,-u,base_GHCziPtr_Ptr_static_info -Wl,-u,ghczmprim_GHCziTypes_Wzh_static_info -Wl,-u,base_GHCziInt_I8zh_static_info -Wl,-u,base_GHCziInt_I16zh_static_info -Wl,-u,base_GHCziInt_I32zh_static_info -Wl,-u,base_GHCziInt_I64zh_static_info -Wl,-u,base_GHCziWord_W8zh_static_info -Wl,-u,base_GHCziWord_W16zh_static_info -Wl,-u,base_GHCziWord_W32zh_static_info -Wl,-u,base_GHCziWord_W64zh_static_info -Wl,-u,base_GHCziStable_StablePtr_static_info -Wl,-u,ghczmprim_GHCziTypes_Izh_con_info -Wl,-u,ghczmprim_GHCziTypes_Czh_con_info -Wl,-u,ghczmprim_GHCziTypes_Fzh_con_info -Wl,-u,ghczmprim_GHCziTypes_Dzh_con_info -Wl,-u,base_GHCziPtr_Ptr_con_info -Wl,-u,base_GHCziPtr_FunPtr_con_info -Wl,-u,base_GHCziStable_StablePtr_con_info -Wl,-u,ghczmprim_GHCziTypes_False_closure -Wl,-u,ghczmprim_GHCziTypes_True_closure -Wl,-u,base_GHCziPack_unpackCString_closure -Wl,-u,base_GHCziIOziException_stackOverflow_closure -Wl,-u,base_GHCziIOziException_heapOverflow_closure -Wl,-u,base_ControlziExceptionziBase_nonTermination_closure -Wl,-u,base_GHCziIOziException_blockedIndefinitelyOnMVar_closure -Wl,-u,base_GHCziIOziException_blockedIndefinitelyOnSTM_closure -Wl,-u,base_GHCziIOziException_allocationLimitExceeded_closure -Wl,-u,base_ControlziExceptionziBase_nestedAtomically_closure -Wl,-u,base_GHCziEventziThread_blockedOnBadFD_closure -Wl,-u,base_GHCziWeak_runFinalizzerBatch_closure -Wl,-u,base_GHCziTopHandler_flushStdHandles_closure -Wl,-u,base_GHCziTopHandler_runIO_closure -Wl,-u,base_GHCziTopHandler_runNonIO_closure -Wl,-u,base_GHCziConcziIO_ensureIOManagerIsRunning_closure -Wl,-u,base_GHCziConcziIO_ioManagerCapabilitiesChanged_closure -Wl,-u,base_GHCziConcziSync_runSparks_closure -Wl,-u,base_GHCziConcziSignal_runHandlersPtr_closure -lHSbase-4.8.2.0-HQfYBxpPvuw8OunzQu6JGM -lHSinteger- gmp-1.0.0.0-2aU3IZNMF9a7mQ0OzsZ0dS -lHSghc- prim-0.4.0.0-8TmvWUcS1U1IKHT0levwg3 -lHSrts -lCffi -lgmp -lm -lrt -ldl link: done *** Deleting temp files: Deleting: /tmp/ghc1541_0/ghc_10.rsp /tmp/ghc1541_0/ghc_9.rsp /tmp/ghc1541_0/ghc_8.o /tmp/ghc1541_0/ghc_7.s /tmp/ghc1541_0/ghc_6.rsp /tmp/ghc1541_0/ghc_5.o /tmp/ghc1541_0/ghc_4.c *** Deleting temp dirs: Deleting: /tmp/ghc1541_0 }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11792 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by Szunti): * Attachment "evil-bug.tar.gz" added. Simple test case -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11792 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by Szunti): Can I help more to get this fixed? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11792#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11792: Optimised unsafe FFI call can get wrong argument
-------------------------------------+-------------------------------------
Reporter: Szunti | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 7.10.3
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: Incorrect result | Unknown/Multiple
at runtime | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by hsyl20):
For the record, the unsafe foreign call in Cmm after sink assignments:
{{{#!C
(_s3N3::I64) = call "ccall" arg hints: [, , ,] result hints: []
third_arg(0, 0, 7457,
%MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(%MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(%MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(%MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(I64[Sp
+ 16] * _s3MA::I64)) / 255 +
%MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(%MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(%MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(I64[Sp
+ 24] * _s3MA::I64)) / 255 +
%MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(%MO_UU_Conv_W32_W64(%MO_UU_Conv_W64_W32(I64[R1
+ 7] * _s3MA::I64)) / 255 << 8)))) << 8)))) << 8)) + 255)));
}}}
Indeed edx doesn't seem to be in the clobber list when the code for the
fourth argument is generated and we obtain:
{{{#!asm
405dc9: ba 21 1d 00 00 mov $0x1d21,%edx ; 0x1d21 is
the third arg
405dce: b9 ff 00 00 00 mov $0xff,%ecx
405dd3: 48 8b 5b 07 mov 0x7(%rbx),%rbx
405dd7: 48 0f af d8 imul %rax,%rbx
405ddb: 48 89 c2 mov %rax,%rdx ; problem
...
405e43: e8 82 03 00 00 callq 4061ca

#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: new Priority: high | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by hsyl20): * priority: normal => high * cc: hsyl20 (added) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11792#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: new Priority: high | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by osa1): Interestingly, these seem to fix this code: - Marking the FFI function "safe". - `-XStrict` May be helpful when debugging... -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11792#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: new Priority: high | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by osa1): I spent some time debugging this. Here are codes for FFI function arguments (before register allocation): {{{ first arg: [ xorl %edi,%edi] second arg: [ xorl %esi,%esi] third arg: [ movl $7457,%edx] fourth arg: [ movl $255,%vI_n4I8, movq 7(%rbx),%vI_n4Ia, imulq %vI_s4pW,%vI_n4Ia, movl %vI_n4Ia,%eax, xorq %rdx,%rdx, divq %vI_n4I8, movq %rax,%vI_n4Ib, shlq $8,%vI_n4Ib, movl %vI_n4Ib,%vI_n4Ic, movl $255,%vI_n4Id, movq 24(%rbp),%vI_n4If, imulq %vI_s4pW,%vI_n4If, movl %vI_n4If,%eax, xorq %rdx,%rdx, divq %vI_n4Id, movq %rax,%vI_n4Ih, addq %vI_n4Ic,%vI_n4Ih, movl %vI_n4Ih,%vI_n4Ii, shlq $8,%vI_n4Ii, movl %vI_n4Ii,%vI_n4Ij, movl $255,%vI_n4Ik, movq 16(%rbp),%vI_n4Im, imulq %vI_s4pW,%vI_n4Im, movl %vI_n4Im,%eax, xorq %rdx,%rdx, divq %vI_n4Ik, movq %rax,%vI_n4Io, addq %vI_n4Ij,%vI_n4Io, movl %vI_n4Io,%vI_n4Ip, shlq $8,%vI_n4Ip, movl %vI_n4Ip,%vI_n4Iq, leaq 255(%vI_n4Iq),%vI_n4Ir, movl %vI_n4Ir,%ecx] }}} These look correct to me. Since the code mostly uses virtual registers `%edx` isn't overridden at this point. So I think the problem may be in register allocation. I don't know how register allocation in GHC is working, but I looked at liveness information output, and it shows this for the `call third_arg` instruction: {{{ call third_arg # born: %r8 %r9 %r10 %r11 %r16 %r17 %r18 %r19 %r20 %r21 %r24 %r25 %r26 %r27 %r28 %r29 %r30 %r31 %r32 %r33 %r34 %r35 %r36 %r37 %r38 %r39 # w_dying: %r2 %r3 %r4 %r5 %r8 %r9 %r10 %r11 %r16 %r17 %r18 %r19 %r20 %r21 %r24 %r25 %r26 %r27 %r28 %r29 %r30 %r31 %r32 %r33 %r34 %r35 %r36 %r37 %r38 %r39 }}} I don't quite understand what's happening here (what are all those registers??), but I'd expect this instruction to "read" (or "use") `%edx`. So `%edx` would have to stay live between `third arg` and this call instruction, and so register allocation would have to generate some spill instructions when allocating registers for fourth argument if available registers are not enough. At least this is how my compiler is doing it. I may have another look tomorrow. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11792#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: new Priority: high | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by hsyl20): Replying to [comment:5 osa1]:
{{{ third arg: [ movl $7457,%edx] fourth arg: [ movl $255,%vI_n4I8, movq 7(%rbx),%vI_n4Ia, imulq %vI_s4pW,%vI_n4Ia, movl %vI_n4Ia,%eax, xorq %rdx,%rdx, }}}
These look correct to me. Since the code mostly uses virtual registers `%edx` isn't overridden at this point.
It is overriden: `%rdx` is `xor`ed before each `divq`. With -ddump-asm- liveness, we can see that `%edx` (`%r3`) born in the `movl` is overwritten. {{{ movl $7457,%edx # born: %r3 # w_dying: %r3 movl $255,%vI_n413 # born: %vI_n413 movq 7(%rbx),%vI_n415 # born: %vI_n415 # r_dying: %r1 imulq %vI_s3Mw,%vI_n415 movl %vI_n415,%eax # born: %r0 # r_dying: %vI_n415 xorq %rdx,%rdx # born: %r3 divq %vI_n413 # r_dying: %vI_n413 # w_dying: %r3 }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11792#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: new Priority: high | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by hsyl20): I have made a first patch: https://phabricator.haskell.org/D2263 The result looks better (even if a little bit suboptimal): {{{#!nasm movq 8(%rbp),%rax xorl %ecx,%ecx xorl %edx,%edx movl $7457,%esi movl $255,%edi ; inlined code not using %esi/%rsi ; ... movq %rcx,%rdi ; suboptimal (could be xorq %rdi, %rdi) movq %rsi,%rcx ; suboptimal (could be movq %rsi, %rdx directly) movq %rbx,%rsi ; suboptimal (could be xorq %rsi, %rsi) movq %rcx,%rdx movq %rax,%rcx subq $8,%rsp xorl %eax,%eax call third_arg }}} The patch doesn't handle pushed args yet. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11792#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: new Priority: high | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2263 Wiki Page: | -------------------------------------+------------------------------------- Changes (by hsyl20): * differential: => Phab:D2263 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11792#comment:8 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: new Priority: high | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2263 Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonmar): Hmm, I'd like to find a way to fix this without making codegen worse for every unsafe call. The problem appears to be that the code for the fourth argument uses `divq` which clobbers `%rdx`. I need to refresh my memory about how this is supposed to work... -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11792#comment:9 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: new Priority: high | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2263 Wiki Page: | -------------------------------------+------------------------------------- Comment (by osa1): I added a comment to the Phab ticket. I think we should fix the code gen so that if a register is written at some point A and read at point B, it should be kept alive no matter what. It'd be great if we could write some unit tests about that, but that needs a lot of infrastructure work... -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11792#comment:10 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: new Priority: high | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2263 Wiki Page: | -------------------------------------+------------------------------------- Comment (by osa1): I was doing some reading on Cmm and found something that may be relevant in [this wiki page](https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/CmmType):
Global Registers in Cmm currently have a problem with inlining: because neither compiler/cmm/PprC.hs nor the NCG are able to keep Global Registers from clashing with C argument passing registers, Cmm expressions that contain Global Registers cannot be inlined into an argument position of a foreign call. For more thorough notes on inlining, see the comments in compiler/cmm/CmmOpt.hs.
The page is a bit out of date but this part sounded like the problem we're having here. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11792#comment:11 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: new Priority: high | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2263 Wiki Page: | -------------------------------------+------------------------------------- Comment (by osa1): I still don't know how the register allocator works, but I realized something interesting. `CmmCall` has a field `cml_args_regs :: [GlobalReg]` for the arguments that are passed to the function, but `CmmUnsafeForeignCall` doesn't have anything like that. Shouldn't it have the same thing to be used in register allocation? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11792#comment:12 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: new Priority: high | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2263 Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonmar): This is unrelated to global registers, in fact. There is a related issue with global registers which is described here: https://phabricator.haskell.org/diffusion/GHC/browse/master/compiler/cmm/Cmm... But the issue here is different: see my comment on the diff. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11792#comment:13 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11792: Optimised unsafe FFI call can get wrong argument
-------------------------------------+-------------------------------------
Reporter: Szunti | Owner:
Type: bug | Status: new
Priority: high | Milestone:
Component: Compiler | Version: 7.10.3
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: Incorrect result | Unknown/Multiple
at runtime | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s): Phab:D2263
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by Ben Gamari

#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: merge Priority: high | Milestone: 8.0.2 Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2263 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: new => merge * milestone: => 8.0.2 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11792#comment:15 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#11792: Optimised unsafe FFI call can get wrong argument -------------------------------------+------------------------------------- Reporter: Szunti | Owner: Type: bug | Status: closed Priority: high | Milestone: 8.0.2 Component: Compiler | Version: 7.10.3 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2263 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: merge => closed * resolution: => fixed Comment: comment:14 merged as aec4a514857d051f5eeb15b9cbc8e6dd29850c5f. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11792#comment:16 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC