2

iPhone/iPad で単語配列を最適に埋めるための NEON コードを書き込もうとしています。この問題の非常に奇妙な点は、NEON 命令が q3 に値を割り当てると、コードが_ARCLite_loadという名前の関数にジャンプするように見えることです。誰かが前にこのようなものを見たことがあります:

(xcode 4.6 および -no-integrated-as フラグでコンパイルされた test_time_asm.s)

.section __TEXT,__text,regular
.section __TEXT,__textcoal_nt,coalesced
.section __TEXT,__const_coal,coalesced
.section __TEXT,__picsymbolstub4,symbol_stubs,none,16
.text   
.align 2
.globl _fill_neon_loop1
.private_extern _fill_neon_loop1
_fill_neon_loop1:
  push {r4, r5, r6, r7, lr}
  // r0 = wordPtr
  // r1 = inWord
  // r2 = numWordsToFill
  mov   r2, #1024
  // Load r1 (inWord) into NEON registers
  vdup.32 q0, r1
  vdup.32 q1, r1
  vdup.32 q2, r1
  vdup.32 q3, r1 (Stepping into this instruction jumps into __ARCLite__load)

NEONFILL16_loop1:
  vstm r0!, {d0-d7}
  sub r2, r2, #16
  cmp r2, #15
  bgt NEONFILL16_loop1

  mov   r0, #0
  pop {r4, r5, r6, r7, pc}
  .subsections_via_symbols

ASM 命令のシングル ステップは、q3 に割り当てられる命令まで機能します。その命令をステップ オーバーすると、コードは次の場所にジャンプするように見えます。

(gdb) bt
#0  0x0009a568 in __ARCLite__load () at /SourceCache/arclite_iOS/arclite-31/source/arclite.m:529
#1  0x0007b050 in test_time_run_cases () at test_time.h:147

これは本当に奇妙で、NEON レジスタへの割り当てがなぜこれを引き起こすのか理解できません。NEON は、私が気付いていない特別なことに q3 を使用しますか?

また、dN (64 ビット regs) を使用してレジスタをロードしようとしましたが、d7 への割り当てでも同じ結果になりました。

  vdup.32 d0, r1
  vdup.32 d1, r1
  vdup.32 d2, r1
  vdup.32 d3, r1
  vdup.32 d4, r1
  vdup.32 d5, r1
  vdup.32 d6, r1
  vdup.32 d7, r1

(後で)提案された変更をいじった後、問題の根本原因を見つけました。それはこのブランチ ラベルでした。

NEONFILL16_loop1:
  vstm r0!, {d0-d7}
  sub r2, r2, #16
  cmp r2, #15
  bgt NEONFILL16_loop1

何らかの理由で、ブランチ ラベルがコード内の別の場所へのジャンプを引き起こしていました。上記のラベルを次のものに置き換えると、問題が修正されました。

1:
  vstm r0!, {d0-d7}
  sub r2, r2, #16
  cmp r2, #15
  bgt 1b

これは、xcode 4.6 で配布された clang の ASM パーサーのバージョンでは奇妙なことかもしれませんが、とにかくラベルを変更するだけで修正されました。

4

2 に答える 2

0

q3 は特別な役割に割り当てられておらず、保持する必要もありません。これについては心配しないでください。

auselen の推測は正しいと思います。分解図を見れば一目瞭然。

以下でこれを試してください:

.section __TEXT,__text,regular
.section __TEXT,__textcoal_nt,coalesced
.section __TEXT,__const_coal,coalesced
.section __TEXT,__picsymbolstub4,symbol_stubs,none,16
.text   
.align 2
.globl _fill_neon_loop1
.private_extern _fill_neon_loop1
_fill_neon_loop1:
  // r0 = wordPtr
  // r1 = inWord
  // r2 = numWordsToFill
  mov   r2, #1024
  // Load r1 (inWord) into NEON registers
  vdup.32 q0, r1
  vdup.32 q1, r1
  vdup.32 q2, r1
  vdup.32 q3, r1
  subs r2, r2, #16
  bxmi lr

NEONFILL16_loop1:
  vstm r0!, {d0-d7}
  subs r2, r2, #16
  bpl NEONFILL16_loop1

  mov   r0, #0
  bx lr
  .subsections_via_symbols

ループ内の cmp に加えて、廃止されたレジスタを完全に削除しました。(ご存知のように、すべてを最適化する必要があります:))

auselen の推測が正しければ、トレースのタイミングが変更された可能性があり、ARClite へのステップは後で発生します。

于 2013-07-02T09:00:31.460 に答える
0

手書きの ARM コードでどこか変なところにジャンプするのはほとんどの場合、親指のインターワーキングをいじり、関数が間違ったモードで実行されていたためです。その結果、命令ストリームは CPU にとってゴミのように見え、ジャンプします。怪我をして倒れるまでランダムに。

関数のエントリポイントであるすべてのラベルには、次のアセンブリ ディレクティブが必要です。

.type _fill_neon_loop1, %function

これは、リンカがBL命令を修正するとき、または関数のアドレスを計算するときに、正しいモードで実行されるように適切な調整を行う必要があることをリンカに伝えます。

于 2013-07-05T15:38:46.360 に答える