[Anthy-dev 2553] Re: ScmObjInternalのCompacting

Back to archive index

YamaKen yamak****@bp*****
2005年 10月 16日 (日) 04:58:17 JST


ヤマケンです。

今まで主観的な予想に基づいて話していた点についていくつか実験した
ので、その結果を踏まえて話を進めます。

r5rs/sigscheme/experimental/imm-const/に調査用コードと結果を置い
といたので興味のある方はどうぞ。必要なら適当にいじってください。

At Fri, 14 Oct 2005 02:14:24 -0700,
jun.l****@gmail***** wrote:
> On Fri, 14 Oct 2005 10:42:35 +0900
> YamaKen <yamak****@bp*****> wrote:
> 
> > At Thu, 13 Oct 2005 16:59:59 -0700,
> > jun.l****@gmail***** wrote:
> > > ここを
> > > .......0|11G : Integer (imm)
> > > ......01|11G : Const (imm)
> > > ......11|11G : Char (imm)
> > > とすれば、#f, (), unbound, #t, EOF, undef その他入れたければ 128M 種類が
> > > 即値に入ります。int の表現範囲も犠牲になりません。
> > 
> > charも自由度の高いエンコーディングのためになるべく広く取っておき
> > たいところです。それからNULL|tag形式は後述のように実行・サイズ効
> > 率のためでもあるので。
> 
> 24 bit じゃ不足ですか? しかも↑だと 24 どころか 27 もあるんですが…私
> は 24 bit あれば十分と考えていますが、そうすると char に 27 割り当てよ
> うが 26 割り当てようが使いません。でも int 型は bit はあればあるほど望
> ましいといえます。だから code 空間の使用率が低いと保証されている
> char/const 型を迫害したんですが。

将来的に複数エンコーディングを自動的に扱えるようにしたくなった場
合に、単一内部エンコーディングにcanonicalizeせずにタグ付けした生
コードを格納する事を可能にする余地を可能な限り大きく残しておきた
かったんですが、これは定数をNULL|tagとOthersに追い出しても大した
オーバヘッドは無いと見越しての事でした。後述のように思ったより影
響があったので井上さん案の方に賛成します。

ただし#fを0にエンコードする事についてはまだはっきりと得失が見え
てないので、選択可能にしておきましょう。

> > あ、ついでですがshift無しでcharacter valueを扱う場合のためにint
> > じゃなくてcharの方を011Gにした方がよいと思います。
> > 
> > ......0|11G : Char    (imm)
> > ------------------------------
> > ......1|11G : Integer (imm)
> 
> Shift 無しで扱う?? Tag bit の操作を思い違われていませんか? (下記参照)

はい。shift無しで。瑣末な事なんで実際に必要になった時に。

> > > > S->Y of Others
> > > >    O           Type                 content of O
> > > > ........|001 : Symbol             : vcell
> > > 
> > > string name でないといけません。Others の定義は S->Y が ScmObj の
> > > convention に縛られない、です。
> > 
> > stringの8byte alignを保証できるならそれでもいいんですが、さすが
> > にちょっと移植性が気になります。heapと違って割り当てサイズ小さい
> > し。
> 
> vcell の tag が 001 固定だと、CONSP(VCELL(any_symbol)) が常に真になっ
> てしまいます。vcell は S の型ではなくて、vcell の tag 型を持っている必
> 要があります。いうなれば vcell の tag bits は S の所有物ではありません。

そうでした。他の部分を考えてる時はちゃんと理解してるつもりだった
んですが、つい頭から抜けてしまってました。

> Alignment については、どうせいずれ posix_memalign() の代替物を用意する
> ことになるのでそれを使えばいいと思います。その上で symbol を優遇して 
> other-tag に圧縮をかければ alignment の要求は 4 bytes まで落とせるので、
> memory の浪費も 1 object 4 bytes までになります。

あ、しまった。nameをY側に置いててもそういう技が使えるんでしたね。
4byte alignなら何も問題はありません。

> > ScmObj の convention に縛られない、というのはわかるんですが、
> > ScmObjを格納してはいけないという制約もあるんでしたっけ?
> 
> G bit を立ててますから、基本的にはダメです。ただし、例えば S->Y が必ず
> cons 型だとわかっているなら、それをその型の other-tag として定義するこ
> とはできます。滅多な事で使うわけにはいきません。

了解です。

> > が、こっちを使う方が適切ですね。
> > 
> > typedef void (*ScmCFunc)(void);
> 
> うーむ、これはそもそもどうやって使うもんなんでしょうか。
> ;; 実装内容は知っています

単に関数へのポインタであるという型情報以上の意味はありません。正
式な型にキャストする時にvoid *と違ってwarningを出さないだけです。

逆にprintf("%p", func)みたいにvoid *として扱う必要がある場合は
SCM_REINTERPRET_CASTで黙らせます。

> > > 何故? >NULL|tag, #f==0
> > 
> > #f == 0についてはzero register, jnz, jz, cmovnz, cmovzの類での効
> > 率化期待です。
> > 
> > #fや()は井上さん形式にすると5-6bit必要になるんでアーキテクチャに
> > よっては最小のimmediate operand fieldに収まらなくなったりするし、
> > 明示的な比較命令も必要になります。
> 
> 良く使うのは 7 bit ですけど、入らんのですか。具体的にはどの 
> architecture? (興味津々

正直に言ってしまうと、実際のSigSchemeのコードにどのような影響を
与えるかは考えずに脊髄反射してしまいました。

しかし、実際に調べてみるとRISC以降の世代では大抵のアーキテクチャ
で基本命令長(16bit or 32bit)の2オペランド操作に8bit immediateを
取れるようになっています。したがってcmpi等のimmediate値との比較
に限れば命令サイズは同じです。

以下は参考まで。

68k/ColdFireにはaddq, subq, moveq等の3bit immediateを取る命令が
あります。

  http://oldwww.nvg.ntnu.no/amiga/MC680x0_Sections/subq.HTML

MIPS16ではoffset付きload, storeが5bit、3オペランドaddが4bit
immediateを取ります。

  http://www.delorie.com/agenda/specs/vr4181-specs.pdf

ARM Thumbでは3オペランド算術演算に3bit immediateがあるようです。

  http://www.arm.com/pdfs/QRC0001H_rvct_v2.1_thumb.pdf

V800シリーズでは2オペランドmov, add, mulh, compareのimmediateは
5bit です。

  http://www.necel.com/cgi-bin/nesdis/dl_docpdf.cgi?lang=E&litcode=U10243EJ7V0UM00

H8はshift等を除いて8bit immediateが最小のようです。

Analog Devices Blackfinではload, addが7bit immediateを取るようです。

  http://www.analog.com/processors/epManualsDisplay/0,2795,,00.html?SectionWeblawId=207&ContentID=67993&Language=English

SH, M32R, FR-V等は調べてません。SHはマニュアルのダウンロードにユー
ザ登録が必要だったんで面倒でやめました。

> > > CONSP() が多いので code size は増えそうな気がしますが? というか↑のように
> > > して他の即値と一緒に入れましょうよ。
> > 
> > 逆にNFALSEP, FALSEPではコードサイズ減少が見込めるんでそうそう肥
> > 大化はしないんじゃないかと思ってます。CONSPでもレジスタに残って
> > る値のゼロ判定が追加されるだけだし。実際どうなるか確実な予測はで
> > きてませんが。
> 
> そうか、cons の下が 0 だとその辺がえらく簡略化されますね。
> ;; x86 はあんまり恩恵無さそうですが

SH, m68k, MIPSでは実際にコードが減る事を確認できました。

> でも、7 bit 以上の即値を効率的に扱えない処理系が多いのならそうしてもいい
> と思いますが、ちょっと正直なところ 7 bit 以下に turnover をもってる 
> architecture がどれぐらいあるのか見せつけられないと納得いきません。とり
> あえず手元の M32R, PowerPC, Alpha, x86-64 を見ましたが、こいつら design
> が古いのでアテになりません (M32R はともかく)。

上述のように比較命令が入る場合はほとんどのアーキテクチャで差が無
く、逆にCLOSUREP等の負担が増してしまう事を実際に確認できたので、
#f以外は井上さん案の方が効率的です。

#fを0にエンコードするのもアーキテクチャによっては効果が無い一方、
CONSPは確実にコード量が増えます。よってデフォルトは井上さん案に
した方がいいような気がします。しかしせっかくですから
sigschemetypeのobject抽象化の試験を兼ねて選択可能にしたいと思い
ます。面倒なら私が後から追加しますんで、井上さん案のみで進めてく
ださい。

しかしgccの-mtuneはpentium以降を指定すると-Osでもメモリ/キャッシュ
効率はおかまいなしですね。libuimのビルドでも気にしておいた方がい
いかもしれません。

-------------------------------
ヤマケン yamak****@bp*****



Anthy-dev メーリングリストの案内
Back to archive index