This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: small varasm.c improvements


David Edelsohn <dje@watson.ibm.com> writes:

> 	The const-elim-? tests fail on AIX as well:
>
> PASS: gcc.dg/const-elim-1.c (test for excess errors)
> FAIL: gcc.dg/const-elim-1.c scan-assembler-not LC

This appears to be a problem with the rs6000 back end.  Code like this

void
test1(void)
{
        if (23 == 23)
                return;
        else {
                const char *str = "pack my box with five dozen liquor jugs";
                use_str(str);
        }
}

will not emit the string, but this

void
test2(void)
{
        const char *str = "pack my box with five dozen liquor jugs";
        if (23 == 23)
                return;
        else {
                use_str(str);
        }
}

will.  Initial RTL generation for test2 produces:

(insn 8 6 9 (nil) (use (symbol_ref/f:SI ("*LC..0") 
                        [flags 0x2] <string_cst 0x4038d960>)) -1 (nil)
    (nil))
(insn 9 8 12 (nil) (set (reg/v/f:SI 118 [ str ])
        (mem/u:SI (plus:SI (reg:SI 2 r2)
                (const:SI (minus:SI (symbol_ref/u:SI ("*LC..1") [flags 0x2])
                        (symbol_ref:SI ("*LCTOC..1"))))) [5 S4 A8])) -1 (nil)
    (nil))

(jump_insn 12 9 13 (nil) (set (pc)
        (label_ref 24)) -1 (nil)
    (nil))

(barrier 13 12 14)

(jump_insn 14 13 15 (nil) (set (pc)
        (label_ref 20)) -1 (nil)
    (nil))

(barrier 15 14 16)

(code_label 16 15 17 2 "" [0 uses])

(code_label 20 19 21 3 "" [0 uses])

(code_label 24 22 0 1 "" [0 uses])

(the numbers don't match because I deleted all the notes)

None of the optimizer passes can get rid of insn 8, even though
everything else is deleted.  Therefore, when mark_constant_pool is
called from final, it will mark the symbol at LC..0, even though there
is no real use anymore.

With test1, we get instead


(jump_insn 9 6 10 (nil) (set (pc)
        (label_ref 27)) -1 (nil)
    (nil))

(barrier 10 9 11)

(jump_insn 11 10 12 (nil) (set (pc)
        (label_ref 23)) -1 (nil)
    (nil))

(barrier 12 11 13)

(code_label 13 12 14 2 "" [0 uses])

(insn 17 15 18 (nil) (use (symbol_ref/f:SI ("*LC..0") [flags 0x2] <string_cst 0x4038d9d8>)) -1 (nil)
    (nil))

(insn 18 17 20 (nil) (set (reg/v/f:SI 118 [ str ])
        (mem/u:SI (plus:SI (reg:SI 2 r2)
                (const:SI (minus:SI (symbol_ref/u:SI ("*LC..1") [flags 0x2])
                        (symbol_ref:SI ("*LCTOC..1"))))) [5 S4 A8])) -1 (nil)
    (nil))

(insn 20 18 21 (nil) (set (reg:SI 3 r3)
        (reg/v/f:SI 118 [ str ])) -1 (nil)
    (nil))

(call_insn 21 20 22 (nil) (parallel [
            (set (reg:SI 3 r3)
                (call (mem:SI (symbol_ref:SI ("use_str[DS]") [flags 0x41] <function_decl 0x40395828 use_str>) [0 S4 A8])
                    (const_int 32 [0x20])))
            (use (const_int 0 [0x0]))
            (clobber (scratch:SI))
        ]) -1 (nil)
    (nil)
    (expr_list (use (reg:SI 3 r3))
        (nil)))

(code_label 23 22 24 3 "" [0 uses])

(code_label 27 25 0 1 "" [0 uses])

In this case, try_optimize_cfg can delete the entire basic block
starting with code_label 13, including the problematic use, so no
label gets emitted.

Looking at rs6000.c I am suspicious of this bit of rs6000_emit_move:

      else if (mode == Pmode
               && CONSTANT_P (operands[1])
               && ((GET_CODE (operands[1]) != CONST_INT
                    && ! easy_fp_constant (operands[1], mode))
                   || (GET_CODE (operands[1]) == CONST_INT
                       && num_insns_constant (operands[1], mode) > 2)
                   || (GET_CODE (operands[0]) == REG
                       && FP_REGNO_P (REGNO (operands[0]))))
               && GET_CODE (operands[1]) != HIGH
               && ! legitimate_constant_pool_address_p (operands[1])
               && ! toc_relative_expr_p (operands[1]))
        {
          /* Emit a USE operation so that the constant isn't deleted if
             expensive optimizations are turned on because nobody
             references it.  This should only be done for operands that
             contain SYMBOL_REFs with CONSTANT_POOL_ADDRESS_P set.
             This should not be done for operands that contain LABEL_REFs.
             For now, we just handle the obvious case.  */
          if (GET_CODE (operands[1]) != LABEL_REF)
            emit_insn (gen_rtx_USE (VOIDmode, operands[1]));

That clearly intends to prevent the constant from being deleted *even
if* nothing uses it, which is precisely what will cause const-elim-1.c
to fail.  I do not know what the consequences of removing that code
would be in the large scale, but deleting it gets rid of two of the
three constants that are being emitted unnecessarily.  The third is
held in place by this insn

(insn# # # 0x403a40c0 (parallel [
            (set (mem/s:BLK (reg/f:SI 128) [6 S+0 S24 A128])
                (mem/s/u:BLK (reg/f:SI 119) [2 S24 A32]))
            (use (const_int 24 [0x18]))
            (use (const_int 4 [0x4]))
            (clobber (reg:SI 5 r5))
            (clobber (reg:SI 6 r6))
            (clobber (reg:SI 7 r7))
            (clobber (reg:SI 8 r8))
            (clobber (reg:SI 9 r9))
            (clobber (reg:SI 10 r10))
            (clobber (scratch:SI))
        ])# {*rs6000.md:9244} (nil)
    (nil))

where (reg 119) has been loaded with the address of the constant.  I
do not know why this is not getting deleted; it's the last instruction
in the function.

zw


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]