コグノスケ


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

link もっと前
2020年5月25日 >>> 2020年5月25日
link もっと後

2020年5月25日

GCCを調べる - その12-1 - 続、オプションO0のエラー調査(define_insn追加編)

目次: GCC

引き続き、ベクトル型を使用する際の下記の問題に取り組みます。

  • 最適化オプションをO0にするとコンパイラがinternal errorを出す

前回(2020年5月22日の日記2020年5月23日の日記2020年5月24日の日記参照)にてdefine_expandを追加し、Internal compile error: maximum number of generated reload insns per insn achieved (90) は出なくなりましたが、別のエラーが出ました。

define_expand追加後のエラー
b.c: In function '_start':
b.c:25:1: error: unrecognizable insn:
   25 | }
      | ^
(insn 10 11 0 2 (set (mem/c:V64SI (reg/f:SI 108) [1 v1+0 S256 A2048])
        (reg:V64SI 109 [ v1 ])) "b.c":7:2 -1
     (nil))
during RTL pass: vregs
dump file: b.c.237r.vregs
b.c:25:1: internal compiler error: in extract_insn, at recog.c:2294

エラーの起きている箇所はvregというパスで、RTLのパスでは2番目(expandの次)です。序盤のパスですし、変なRTLが後ろのパスに伝わって意味不明なエラー、というケースではなさそうです。素直にエラーが出ている箇所を見ます。

エラーが起きている箇所

// gcc/recog.c

void
extract_insn (rtx_insn *insn)
{
  int i;
  int icode;
  int noperands;
  rtx body = PATTERN (insn);

...

  switch (GET_CODE (body))
    {

...

    case SET:
      if (GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
	goto asm_insn;
      else
	goto normal_insn;  //★★ここにきて、ジャンプ

...

    default:
    normal_insn:
      /* Ordinary insn: recognize it, get the operands via insn_extract
	 and get the constraints.  */

      icode = recog_memoized (insn);
      if (icode < 0)
	fatal_insn_not_found (insn);  //★★ここでエラー

...


// gcc/recog.h

/* Try recognizing the instruction INSN,
   and return the code number that results.
   Remember the code so that repeated calls do not
   need to spend the time for actual rerecognition.

   This function is the normal interface to instruction recognition.
   The automatically-generated function `recog' is normally called
   through this one.  */

static inline int
recog_memoized (rtx_insn *insn)
{
  if (INSN_CODE (insn) < 0)
    INSN_CODE (insn) = recog (PATTERN (insn), insn, 0);
  return INSN_CODE (insn);
}

// ★★PATTERN(insn) はinsn->u.fld[3]->rt_rtxを返す。

PATTERN() の3という数値はinsnのRTL formatに基づいています。insnのRTLの引数は "uuBeiie" となっており、4つ目の引数eがinsnの実行したい処理を表しているようです。残念ながらPATTERN() という関数名から、そのような事情は掴めないですよね、普通。

insn RTLのe引数

          |u |u|B|e ↓これ
 (insn 10 11 0 2 (set (mem/c:V64SI (reg/f:SI 108) [1 v1+0 S256 A2048])
      (reg:V64SI 109 [ v1 ])) "b.c":7:2 -1
   (nil))

続きを追います。recog() という関数に入っていきます。recogから始まる関数群は自動生成されたコードです。自動生成コードは読みにくいですが、GCC本体よりロジックがシンプルで理解しやすいです。GCC本体は読みにくい&理解不能なので、辛くて泣けてきます。

エラーが起きている箇所(続き)

// build_gcc/insn-recog.c

int
recog (rtx x1 ATTRIBUTE_UNUSED,
	rtx_insn *insn ATTRIBUTE_UNUSED,
	int *pnum_clobbers ATTRIBUTE_UNUSED)
{
  rtx * const operands ATTRIBUTE_UNUSED = &recog_data.operand[0];
  rtx x2, x3, x4, x5, x6, x7, x8, x9;
  rtx x10, x11, x12, x13, x14, x15, x16, x17;
  rtx x18, x19, x20, x21, x22, x23, x24, x25;
  rtx x26, x27, x28;
  int res ATTRIBUTE_UNUSED;
  recog_data.insn = NULL;
  switch (GET_CODE (x1))
    {
    case SET:
      return recog_17 (x1, insn, pnum_clobbers);  //★★これ

...


static int
recog_17 (rtx x1 ATTRIBUTE_UNUSED,
	rtx_insn *insn ATTRIBUTE_UNUSED,
	int *pnum_clobbers ATTRIBUTE_UNUSED)
{
  rtx * const operands ATTRIBUTE_UNUSED = &recog_data.operand[0];
  rtx x2, x3, x4, x5, x6, x7;
  int res ATTRIBUTE_UNUSED;
  x2 = XEXP (x1, 1);
  switch (GET_CODE (x2))
    {

...

    case CONST_INT:
    case CONST_WIDE_INT:
    case CONST_POLY_INT:
    case CONST_FIXED:
    case CONST_DOUBLE:
    case CONST_VECTOR:
    case CONST:
    case REG:
    case SUBREG:
    case MEM:
    case LABEL_REF:
    case SYMBOL_REF:
    case HIGH:
      return recog_7 (x1, insn, pnum_clobbers);  //★★これ

...


static int
recog_7 (rtx x1 ATTRIBUTE_UNUSED,
	rtx_insn *insn ATTRIBUTE_UNUSED,
	int *pnum_clobbers ATTRIBUTE_UNUSED)
{
  rtx * const operands ATTRIBUTE_UNUSED = &recog_data.operand[0];
  rtx x2, x3, x4;
  int res ATTRIBUTE_UNUSED;
  x2 = XEXP (x1, 0);
  switch (GET_CODE (x2))
    {
    case REG:
    case SUBREG:
    case MEM:
      res = recog_2 (x1, insn, pnum_clobbers);  //★★これ
      if (res >= 0)
        return res;
      break;

...


static int
recog_2 (rtx x1 ATTRIBUTE_UNUSED,
	rtx_insn *insn ATTRIBUTE_UNUSED,
	int *pnum_clobbers ATTRIBUTE_UNUSED)
{
  rtx * const operands ATTRIBUTE_UNUSED = &recog_data.operand[0];
  rtx x2, x3, x4;
  int res ATTRIBUTE_UNUSED;
  x2 = XEXP (x1, 0);
  operands[0] = x2;
  x3 = XEXP (x1, 1);
  operands[1] = x3;
  switch (GET_MODE (operands[0]))
    {

...

    default:
      break;  //★★V64SImodeはいずれのcaseにも該当しないのでここにくる
    }

...

  if (pnum_clobbers == NULL  //★★この条件に引っかかる
      || GET_CODE (x2) != MEM)
    return -1;  //★★ここにくる

...

なぜかrecog() 関数はデバッグ情報がおかしくて、gdbのnextコマンドが正常に動きません。非常にデバッグしづらいです。gdbで追うときはbuild_gcc/insn-recog.c内の #lineディレクティブを全て削除するとデバッグしやすいです。

エラーを解消するにはrecog_2のswitch-caseに変化を及ぼす方法を知る必要があります。しかしそんなものわかる訳ありません。仕方ないので周辺のコードを眺めます。

エラーが起きている箇所の周辺

static int
recog_2 (rtx x1 ATTRIBUTE_UNUSED,
	rtx_insn *insn ATTRIBUTE_UNUSED,
	int *pnum_clobbers ATTRIBUTE_UNUSED)
{

...

  switch (GET_MODE (operands[0]))
    {
    case E_DImode:
      if (nonimmediate_operand (operands[0], E_DImode)
          && move_operand (operands[1], E_DImode))
        {
          if (
#line 1340 "./gcc/gcc/config/riscv/riscv.md"    //★★この辺りにヒントがあるのでは??
(!TARGET_64BIT
   && (register_operand (operands[0], DImode)
       || reg_or_0_operand (operands[1], DImode))))
            return 135; /* *movdi_32bit */
          if (
#line 1350 "./gcc/gcc/config/riscv/riscv.md"
(TARGET_64BIT
   && (register_operand (operands[0], DImode)
       || reg_or_0_operand (operands[1], DImode))))
            return 136; /* *movdi_64bit */
        }
      break;

ぐちゃぐちゃのif文の中に #lineが差し込まれています。コードの一部をriscv.mdから持ってきているようです。

riscv.mdの該当部分

;; gcc/config/riscv/riscv.md

(define_insn "*movdi_32bit"
  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m,  *f,*f,*r,*f,*m")
	(match_operand:DI 1 "move_operand"         " r,i,m,r,*J*r,*m,*f,*f,*f"))]

★★↓このコードがrecog_2にコピーされている

  "!TARGET_64BIT
   && (register_operand (operands[0], DImode)
       || reg_or_0_operand (operands[1], DImode))"

★★↑

  { return riscv_output_move (operands[0], operands[1]); }
  [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore")
   (set_attr "mode" "DI")])

おそらくdefine_insnを定義すれば、recog_2() も変わるでしょう。近しいものをコピーして作ります。

riscv.mdにdefine_insnを追加

;; gcc/config/riscv/riscv.md

(define_attr "vecmode" "unknown,V64SI"
  (const_string "unknown"))

(define_insn "*movv64si_internal"
  [(set (match_operand:V64SI 0 "nonimmediate_operand" "=v,v,m")
	(match_operand:V64SI 1 "move_operand"         " v,m,v"))]    //★★RTL template
  "(register_operand (operands[0], V64SImode)
    || reg_or_0_operand (operands[1], V64SImode))"    //★★condition
  { return riscv_output_move (operands[0], operands[1]); }    //★★output template
  [(set_attr "move_type" "move,load,store")
   (set_attr "vecmode" "V64SI")])    //★★insn attributes

とりあえずRTL template, condition, insn attributesに出現するmachine modeだけ変更しました。これが合っているのかわかりませんが、ダメなら後で直しましょう。

define_insnを追加後のrecog

static int
recog_2 (rtx x1 ATTRIBUTE_UNUSED,
	rtx_insn *insn ATTRIBUTE_UNUSED,
	int *pnum_clobbers ATTRIBUTE_UNUSED)
{

...

  switch (GET_MODE (operands[0]))
    {
    case E_V64SImode:
      if (nonimmediate_operand (operands[0], E_V64SImode)
          && move_operand (operands[1], E_V64SImode)
          && 
#line 1320 "./gcc/gcc/config/riscv/riscv.md"
((register_operand (operands[0], V64SImode)
    || reg_or_0_operand (operands[1], V64SImode))))
        return 134; /* *movv64si_internal */    //★★ここにくるようになった
      break;

再びrecog_2() を追いかけてみると、先程はなかったcaseが増えており、-1ではない値が返されるようになりました。

define_insnを追加後のエラー
during RTL pass: final
dump file: b.c.314r.final

b.c: In function '_start':
b.c:25:1: internal compiler error: in riscv_output_move, at config/riscv/riscv.c:2000
   25 | }
      | ^

0x1ae3d41 riscv_output_move(rtx_def*, rtx_def*)

今度こそうまく行くかと思いきや、また別のエラーが発生しました。道のりは長そうです。

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

コメント一覧

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



link もっと前
2020年5月25日 >>> 2020年5月25日
link もっと後

管理用メニュー

link 記事を新規作成

<2020>
<<<05>>>
-----12
3456789
10111213141516
17181920212223
24252627282930
31------

最近のコメント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