public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* A problem with passing the Global Offset Table address to a function in %edx
@ 2021-02-22 15:44 Barnes, Richard
  0 siblings, 0 replies; only message in thread
From: Barnes, Richard @ 2021-02-22 15:44 UTC (permalink / raw)
  To: gcc

[-- Attachment #1: Type: text/plain, Size: 2268 bytes --]

I am in the process of porting gcc-10.2.0 to a non-Unix operating system called VOS that does have a POSIX Application Programming Interface (API) but does not have a Unix Application Binary Interface (ABI). The main way that VOS differs from Unix is in how the Global Offset Table (GOT) for position-independent code (PIC) is handled. In Unix PIC code, there is one GOT per program and each function is responsible for finding the address of the GOT on its own. In VOS, all non-kernel code is PIC, and there is a different GOT for each thread in a program. Therefore, each function is responsible for passing the address of the GOT in a register. On IA-32, that is %edx, which is a caller-save register. (On PA-RISC, it is r27, which is a callee-save register.) Also on VOS if a function calls a nested function, it needs to pass the static-chain address in %ecx, another caller-save register.

Many years ago, when I ported gcc-3.4.6 to VOS, I had no trouble doing this. At the call-site I merely set %edx to the address of the GOT and did a use_reg of %edx, which attached a (use (reg:SI 1 dx)) to the CALL_INSN_FUNCTION_USAGE list hanging off the CALL instruction. A similar thing happened with %edx for nested function calls. However, with the gcc-10.2.0 port this now fails. There are 4 passes that run dead code elimination (DCE), sometimes as a side-effect for what the pass is mostly doing, and those passes eventually decide that the set of %edx is dead code and eliminates it. The reason it happens is that the DCE code (run_fast_df_dce) is run as a side-effect of a live-register problem and is considered a recursive call. This causes DCE to ignore the register uses in the CALL_INSN_FUNCTION_USAGE list and, thus the prior set becomes dead.

I believe this happened because our port of gcc-3.4.6 to VOS was not accepted as a contribution to the core product, athough we did offer it, and the only other port that had a similar ABI was to IA-64, which I believe is no longer supported.

I enclose some -da output from a compilation of a hello_world main function that illustrates this problem in the cse1 pass. Any line that starts with "**" is a result of debugging code that I have inserted to help me figure this out.

Thanks,
Richard Barnes

[-- Attachment #2: hello_world.c.242r.cse1 --]
[-- Type: application/octet-stream, Size: 14279 bytes --]


;; Function main (main, funcdef_no=0, decl_uid=1680, cgraph_uid=1, symbol_order=0) (executed once)


3 basic blocks, 2 edges.
;; basic block 0, loop depth 0, count 1073741824 (estimated locally), maybe hot
;;  prev block (nil), next block 2, flags: (RTL, MODIFIED)
;;  pred:      
;; bb 0 artificial_defs: { d-1(1){ }d-1(6){ }d-1(7){ }d-1(16){ }d-1(19){ }}
;; bb 0 artificial_uses: { }


;;  succ:       2 [always]  count:1073741824 (estimated locally) (FALLTHRU)

;; basic block 2, loop depth 0, count 1073741824 (estimated locally), maybe hot
;;  prev block 0, next block 1, flags: (RTL, MODIFIED)
;;  pred:       ENTRY [always]  count:1073741824 (estimated locally) (FALLTHRU)
;; bb 2 artificial_defs: { }
;; bb 2 artificial_uses: { u-1(1){ }u-1(6){ }u-1(7){ }u-1(16){ }u-1(19){ }}

(note 6 0 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
(insn 2 6 3 2 (set (reg:SI 82)
        (reg:SI 1 dx)) "hello_world.c":5:1 60 {*movsi_internal}
     (nil))
(note 3 2 4 2 NOTE_INSN_FUNCTION_BEG)
(insn 4 3 5 2 (set (reg:SI 1 dx)
        (reg:SI 82)) "hello_world.c":5:1 60 {*movsi_internal}
     (nil))
(call_insn 5 4 8 2 (call (mem:QI (symbol_ref:SI ("__main") [flags 0x41]  <function_decl 3feb2c00 __main>) [0  S1 A8])
        (const_int 0 [0])) "hello_world.c":5:1 604 {*call}
     (expr_list:REG_CALL_DECL (symbol_ref:SI ("__main") [flags 0x41]  <function_decl 3feb2c00 __main>)
        (expr_list:REG_EH_REGION (const_int -2147483648 [0xffffffff80000000])
            (nil)))
    (expr_list (use (reg:SI 1 dx))
        (nil)))
(insn 8 5 9 2 (set (mem:SI (plus:SI (reg/f:SI 7 sp)
                (const_int 12 [0xc])) [0  S4 A32])
        (const:SI (plus:SI (symbol_ref:SI ("_iob") [flags 0x40]  <var_decl 3fea8948 _iob>)
                (const_int 104 [0x68])))) "hello_world.c":6:3 60 {*movsi_internal}
     (nil))
(insn 9 8 10 2 (set (mem:SI (plus:SI (reg/f:SI 7 sp)
                (const_int 8 [0x8])) [0  S4 A32])
        (const_int 13 [0xd])) "hello_world.c":6:3 60 {*movsi_internal}
     (nil))
(insn 10 9 11 2 (set (mem:SI (plus:SI (reg/f:SI 7 sp)
                (const_int 4 [0x4])) [0  S4 A32])
        (const_int 1 [0x1])) "hello_world.c":6:3 60 {*movsi_internal}
     (nil))
(insn 11 10 12 2 (set (mem:SI (reg/f:SI 7 sp) [0  S4 A32])
        (symbol_ref/f:SI ("*.LC0") [flags 0x2]  <var_decl 3fea8f78 *.LC0>)) "hello_world.c":6:3 60 {*movsi_internal}
     (nil))
(insn 12 11 13 2 (set (reg:SI 1 dx)
        (reg:SI 82)) "hello_world.c":6:3 60 {*movsi_internal}
     (nil))
(call_insn 13 12 14 2 (set (reg:SI 0 ax)
        (call (mem:QI (symbol_ref:SI ("fwrite") [flags 0x41]  <function_decl 3fe6b980 __builtin_fwrite>) [0 __builtin_fwrite S1 A8])
            (const_int 16 [0x10]))) "hello_world.c":6:3 615 {*call_value}
     (expr_list:REG_CALL_DECL (symbol_ref:SI ("fwrite") [flags 0x41]  <function_decl 3fe6b980 __builtin_fwrite>)
        (nil))
    (expr_list (use (reg:SI 1 dx))
        (expr_list:SI (use (mem/f:SI (reg/f:SI 7 sp) [0  S4 A32]))
            (expr_list:SI (use (mem:SI (plus:SI (reg/f:SI 7 sp)
                            (const_int 4 [0x4])) [0  S4 A32]))
                (expr_list:SI (use (mem:SI (plus:SI (reg/f:SI 7 sp)
                                (const_int 8 [0x8])) [0  S4 A32]))
                    (expr_list:SI (use (mem/f:SI (plus:SI (reg/f:SI 7 sp)
                                    (const_int 12 [0xc])) [0  S4 A32]))
                        (nil)))))))
(insn 14 13 18 2 (set (reg:SI 83 [ <retval> ])
        (const_int 0 [0])) "hello_world.c":8:1 60 {*movsi_internal}
     (nil))
(insn 18 14 19 2 (set (reg/i:SI 0 ax)
        (reg:SI 83 [ <retval> ])) "hello_world.c":8:1 60 {*movsi_internal}
     (nil))
(insn 19 18 0 2 (use (reg/i:SI 0 ax)) "hello_world.c":8:1 -1
     (nil))

;;  succ:       EXIT [always]  count:1073741824 (estimated locally) (FALLTHRU)

;; basic block 1, loop depth 0, count 1073741824 (estimated locally), maybe hot
;;  prev block 2, next block (nil), flags: (RTL, MODIFIED)
;;  pred:       2 [always]  count:1073741824 (estimated locally) (FALLTHRU)
;; bb 1 artificial_defs: { }
;; bb 1 artificial_uses: { u-1(0){ }u-1(6){ }u-1(7){ }u-1(19){ }}


;;  succ:      


starting the processing of deferred insns
ending the processing of deferred insns
df_analyze called
df_worklist_dataflow_doublequeue: n_basic_blocks 3 n_edges 2 count 3 (    1)
**df_in_progress = true


main

Dataflow summary:
def_info->table_size = 0, use_info->table_size = 0
;;  fully invalidated by EH 	 0 [ax] 1 [dx] 2 [cx] 8 [st] 9 [st(1)] 10 [st(2)] 11 [st(3)] 12 [st(4)] 13 [st(5)] 14 [st(6)] 15 [st(7)] 17 [flags] 18 [fpsr] 20 [xmm0] 21 [xmm1] 22 [xmm2] 23 [xmm3] 24 [xmm4] 25 [xmm5] 26 [xmm6] 27 [xmm7] 28 [mm0] 29 [mm1] 30 [mm2] 31 [mm3] 32 [mm4] 33 [mm5] 34 [mm6] 35 [mm7] 36 [r8] 37 [r9] 38 [r10] 39 [r11] 40 [r12] 41 [r13] 42 [r14] 43 [r15] 44 [xmm8] 45 [xmm9] 46 [xmm10] 47 [xmm11] 48 [xmm12] 49 [xmm13] 50 [xmm14] 51 [xmm15] 52 [xmm16] 53 [xmm17] 54 [xmm18] 55 [xmm19] 56 [xmm20] 57 [xmm21] 58 [xmm22] 59 [xmm23] 60 [xmm24] 61 [xmm25] 62 [xmm26] 63 [xmm27] 64 [xmm28] 65 [xmm29] 66 [xmm30] 67 [xmm31] 68 [k0] 69 [k1] 70 [k2] 71 [k3] 72 [k4] 73 [k5] 74 [k6] 75 [k7]
;;  hardware regs used 	 7 [sp] 16 [argp] 19 [frame]
;;  regular block artificial uses 	 1 [dx] 6 [bp] 7 [sp] 16 [argp] 19 [frame]
;;  eh block artificial uses 	 1 [dx] 6 [bp] 7 [sp] 16 [argp] 19 [frame]
;;  entry block defs 	 1 [dx] 6 [bp] 7 [sp] 16 [argp] 19 [frame]
;;  exit block uses 	 0 [ax] 6 [bp] 7 [sp] 19 [frame]
;;  regs ever live 	 0 [ax] 7 [sp]
;;  ref usage 	r0={3d,2u} r1={3d,1u} r2={2d} r6={1d,2u} r7={1d,12u} r8={2d} r9={2d} r10={2d} r11={2d} r12={2d} r13={2d} r14={2d} r15={2d} r16={1d,1u} r17={2d} r18={2d} r19={1d,2u} r20={2d} r21={2d} r22={2d} r23={2d} r24={2d} r25={2d} r26={2d} r27={2d} r28={2d} r29={2d} r30={2d} r31={2d} r32={2d} r33={2d} r34={2d} r35={2d} r36={2d} r37={2d} r38={2d} r39={2d} r40={2d} r41={2d} r42={2d} r43={2d} r44={2d} r45={2d} r46={2d} r47={2d} r48={2d} r49={2d} r50={2d} r51={2d} r52={2d} r53={2d} r54={2d} r55={2d} r56={2d} r57={2d} r58={2d} r59={2d} r60={2d} r61={2d} r62={2d} r63={2d} r64={2d} r65={2d} r66={2d} r67={2d} r68={2d} r69={2d} r70={2d} r71={2d} r72={2d} r73={2d} r74={2d} r75={2d} r82={1d,2u} r83={1d,1u} 
;;    total ref usage 169{146d,23u,0e} in 12{10 regular + 2 call} insns.

( )->[0]->( 2 )
;; bb 0 artificial_defs: { d-1(1){ }d-1(6){ }d-1(7){ }d-1(16){ }d-1(19){ }}
;; bb 0 artificial_uses: { }

( 0 )->[2]->( 1 )
;; bb 2 artificial_defs: { }
;; bb 2 artificial_uses: { u-1(1){ }u-1(6){ }u-1(7){ }u-1(16){ }u-1(19){ }}

( 2 )->[1]->( )
;; bb 1 artificial_defs: { }
;; bb 1 artificial_uses: { u-1(0){ }u-1(6){ }u-1(7){ }u-1(19){ }}

**Entering fast_dce at register level.
Finding needed instructions:
**deletable_insn_p protects USE of register 0
**mark_insn called for insn 19
  Adding insn 19 to worklist
**mark_insn called for insn 13
  Adding insn 13 to worklist
**mark_insn called for insn 11
  Adding insn 11 to worklist
**mark_insn called for insn 10
  Adding insn 10 to worklist
**mark_insn called for insn 9
  Adding insn 9 to worklist
**mark_insn called for insn 8
  Adding insn 8 to worklist
**mark_insn called for insn 5
  Adding insn 5 to worklist
**mark_insn called for insn 2
  Adding insn 2 to worklist
Finished finding needed instructions:
processing block 2 lr out =  0 [ax] 6 [bp] 7 [sp] 16 [argp] 19 [frame]
**See if there is a use of reg 0 of insn 18.
**mark_insn called for insn 18
  Adding insn 18 to worklist
**See if there is a use of reg 83 of insn 14.
**mark_insn called for insn 14
  Adding insn 14 to worklist
DCE: Deleting insn 12
deleting insn with uid = 12.
DCE: Deleting insn 4
deleting insn with uid = 4.
**df_in_progress = false
df_worklist_dataflow_doublequeue: n_basic_blocks 3 n_edges 2 count 3 (    1)
df_worklist_dataflow_doublequeue: n_basic_blocks 3 n_edges 2 count 3 (    1)
;; Following path with 10 sets: 2 
deferring rescan insn with uid = 18.


try_optimize_cfg iteration 1

starting the processing of deferred insns
rescanning insn with uid = 18.
ending the processing of deferred insns


main

Dataflow summary:
;;  fully invalidated by EH 	 0 [ax] 1 [dx] 2 [cx] 8 [st] 9 [st(1)] 10 [st(2)] 11 [st(3)] 12 [st(4)] 13 [st(5)] 14 [st(6)] 15 [st(7)] 17 [flags] 18 [fpsr] 20 [xmm0] 21 [xmm1] 22 [xmm2] 23 [xmm3] 24 [xmm4] 25 [xmm5] 26 [xmm6] 27 [xmm7] 28 [mm0] 29 [mm1] 30 [mm2] 31 [mm3] 32 [mm4] 33 [mm5] 34 [mm6] 35 [mm7] 36 [r8] 37 [r9] 38 [r10] 39 [r11] 40 [r12] 41 [r13] 42 [r14] 43 [r15] 44 [xmm8] 45 [xmm9] 46 [xmm10] 47 [xmm11] 48 [xmm12] 49 [xmm13] 50 [xmm14] 51 [xmm15] 52 [xmm16] 53 [xmm17] 54 [xmm18] 55 [xmm19] 56 [xmm20] 57 [xmm21] 58 [xmm22] 59 [xmm23] 60 [xmm24] 61 [xmm25] 62 [xmm26] 63 [xmm27] 64 [xmm28] 65 [xmm29] 66 [xmm30] 67 [xmm31] 68 [k0] 69 [k1] 70 [k2] 71 [k3] 72 [k4] 73 [k5] 74 [k6] 75 [k7]
;;  hardware regs used 	 7 [sp] 16 [argp] 19 [frame]
;;  regular block artificial uses 	 1 [dx] 6 [bp] 7 [sp] 16 [argp] 19 [frame]
;;  eh block artificial uses 	 1 [dx] 6 [bp] 7 [sp] 16 [argp] 19 [frame]
;;  entry block defs 	 1 [dx] 6 [bp] 7 [sp] 16 [argp] 19 [frame]
;;  exit block uses 	 0 [ax] 6 [bp] 7 [sp] 19 [frame]
;;  regs ever live 	 0 [ax] 7 [sp]
;;  ref usage 	r0={3d,2u} r1={3d,1u} r2={2d} r6={1d,2u} r7={1d,12u} r8={2d} r9={2d} r10={2d} r11={2d} r12={2d} r13={2d} r14={2d} r15={2d} r16={1d,1u} r17={2d} r18={2d} r19={1d,2u} r20={2d} r21={2d} r22={2d} r23={2d} r24={2d} r25={2d} r26={2d} r27={2d} r28={2d} r29={2d} r30={2d} r31={2d} r32={2d} r33={2d} r34={2d} r35={2d} r36={2d} r37={2d} r38={2d} r39={2d} r40={2d} r41={2d} r42={2d} r43={2d} r44={2d} r45={2d} r46={2d} r47={2d} r48={2d} r49={2d} r50={2d} r51={2d} r52={2d} r53={2d} r54={2d} r55={2d} r56={2d} r57={2d} r58={2d} r59={2d} r60={2d} r61={2d} r62={2d} r63={2d} r64={2d} r65={2d} r66={2d} r67={2d} r68={2d} r69={2d} r70={2d} r71={2d} r72={2d} r73={2d} r74={2d} r75={2d} r82={1d} r83={1d} 
;;    total ref usage 166{146d,20u,0e} in 10{8 regular + 2 call} insns.
;; basic block 2, loop depth 0, count 1073741824 (estimated locally), maybe hot
;;  prev block 0, next block 1, flags: (REACHABLE, RTL, MODIFIED)
;;  pred:       ENTRY [always]  count:1073741824 (estimated locally) (FALLTHRU)
;; bb 2 artificial_defs: { }
;; bb 2 artificial_uses: { u-1(1){ }u-1(6){ }u-1(7){ }u-1(16){ }u-1(19){ }}
;; lr  in  	 6 [bp] 7 [sp] 16 [argp] 19 [frame]
;; lr  use 	 6 [bp] 7 [sp] 16 [argp] 19 [frame]
;; lr  def 	 0 [ax] 1 [dx] 2 [cx] 8 [st] 9 [st(1)] 10 [st(2)] 11 [st(3)] 12 [st(4)] 13 [st(5)] 14 [st(6)] 15 [st(7)] 17 [flags] 18 [fpsr] 20 [xmm0] 21 [xmm1] 22 [xmm2] 23 [xmm3] 24 [xmm4] 25 [xmm5] 26 [xmm6] 27 [xmm7] 28 [mm0] 29 [mm1] 30 [mm2] 31 [mm3] 32 [mm4] 33 [mm5] 34 [mm6] 35 [mm7] 36 [r8] 37 [r9] 38 [r10] 39 [r11] 40 [r12] 41 [r13] 42 [r14] 43 [r15] 44 [xmm8] 45 [xmm9] 46 [xmm10] 47 [xmm11] 48 [xmm12] 49 [xmm13] 50 [xmm14] 51 [xmm15] 52 [xmm16] 53 [xmm17] 54 [xmm18] 55 [xmm19] 56 [xmm20] 57 [xmm21] 58 [xmm22] 59 [xmm23] 60 [xmm24] 61 [xmm25] 62 [xmm26] 63 [xmm27] 64 [xmm28] 65 [xmm29] 66 [xmm30] 67 [xmm31] 68 [k0] 69 [k1] 70 [k2] 71 [k3] 72 [k4] 73 [k5] 74 [k6] 75 [k7] 82 83
;; live  in  	 6 [bp] 7 [sp] 16 [argp] 19 [frame]
;; live  gen 	 0 [ax] 82 83
;; live  kill	
(note 6 0 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
(insn 2 6 3 2 (set (reg:SI 82)
        (reg:SI 1 dx)) "hello_world.c":5:1 60 {*movsi_internal}
     (expr_list:REG_DEAD (reg:SI 1 dx)
        (expr_list:REG_UNUSED (reg:SI 82)
            (nil))))
(note 3 2 5 2 NOTE_INSN_FUNCTION_BEG)
(call_insn 5 3 8 2 (call (mem:QI (symbol_ref:SI ("__main") [flags 0x41]  <function_decl 3feb2c00 __main>) [0  S1 A8])
        (const_int 0 [0])) "hello_world.c":5:1 604 {*call}
     (expr_list:REG_DEAD (reg:SI 1 dx)
        (expr_list:REG_CALL_DECL (symbol_ref:SI ("__main") [flags 0x41]  <function_decl 3feb2c00 __main>)
            (expr_list:REG_EH_REGION (const_int -2147483648 [0xffffffff80000000])
                (nil))))
    (expr_list (use (reg:SI 1 dx))
        (nil)))
(insn 8 5 9 2 (set (mem:SI (plus:SI (reg/f:SI 7 sp)
                (const_int 12 [0xc])) [0  S4 A32])
        (const:SI (plus:SI (symbol_ref:SI ("_iob") [flags 0x40]  <var_decl 3fea8948 _iob>)
                (const_int 104 [0x68])))) "hello_world.c":6:3 60 {*movsi_internal}
     (nil))
(insn 9 8 10 2 (set (mem:SI (plus:SI (reg/f:SI 7 sp)
                (const_int 8 [0x8])) [0  S4 A32])
        (const_int 13 [0xd])) "hello_world.c":6:3 60 {*movsi_internal}
     (nil))
(insn 10 9 11 2 (set (mem:SI (plus:SI (reg/f:SI 7 sp)
                (const_int 4 [0x4])) [0  S4 A32])
        (const_int 1 [0x1])) "hello_world.c":6:3 60 {*movsi_internal}
     (nil))
(insn 11 10 13 2 (set (mem:SI (reg/f:SI 7 sp) [0  S4 A32])
        (symbol_ref/f:SI ("*.LC0") [flags 0x2]  <var_decl 3fea8f78 *.LC0>)) "hello_world.c":6:3 60 {*movsi_internal}
     (nil))
(call_insn 13 11 14 2 (set (reg:SI 0 ax)
        (call (mem:QI (symbol_ref:SI ("fwrite") [flags 0x41]  <function_decl 3fe6b980 __builtin_fwrite>) [0 __builtin_fwrite S1 A8])
            (const_int 16 [0x10]))) "hello_world.c":6:3 615 {*call_value}
     (expr_list:REG_DEAD (reg:SI 1 dx)
        (expr_list:REG_UNUSED (reg:SI 0 ax)
            (expr_list:REG_CALL_DECL (symbol_ref:SI ("fwrite") [flags 0x41]  <function_decl 3fe6b980 __builtin_fwrite>)
                (nil))))
    (expr_list (use (reg:SI 1 dx))
        (expr_list:SI (use (mem/f:SI (reg/f:SI 7 sp) [0  S4 A32]))
            (expr_list:SI (use (mem:SI (plus:SI (reg/f:SI 7 sp)
                            (const_int 4 [0x4])) [0  S4 A32]))
                (expr_list:SI (use (mem:SI (plus:SI (reg/f:SI 7 sp)
                                (const_int 8 [0x8])) [0  S4 A32]))
                    (expr_list:SI (use (mem/f:SI (plus:SI (reg/f:SI 7 sp)
                                    (const_int 12 [0xc])) [0  S4 A32]))
                        (nil)))))))
(insn 14 13 18 2 (set (reg:SI 83 [ <retval> ])
        (const_int 0 [0])) "hello_world.c":8:1 60 {*movsi_internal}
     (nil))
(insn 18 14 19 2 (set (reg/i:SI 0 ax)
        (const_int 0 [0])) "hello_world.c":8:1 60 {*movsi_internal}
     (expr_list:REG_DEAD (reg:SI 83 [ <retval> ])
        (nil)))
(insn 19 18 0 2 (use (reg/i:SI 0 ax)) "hello_world.c":8:1 -1
     (nil))
;;  succ:       EXIT [always]  count:1073741824 (estimated locally) (FALLTHRU)
;; lr  out 	 0 [ax] 6 [bp] 7 [sp] 16 [argp] 19 [frame]
;; live  out 	 0 [ax] 6 [bp] 7 [sp] 16 [argp] 19 [frame]


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-02-22 15:45 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-22 15:44 A problem with passing the Global Offset Table address to a function in %edx Barnes, Richard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).