Type inference on registers with can contain multiple types

My architecture has an FPU, but uses integer registers to store
floating-point values. So each register can store either an int or an
IEEE float. I define a register class like this:

def GR32 : RegisterClass<"MyArch", [i32, f32], 32,
  (sequence "R%u", 0, 32)>;

So far so good. However, when I write a rule to store a register:

def STORE32r : S32<
  (outs), (ins GR32:$rS, GR32:$rD),
  "st {$rS, ($rD)}",
  [(store GR32:$rS, (iPTR GR32:$rD))]>;

...then I get the dreaded 'cannot infer all types in pattern' error.
This is presumably because tablegen can't tell whether the input is an
i32 or a f32.

What's the best thing to do here? Explicitly annotating the input type
works, of course, but then I need two rules. Use a multipattern? Or is
there a way to tell tablegen that the input is allowed to be either?

From: "David Given" <dg@cowlark.com>
To: "LLVM Dev" <llvmdev@cs.uiuc.edu>
Sent: Wednesday, March 19, 2014 6:18:53 PM
Subject: [LLVMdev] Type inference on registers with can contain multiple types

My architecture has an FPU, but uses integer registers to store
floating-point values. So each register can store either an int or an
IEEE float. I define a register class like this:

def GR32 : RegisterClass<"MyArch", [i32, f32], 32,
  (sequence "R%u", 0, 32)>;

So far so good. However, when I write a rule to store a register:

def STORE32r : S32<
  (outs), (ins GR32:$rS, GR32:$rD),
  "st {$rS, ($rD)}",
  [(store GR32:$rS, (iPTR GR32:$rD))]>;

...then I get the dreaded 'cannot infer all types in pattern' error.
This is presumably because tablegen can't tell whether the input is
an
i32 or a f32.

What's the best thing to do here? Explicitly annotating the input
type
works, of course, but then I need two rules. Use a multipattern? Or
is
there a way to tell tablegen that the input is allowed to be either?

You'll need to write the pattern with a single type. In your *ISelLowering.cpp, can you mark the store of the other type as Promote, and then promote it to the type for which there is a pattern? As I recall, the PowerPC backend does this for its vector types.

-Hal

> From: "David Given" <dg@cowlark.com>
> To: "LLVM Dev" <llvmdev@cs.uiuc.edu>
> Sent: Wednesday, March 19, 2014 6:18:53 PM
> Subject: [LLVMdev] Type inference on registers with can contain multiple types
>
> My architecture has an FPU, but uses integer registers to store
> floating-point values. So each register can store either an int or an
> IEEE float. I define a register class like this:
>
> def GR32 : RegisterClass<"MyArch", [i32, f32], 32,
> (sequence "R%u", 0, 32)>;
>
> So far so good. However, when I write a rule to store a register:
>
> def STORE32r : S32<
> (outs), (ins GR32:$rS, GR32:$rD),
> "st {$rS, ($rD)}",
> [(store GR32:$rS, (iPTR GR32:$rD))]>;
>
> ...then I get the dreaded 'cannot infer all types in pattern' error.
> This is presumably because tablegen can't tell whether the input is
> an
> i32 or a f32.
>
> What's the best thing to do here? Explicitly annotating the input
> type
> works, of course, but then I need two rules. Use a multipattern? Or
> is
> there a way to tell tablegen that the input is allowed to be either?

You'll need to write the pattern with a single type. In your *ISelLowering.cpp, can you mark the store of the other type as Promote, and then promote it to the type for which there is a pattern? As I recall, the PowerPC backend does this for its vector types.

This is what R600 does as well. All floating-point loads/stores are
promoted to integer and then we just have integer load/store patterns.

-Tom