GNURX用のCCRXmachine.hとCCRXmachine.cというソースがe2 studioフォルダにありました(内容は概ね名前から予想される通りのものでした)

こんにちは。NoMaYです。

e2 studio v6.3.0がリリースされていたので、インストールして幾つかプロジェクトを作成して、いつものようにe2 studioのインストールフォルダを眺めていたら、CCRXmachine.hとCCRXmachine.cというファイルがあることに気付きました。中を見てみると、概ねファイル名から予想される通りのソースファイルでした。(今までのe2 studioのインストールフォルダを見直してみたところ、以前からあったことが分かりましたが、今まで気付きませんでした。) ただ、一部コメントアウトされているものがあったり、以前に別スレッド『GUNRX用プロジェクトのスマートコンフィグレータのBSPを見ていて気付いた変な移植コード』で話題にしたことと同じ元のコードの意図を理解していない書き換えがあったり、ちょっと惜しいような気もしました。

e2 studioインストールフォルダ\internal\projectgen\rx\Generate\CCRXConversion\inc\CCRXmachine.h



e2 studioインストールフォルダ\internal\projectgen\rx\Generate\CCRXConversion\inc\CCRXmachine.c



Parents
  • GNURX の __builtin_rx_xchg() を確認してみましたが

     $ cat -n xchgTest.c
         1  extern int a, b;
         2
         3  void hoge(void)
         4  {
         5      __builtin_rx_xchg(&a, &b);
         6  }
    
    $ rx-elf-gcc -v
    Using built-in specs.
    COLLECT_GCC=C:\Renesas\e2studio\GCC for Renesas RX 4.8.4.201801-GNURX-ELF\rx-elf\rx-elf\bin\rx-elf-gcc.exe
    COLLECT_LTO_WRAPPER=c:/renesas/e2studio/gcc\ for\ renesas\ rx\ 4.8.4.201801-gnurx-elf/rx-elf/rx-elf/bin/../libexec/gcc/rx-elf/4.8.4.201801-GNURX/lto-wrapper.exe
    Target: rx-elf
    Configured with: /builder/AutomatedBuilds/rx/builds/2018q1_RX_RC3/rx/source/gcc/configure --target=rx-elf --host=i586-mingw32msvc --enable-languages=c,c++ --disable-shared --with-newlib --enable-lto --enable-libssp --enable-plugins --enable-gold --disable-libstdcxx-pch --with-pkgversion=GCC_Build_20180316 --prefix=/builder/AutomatedBuilds/rx/builds/2018q1_RX_RC3/rx/rx_win
    Thread model: single
    gcc version 4.8.4.201801-GNURX (GCC_Build_20180316)
    
    $ rx-elf-gcc -O2 xchgTest.c -S -o -
            .file   "xchgTest.c"
            .section P,"ax"
            .global _hoge
            .type   _hoge, @function
    _hoge:
            mov.L   #_a, r2
            mov.L   [r2], r3
            mov.L   #_b, r5
            mov.L   [r5], r4
            mov.L   r3, [r2]
            xchg    r4, r3
            mov.L   r4, [r5]
            rts
            .size   _hoge, .-_hoge
            .ident  "GCC: (GCC_Build_20180316) 4.8.4.201801-GNURX"
    
    $   
    

    ちょっと排他制御には使えない感じですね。

  • つーか、ただの交換も機能しない罠。
  • こんにちは。NoMaYです。

    fujita nozomu said:
    つーか、ただの交換も機能しない罠。

    GNURXの__builtin_rx_xchg()関数のソースをGNURXのGCCのソースの中から探してみると、以下の通りでした。何か場合分けもされているようです。[追記] 今回のはelse節の方だと思うのですが、ひょっとして、後続の最適化処理で命令の順番が入れ替わってしまったのでは? もしそうなら、別の部分(命令定義部?)にヤバイ不具合があるのではないかという予感がします、、、[ここまで追記]

    rx_gcc4.8.4_2018q1\gcc\gcc\config\rx\rx.c

    static rtx
    rx_expand_builtin_xchg (tree exp)
    {
        rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
        rtx arg2 = expand_normal (CALL_EXPR_ARG (exp, 1));

        /* if arg2 is a reg than we can safely use the form xchg [Rs].memex, Rd, othewise only xchg Rs, Rd */
        if(REG_P(arg2))
        {
            rtx mem1 = gen_rtx_MEM (SImode, arg1);
            rtx mem2 = gen_rtx_MEM (SImode, arg2);

            rtx mem1toreg = copy_to_reg(mem1);

            MEM_VOLATILE_P (mem1) = 1;
            MEM_VOLATILE_P (mem2) = 1;

            emit_insn (gen_exchangesi (mem1toreg, mem2));
            emit_move_insn(mem1, mem1toreg);
        }
        else
        {
            rtx mem1 = gen_rtx_MEM (SImode, arg1);
            rtx mem2 = gen_rtx_MEM (SImode, arg2);

            rtx mem1toreg = copy_to_reg(mem1);
            rtx mem2toreg = copy_to_reg(mem2);

            MEM_VOLATILE_P (mem1) = 1;
            MEM_VOLATILE_P (mem2) = 1;

            emit_insn (gen_exchangesi (mem1toreg, mem2toreg));
            emit_move_insn(mem1, mem1toreg);
            emit_move_insn(mem2, mem2toreg);
        }

        return NULL_RTX;
    }

     

  • > ひょっとして、後続の最適化処理で命令の順番が入れ替わってしまったのでは?

    最適化レベル 0 や 1 でコンパイルすると効率は悪いものゝ交換自体には問題がないっぽいコードを吐くのでそれっぽい感じですね。

    $ rx-elf-gcc -O0 xchgTest.c -S -o -
            .file   "xchgTest.c"
            .section P,"ax"
            .global _hoge
            .type   _hoge, @function
    _hoge:
            push.l  r6
            mov.L   r0, r6
            mov.L   #_a, r5
            mov.L   [r5], r4
            mov.L   #_b, r5
            mov.L   [r5], r5
            xchg    r5, r4
            mov.L   #_a, r3
            mov.L   r4, [r3]
            mov.L   #_b, r4
            mov.L   r5, [r4]
            rtsd    #4, r6-r6
            .size   _hoge, .-_hoge
            .ident  "GCC: (GCC_Build_20180316) 4.8.4.201801-GNURX"
    
    $ rx-elf-gcc -O1 xchgTest.c -S -o -
            .file   "xchgTest.c"
            .section P,"ax"
            .global _hoge
            .type   _hoge, @function
    _hoge:
            mov.L   #_a, r3
            mov.L   [r3], r2
            mov.L   #_b, r5
            mov.L   [r5], r4
            xchg    r4, r2
            mov.L   r2, [r3]
            mov.L   r4, [r5]
            rts
            .size   _hoge, .-_hoge
            .ident  "GCC: (GCC_Build_20180316) 4.8.4.201801-GNURX"
    
    $
    
  • > つーか、ただの交換も機能しない罠。

    自己レス。
    gcc-renesas.com のサポートへ不具合として報告したところ既知の問題として対応作業中であるという回答を貰いました。
    次版かどこかで修正されるとは思いますが、過去の GNURX 対応をスッパリ切るんでもできない限りは __builtin_rx_xchg() の使用は考えるべきでないと思います。
  • 自己レス

    > つーか、ただの交換も機能しない罠。

    https://gcc-renesas.com/ja/ で知らぬ間に GCC for Renesas 4.8.4.201803-GNURX Toolchain というのが公開されており(https://gcc-renesas.com/ja/rx-download-toolchains/)、これを早速ダウンロード、インストールしてみたところ、release_notes.pdf に変更点として

    > 3. [Bug-Fix]Fixed the xchgbuiltin function.

    というのがあり、期待して確認してみたところでは

    $ rx-elf-gcc -v
    Using built-in specs.
    COLLECT_GCC=C:\Renesas\e2studio\GCC_for_Renesas_RX_4.8.4.201803-GNURX-ELF\rx-elf\rx-elf\bin\rx-elf-gcc.exe
    COLLECT_LTO_WRAPPER=c:/renesas/e2studio/gcc_for_renesas_rx_4.8.4.201803-gnurx-elf/rx-elf/rx-elf/bin/../libexec/gcc/rx-elf/4.8.4.201803-GNURX/lto-wrapper.exe
    Target: rx-elf
    Configured with: /builder/AutomatedBuilds/rx/builds/2018q3_RX_RC4/rx/source/gcc/configure --target=rx-elf --host=i686-w64-mingw32 --enable-languages=c,c++ --disable-shared --with-newlib --enable-lto --enable-libssp --enable-plugins --enable-gold --disable-libstdcxx-pch --with-pkgversion=GCC_Build_20181126 --prefix=/builder/AutomatedBuilds/rx/builds/2018q3_RX_RC4/rx/rx_win
    Thread model: single
    gcc version 4.8.4.201803-GNURX (GCC_Build_20181126)
    
    $ cat -n xchgTest.c
         1  extern int a, b;
         2
         3  void hoge(void)
         4  {
         5      __builtin_rx_xchg(&a, &b);
         6  }
    
    $ rx-elf-gcc -O2 xchgTest.c -S -o -
            .file   "xchgTest.c"
            .section P,"ax"
            .global _hoge
            .type   _hoge, @function
    _hoge:
            mov.L   #_a, r3
            mov.L   #_b, r5
            mov.L   [r3], r2
            mov.L   [r5], r4
            xchg    r4, r2
            mov.L   r2, [r3]
            mov.L   r4, [r5]
            rts
            .size   _hoge, .-_hoge
            .ident  "GCC: (GCC_Build_20181126) 4.8.4.201803-GNURX"
    
    $ rx-elf-gcc -O0 xchgTest.c -S -o -
            .file   "xchgTest.c"
            .section P,"ax"
            .global _hoge
            .type   _hoge, @function
    _hoge:
            push.l  r6
            mov.L   r0, r6
            mov.L   #_a, r5
            mov.L   [r5], r4
            mov.L   #_b, r5
            mov.L   [r5], r5
            xchg    r5, r4
            mov.L   #_a, r3
            mov.L   r4, [r3]
            mov.L   #_b, r4
            mov.L   r5, [r4]
            rtsd    #4, r6-r6
            .size   _hoge, .-_hoge
            .ident  "GCC: (GCC_Build_20181126) 4.8.4.201803-GNURX"
    
    $
    

    なんと! 交換が機能するようになったようです(ヤッターオメデトーパチパチパチ

    ……ただ、排他制御には使えないし処理としても無駄に xchg 命令が使われてるだけなので価値はないですね。

    # ゲーまた GNU Tools に報告して今度は正しく直してくれたとしても半年後とかかよ。レスポンス悪すぎて気が遠くなるな。

Reply
  • 自己レス

    > つーか、ただの交換も機能しない罠。

    https://gcc-renesas.com/ja/ で知らぬ間に GCC for Renesas 4.8.4.201803-GNURX Toolchain というのが公開されており(https://gcc-renesas.com/ja/rx-download-toolchains/)、これを早速ダウンロード、インストールしてみたところ、release_notes.pdf に変更点として

    > 3. [Bug-Fix]Fixed the xchgbuiltin function.

    というのがあり、期待して確認してみたところでは

    $ rx-elf-gcc -v
    Using built-in specs.
    COLLECT_GCC=C:\Renesas\e2studio\GCC_for_Renesas_RX_4.8.4.201803-GNURX-ELF\rx-elf\rx-elf\bin\rx-elf-gcc.exe
    COLLECT_LTO_WRAPPER=c:/renesas/e2studio/gcc_for_renesas_rx_4.8.4.201803-gnurx-elf/rx-elf/rx-elf/bin/../libexec/gcc/rx-elf/4.8.4.201803-GNURX/lto-wrapper.exe
    Target: rx-elf
    Configured with: /builder/AutomatedBuilds/rx/builds/2018q3_RX_RC4/rx/source/gcc/configure --target=rx-elf --host=i686-w64-mingw32 --enable-languages=c,c++ --disable-shared --with-newlib --enable-lto --enable-libssp --enable-plugins --enable-gold --disable-libstdcxx-pch --with-pkgversion=GCC_Build_20181126 --prefix=/builder/AutomatedBuilds/rx/builds/2018q3_RX_RC4/rx/rx_win
    Thread model: single
    gcc version 4.8.4.201803-GNURX (GCC_Build_20181126)
    
    $ cat -n xchgTest.c
         1  extern int a, b;
         2
         3  void hoge(void)
         4  {
         5      __builtin_rx_xchg(&a, &b);
         6  }
    
    $ rx-elf-gcc -O2 xchgTest.c -S -o -
            .file   "xchgTest.c"
            .section P,"ax"
            .global _hoge
            .type   _hoge, @function
    _hoge:
            mov.L   #_a, r3
            mov.L   #_b, r5
            mov.L   [r3], r2
            mov.L   [r5], r4
            xchg    r4, r2
            mov.L   r2, [r3]
            mov.L   r4, [r5]
            rts
            .size   _hoge, .-_hoge
            .ident  "GCC: (GCC_Build_20181126) 4.8.4.201803-GNURX"
    
    $ rx-elf-gcc -O0 xchgTest.c -S -o -
            .file   "xchgTest.c"
            .section P,"ax"
            .global _hoge
            .type   _hoge, @function
    _hoge:
            push.l  r6
            mov.L   r0, r6
            mov.L   #_a, r5
            mov.L   [r5], r4
            mov.L   #_b, r5
            mov.L   [r5], r5
            xchg    r5, r4
            mov.L   #_a, r3
            mov.L   r4, [r3]
            mov.L   #_b, r4
            mov.L   r5, [r4]
            rtsd    #4, r6-r6
            .size   _hoge, .-_hoge
            .ident  "GCC: (GCC_Build_20181126) 4.8.4.201803-GNURX"
    
    $
    

    なんと! 交換が機能するようになったようです(ヤッターオメデトーパチパチパチ

    ……ただ、排他制御には使えないし処理としても無駄に xchg 命令が使われてるだけなので価値はないですね。

    # ゲーまた GNU Tools に報告して今度は正しく直してくれたとしても半年後とかかよ。レスポンス悪すぎて気が遠くなるな。

Children
  • fujitaさん
    ほやです。
    -O0 指定時のコードだけど、builtin関数を1個しか書かないとhoge関数由来のコードと、builtin関数由来のコードがどこからなのか区別が付きませんが、3つ4つ並べて書いたものを見た限りではbuiltin関数由来のコードが無用に大きいと言う訳でもなさそうです。「無駄に xchg 命令が使われてるだけ」って、どういう意味ですか?(喧嘩売ってるのでなくただ聞いているだけです念のため)

  • > 「無駄に xchg 命令が使われてるだけ」って、どういう意味ですか?

    `-O2' 版:

    _hoge:
            mov.L   #_a, r3
            mov.L   #_b, r5
            mov.L   [r3], r2
            mov.L   [r5], r4
            xchg    r4, r2
            mov.L   r2r4, [r3]
            mov.L   r4r2, [r5]
            rts
    

    `-O0' 版:

    _hoge:
            push.l  r6
            mov.L   r0, r6
            mov.L   #_a, r5
            mov.L   [r5], r4
            mov.L   #_b, r5
            mov.L   [r5], r5
            xchg    r5, r4
            mov.L   #_a, r3
            mov.L   r4r5, [r3]
            mov.L   #_b, r4r3
            mov.L   r5r4, [r4r3]
            rtsd    #4, r6-r6
    

    無駄に使われてる xchg 命令はない方が良いという意味です。

  • fujita nozomuさん
    ほや です。

    なるほど。意図は理解しましたが、そこまではやってくれないのではないかと思います。

    ここから先はGCCが何でできているかの話になってしまうのですが、
    GCCではビルトイン関数をRTLで記述されたinstruction patternとして実装されます。GNURXも同様のはずです。
    参考:https://gcc.gnu.org/onlinedocs/gccint/RTL-Template.html

    C言語部分からビルトイン関数へのパラメータ引き渡しをどうコードに展開するかはGCCに任されるので、そこはビルトイン関数の中身を工夫しても改善はされないでしょう。
    (RTLの書き方で工夫の余地があるかもしれませんが、余計な事やってバグが増えるのも心配…)
    上のコードで言えば、変数から持って来る所と変数に書き戻すコードはビルトイン関数の中身ではなくパラメータ引き渡し部に相当します(最適化で消えるのも中身ではなく引き渡しのコード)。

  • RTL で最小限のコードで XCHG 命令を記述できれば最適化でおかしくなることもないのでは?

    RTL ではありませんが下記のインラインアセンブラは引数がレジスタで渡されてインライン展開された場合、一つの XCHG 命令になります。

    $ cat -n xchg.c
         1  int xchg(int a, int* b)
         2  {
         3      __asm __volatile(
         4          "xchg    [%1], %0 \n"
         5          : "+r"(a)
         6          : "r"(b)
         7          : "memory"
         8      );
         9      return a;
        10  }
    
    $ rx-elf-gcc -O2 -c xchg.c ; rx-elf-objdump -d xchg.o
    
    xchg.o:     file format elf32-rx-le
    
    
    Disassembly of section P:
    
    00000000 <_xchg>:
       0:   06 a0 10 21                     xchg    [r2].l, r1
       4:   02                              rts
    
    $
    

    これ以上は最適化不能なので最適化の影響もないですね。RTL でも同じようなことは可能では?

    $ cat -n hogera.c
         1  static inline int xchg(int a, int* b) __attribute__((always_inline));
         2  static inline int xchg(int a, int* b)
         3  {
         4      __asm __volatile(
         5          "xchg    [%1], %0 \n"
         6          : "+r"(a)
         7          : "r"(b)
         8          : "memory"
         9      );
        10      return a;
        11  }
        12
        13  extern int a, b;
        14
        15  void inlineAsmXchgTest1(void)
        16  {
        17      a = xchg(a, &b);
        18  }
        19
        20  void builtinRxXchgTest1(void)
        21  {
        22      __builtin_rx_xchg(&a, &b);
        23  }
        24
        25  void inlineAsmXchgTest2(int* a, int* b)
        26  {
        27      *a = xchg(*a, b);
        28  }
        29
        30  void builtinRxXchgTest2(int* a, int* b)
        31  {
        32      __builtin_rx_xchg(a, b);
        33  }
    
    $ rx-elf-gcc -O2 -S hogera.c -o-
            .file   "hogera.c"
            .section P,"ax"
            .global _inlineAsmXchgTest1
            .type   _inlineAsmXchgTest1, @function
    _inlineAsmXchgTest1:
            mov.L   #_a, r4
            mov.L   [r4], r5
            mov.L   #_b, r3
     ; 4 "hogera.c" 1
            xchg    [r3], r5
    
     ; 0 "" 2
            mov.L   r5, [r4]
            rts
            .size   _inlineAsmXchgTest1, .-_inlineAsmXchgTest1
            .global _builtinRxXchgTest1
            .type   _builtinRxXchgTest1, @function
    _builtinRxXchgTest1:
            mov.L   #_a, r3
            mov.L   #_b, r5
            mov.L   [r3], r2
            mov.L   [r5], r4
            xchg    r4, r2
            mov.L   r2, [r3]
            mov.L   r4, [r5]
            rts
            .size   _builtinRxXchgTest1, .-_builtinRxXchgTest1
            .global _inlineAsmXchgTest2
            .type   _inlineAsmXchgTest2, @function
    _inlineAsmXchgTest2:
            mov.L   [r1], r5
     ; 4 "hogera.c" 1
            xchg    [r2], r5
    
     ; 0 "" 2
            mov.L   r5, [r1]
            rts
            .size   _inlineAsmXchgTest2, .-_inlineAsmXchgTest2
            .global _builtinRxXchgTest2
            .type   _builtinRxXchgTest2, @function
    _builtinRxXchgTest2:
            mov.L   [r1], r5
            xchg    [r2].L, r5
            mov.L   r5, [r1]
            rts
            .size   _builtinRxXchgTest2, .-_builtinRxXchgTest2
            .ident  "GCC: (GCC_Build_20181126) 4.8.4.201803-GNURX"
    
    $ rx-elf-gcc -O0 -S hogera.c -o-
            .file   "hogera.c"
            .section P,"ax"
            .global _inlineAsmXchgTest1
            .type   _inlineAsmXchgTest1, @function
    _inlineAsmXchgTest1:
            push.l  r6
            add     #-8, r0, r6
            mov.L   r6, r0
            mov.L   #_a, r5
            mov.L   [r5], r5
            mov.L   r5, [r6]
            mov.L   #_b, 4[r6]
            mov.L   4[r6], r4
            mov.L   [r6], r5
     ; 4 "hogera.c" 1
            xchg    [r4], r5
    
     ; 0 "" 2
            mov.L   r5, [r6]
            mov.L   [r6], r5
            mov.L   r5, r4
            mov.L   #_a, r5
            mov.L   r4, [r5]
            rtsd    #12, r6-r6
            .size   _inlineAsmXchgTest1, .-_inlineAsmXchgTest1
            .global _builtinRxXchgTest1
            .type   _builtinRxXchgTest1, @function
    _builtinRxXchgTest1:
            push.l  r6
            mov.L   r0, r6
            mov.L   #_a, r5
            mov.L   [r5], r4
            mov.L   #_b, r5
            mov.L   [r5], r5
            xchg    r5, r4
            mov.L   #_a, r3
            mov.L   r4, [r3]
            mov.L   #_b, r4
            mov.L   r5, [r4]
            rtsd    #4, r6-r6
            .size   _builtinRxXchgTest1, .-_builtinRxXchgTest1
            .global _inlineAsmXchgTest2
            .type   _inlineAsmXchgTest2, @function
    _inlineAsmXchgTest2:
            push.l  r6
            add     #-16, r0, r6
            mov.L   r6, r0
            mov.L   r1, 8[r6]
            mov.L   r2, 12[r6]
            mov.L   8[r6], r5
            mov.L   [r5], r5
            mov.L   r5, [r6]
            mov.L   12[r6], r5
            mov.L   r5, 4[r6]
            mov.L   4[r6], r4
            mov.L   [r6], r5
     ; 4 "hogera.c" 1
            xchg    [r4], r5
    
     ; 0 "" 2
            mov.L   r5, [r6]
            mov.L   [r6], r5
            mov.L   r5, r4
            mov.L   8[r6], r5
            mov.L   r4, [r5]
            rtsd    #20, r6-r6
            .size   _inlineAsmXchgTest2, .-_inlineAsmXchgTest2
            .global _builtinRxXchgTest2
            .type   _builtinRxXchgTest2, @function
    _builtinRxXchgTest2:
            push.l  r6
            add     #-8, r0, r6
            mov.L   r6, r0
            mov.L   r1, [r6]
            mov.L   r2, 4[r6]
            mov.L   [r6], r5
            mov.L   [r5], r4
            mov.L   4[r6], r5
            mov.L   [r5], r5
            xchg    r5, r4
            mov.L   [r6], r3
            mov.L   r4, [r3]
            mov.L   4[r6], r4
            mov.L   r5, [r4]
            rtsd    #12, r6-r6
            .size   _builtinRxXchgTest2, .-_builtinRxXchgTest2
            .ident  "GCC: (GCC_Build_20181126) 4.8.4.201803-GNURX"
    
    $
    
  • fujita nozomuさん
    ほや です。

    >RTL で最小限のコードで XCHG 命令を記述できれば最適化でおかしくなることもないのでは?
    RTL(instruction pattern)の中には最適化は及びません。
    修正前後のコードを比較した限りでの推測ですが、最適化で問題が出たのは渡されたパラメータに書き戻す手順をRTLの中で記述していなかったからだと思います。

    > RTL でも同じようなことは可能では?
    可能ではあるでしょう。
    RTLの記述で明示的にレジスタ渡しやアドレス渡しに限定するなど、渡されたパラメータの属性毎に書き分けをすれば出力コードはもっと短くなると思います。
    (書き分け方はこの辺にも書いてあります。難しそう→ https://gcc.gnu.org/onlinedocs/gccint/Expander-Definitions.html)
    しかしそういう事をやり始めると書き分けのケースから漏れたパターンは正しく処理されないし、他のinstruction patternも同じようにしなきゃならなくなったり、なんだか大変な事になりそうな気がします。
    「頑張ってみたけど、最適化に任せた方がマシだった」という結果になるかも。