コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2020年7月8日 >>> 2020年7月8日
link もっと後

2020年7月8日

GCCを調べる - その15-3 - ベクトルレジスタを使用するmachine mode

目次: GCC

前回(2020年7月7日の日記参照)はベクトルレジスタが選択されてしまう仕組みが何となくわかりました。

今回やりたかったことを復習しておくと「ベクトルの演算以外でベクトルレジスタを使わないでほしい」でした。つまりira_prohibited_class_mode_regs[cl][j] のうちベクトル以外のmachine modeかつベクトルレジスタに相当するビットを「セット」つまり割り当て禁止状態にすれば良いはずです。

配列の次元のうちclはレジスタのクラス(enum reg_class)で、jはmachine modeです。レジスタのクラスは以前(2020年3月28日の日記参照)ちょっとだけ使いました。幸いなことに、今回はレジスタのクラスは気にしなくて良いです、というかコードのif文の条件hard_regno_mode_ok(hard_regno, (machine_mode) j) を見るとわかるように、そもそもレジスタのクラスが渡されないので、ターゲット側(=RISC-V依存の実装部分)で何もできないです。

重要なのはmachine modeで、ベクトル以外のモード(浮動小数点など)だったらベクトルレジスタを割り当て禁止状態にすれば良いです。

targetm.hard_regno_mode_ok() のRISC-V向け実装

// gcc/config/riscv/riscv.c

/* Implement TARGET_HARD_REGNO_MODE_OK.  */

static bool
riscv_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
{
  unsigned int nregs = riscv_hard_regno_nregs (regno, mode);

  if (GP_REG_P (regno))
    {
      if (!GP_REG_P (regno + nregs - 1))
	return false;
    }
  else if (FP_REG_P (regno))
    {
      if (!FP_REG_P (regno + nregs - 1))
	return false;

      if (GET_MODE_CLASS (mode) != MODE_FLOAT
	  && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
	return false;

      /* Only use callee-saved registers if a potential callee is guaranteed
	 to spill the requisite width.  */
      if (GET_MODE_UNIT_SIZE (mode) > UNITS_PER_FP_REG
	  || (!call_used_or_fixed_reg_p (regno)
	      && GET_MODE_UNIT_SIZE (mode) > UNITS_PER_FP_ARG))
	return false;
    }
  else if (VP_REG_P (regno))    //★★前回足した実装
    {
      return true;
    }
  else
    return false;

...

ここでベクトル系のmachine modeを直接記述(mode == V64SImodeなど)しても間違いではないと思うのですが、単純にモードがたくさんあると鬱陶しいですし、該当するモードがあとで増えたときの修正が大変です。こういうときはmachine modeのクラスが便利です。クラスってなんだったかというと、machmode.defやriscv-modes.defに書いたあれです。

machine modeクラスの定義

// gcc/machmode.def

...

/* Basic integer modes.  We go up to TI in generic code (128 bits).
   TImode is needed here because the some front ends now genericly
   support __int128.  If the front ends decide to generically support
   larger types, then corresponding modes must be added here.  The
   name OI is reserved for a 256-bit type (needed by some back ends).
    */

//★★MODE_INTクラスになる

INT_MODE (QI, 1);
INT_MODE (HI, 2);
INT_MODE (SI, 4);
INT_MODE (DI, 8);
INT_MODE (TI, 16);

...


// gcc/config/riscv/riscv-modes.def

//★★MODE_FLOATクラスになる

FLOAT_MODE (TF, 16, ieee_quad_format);

//★★以前、追加した実装
//★★VECTOR_MODEの場合は少し特殊で、MODE_VECTOR + 最初の引数 クラスになる
//★★この例だとMODE_VECTOR_INTになる

VECTOR_MODE (INT, SI, 32);
VECTOR_MODE (INT, SI, 64);

クラスは上記の通り各所の *.defにて定義されますが、正直言ってどこにあるかわかりにくいし、クラスの名前も見えません。machine modeとクラスの対応を確認するだけなら、ビルド時に生成されるinsn-modes.cを見たほうが早いです。

machine modeとクラスの対応、早見方法

// build_gcc/insn-modes.c

const unsigned char mode_class[NUM_MACHINE_MODES] =
{
  MODE_RANDOM,             /* VOID */
  MODE_RANDOM,             /* BLK */
  MODE_CC,                 /* CC */
  MODE_INT,                /* BI */
  MODE_INT,                /* QI */
  MODE_INT,                /* HI */
  MODE_INT,                /* SI */
  MODE_INT,                /* DI */
  MODE_INT,                /* TI */
  MODE_FRACT,              /* QQ */
  MODE_FRACT,              /* HQ */
  MODE_FRACT,              /* SQ */
  MODE_FRACT,              /* DQ */
  MODE_FRACT,              /* TQ */
  MODE_UFRACT,             /* UQQ */
  MODE_UFRACT,             /* UHQ */
  MODE_UFRACT,             /* USQ */
  MODE_UFRACT,             /* UDQ */
  MODE_UFRACT,             /* UTQ */
  MODE_ACCUM,              /* HA */
  MODE_ACCUM,              /* SA */
  MODE_ACCUM,              /* DA */
  MODE_ACCUM,              /* TA */
  MODE_UACCUM,             /* UHA */
  MODE_UACCUM,             /* USA */
  MODE_UACCUM,             /* UDA */
  MODE_UACCUM,             /* UTA */
  MODE_FLOAT,              /* SF */
  MODE_FLOAT,              /* DF */
  MODE_FLOAT,              /* TF */

...

  MODE_COMPLEX_FLOAT,      /* SC */
  MODE_COMPLEX_FLOAT,      /* DC */
  MODE_COMPLEX_FLOAT,      /* TC */
  MODE_VECTOR_INT,         /* V32SI */
  MODE_VECTOR_INT,         /* V64SI */
};

ベクトル系のmachine modeを引っ掛けるにはMODE_VECTOR_INTを使えば良さそうです。今の実装では使っていませんがRISC-Vのベクトルは浮動小数点のベクトル(MODE_VECTOR_FLOAT)も扱えるはずなので、これも条件に追加しておきましょう。

targetm.hard_regno_mode_ok() のRISC-V向け実装、修正版

// gcc/config/riscv/riscv.c

/* Implement TARGET_HARD_REGNO_MODE_OK.  */

static bool
riscv_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
{
  unsigned int nregs = riscv_hard_regno_nregs (regno, mode);

  if (GP_REG_P (regno))
    {
      if (!GP_REG_P (regno + nregs - 1))
	return false;
    }
  else if (FP_REG_P (regno))
    {
      if (!FP_REG_P (regno + nregs - 1))
	return false;

      if (GET_MODE_CLASS (mode) != MODE_FLOAT
	  && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
	return false;

      /* Only use callee-saved registers if a potential callee is guaranteed
	 to spill the requisite width.  */
      if (GET_MODE_UNIT_SIZE (mode) > UNITS_PER_FP_REG
	  || (!call_used_or_fixed_reg_p (regno)
	      && GET_MODE_UNIT_SIZE (mode) > UNITS_PER_FP_ARG))
	return false;
    }
  else if (VP_REG_P (regno))    //★★前回足した実装
    {
      if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT
	  && GET_MODE_CLASS (mode) != MODE_VECTOR_FLOAT)    //★★今回足した実装
	return false;

      return true;
    }
  else
    return false;

...

修正後のコンパイラは浮動小数点数を60個使うコードを正常にコンパイルできます。たったこの3行を説明するだけで、えらい時間を費やしました。GCCは魔界ですね。

お気づきの方もいるかと思いますが、実は1つ上のelse if節にほぼ全く同じ判定文が既にあります。何も考えずに上からパクってMODEの名前を書き換えれば、今回の問題は直るんですけど、それだとどうして直るのか全くわからないんですよ……。

編集者:すずき(2023/09/24 11:52)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
2020年7月8日 >>> 2020年7月8日
link もっと後

管理用メニュー

link 記事を新規作成

<2020>
<<<07>>>
---1234
567891011
12131415161718
19202122232425
262728293031-

最近のコメント5件

  • link 24年4月22日
    hdkさん (04/24 08:36)
    「うちのHHFZ4310は15年突破しまし...」
  • link 24年4月22日
    すずきさん (04/24 00:37)
    「ちゃんと数えてないですけど蛍光管が10年...」
  • link 24年4月22日
    hdkさん (04/23 20:52)
    「おお... うちのHHFZ4310より後...」
  • link 20年6月19日
    すずきさん (04/06 22:54)
    「ディレクトリを予め作成しておけば良いです...」
  • link 20年6月19日
    斎藤さん (04/06 16:25)
    「「Preferencesというメニューか...」

最近の記事3件

  • link 24年2月7日
    すずき (04/24 02:52)
    「[複数の音声ファイルのラウドネスを統一したい] PCやデジタル音楽プレーヤーで音楽を聞いていると、曲によって音量の大小が激しく...」
  • link 24年4月22日
    すずき (04/23 20:13)
    「[仕事部屋の照明が壊れた] いきなり仕事部屋のシーリングライトが消えました。蛍光管の寿命にしては去年(2022年10月19日の...」
  • link 24年4月17日
    すずき (04/18 22:44)
    「[VSCodeとMarkdownとPlantUMLのローカルサーバー] 目次: LinuxVSCodeのPlantUML Ex...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 04/24 08:36