[llvm-dev] How to define subreg relationship in td file?

林政宗 via llvm-dev llvm-dev at lists.llvm.org
Fri Aug 13 09:30:34 PDT 2021


Thanks!  The problem has been solved.
Here comes another problem related to the previous one.
We know that ARM use struct to represent the relationship between SuperReg and SubReg in C level.
for example:
------------------------------------------------------------------------------
// this is file a.c

1 #include "arm_neon.h"

2 void test (float32_t *p1, float32_t *p2, float32_t *p3) {

3 float32x4x2_t a = vld1q_f32_x2(p1);

4 float32x4x2_t b = vld1q_f32_x2(p2);

5 float32x4_t c = vaddq_f32(a.val[0], b.val[1]);

6 vst1q_f32(p3, c);

7 }

-----------------------------------------------------------------------------
compiling the c source by "clang --target=aarch64 -O3 -S a.c" will generate a.s like below:
--------------------------------------------------------------------------------------------------------------------------------------
  1    .text
 2    .file   "b.c"
 3    .globl  test                    // -- Begin function test
 4    .p2align    2
 5    .type   test, at function
 6test:                                   // @test
 7.Ltest$local:
 8// %bb.0:                               // %entry
 9     ld1 { v0.4s, v1.4s }, [x0]
10    ld1 { v2.4s, v3.4s }, [x1]
11    fadd    v0.4s, v0.4s, v3.4s
12    str q0, [x2]
13    ret
14.Lfunc_end0:
15    .size   test, .Lfunc_end0-test
16                                        // -- End function
17    .ident  "clang version 11.0.0 "
18    .section    ".note.GNU-stack","", at progbits
19    .addrsig
----------------------------------------------------------------------------------------------------------------------------------------------
the definition of float32x4x2_t is:
------------------------------------------------------------------------

157 typedef struct float32x4x2_t {

158   float32x4_t val[2];

159 } float32x4x2_t;
-------------------------------------------------------------------------
vld1q_f32_x2 will load QQ which consists of two subreg (Q). So a.val[0] refers to the first SubReg Q and b.val[1] refers to the second SubReg Q.


I need to implement something like this. A load builtin would load an QVR, which is represented by struct. like this
--------------------------------------------------------------------------------------------
typedef struct dvr_t {
   float32x4_t val[2];
} dvr_t;
typedef struct qvr_t {
  dvr_t val[2];
} qvr_t;
--------------------------------------------------------------------------------------
and we can use qvr_t.val[0] to refer to the first SubReg DVR, qvr_t.val[1] to refer to the second SubReg DVR.
And also we can use qvr_t.val[0].val[0] to refer to the first VR SubReg, qvr_t.val[1].val[1] to refer to the fourth VR SubReg, and so on.
What is different is that ARM usage has one level inclusion in struct but the above usage has two level inclusion in struct.
I have been trying to find a solution for a few days. The key point is that I need load data into some QVR, and get the SubReg(VR or DVR) of the QVR loaded directly as operand for later operation.
Is there any soloution or idea for the problem?  


Many Thanks!






At 2021-08-10 22:51:37, "Diogo Sampaio" <dsampaio at kalray.eu> wrote:

We also had quad registers defined in function of 4 single registers, then we couldn't extract paired register from it easily.
So we changed and made them defined in function of paired registers. We also named the sub indices as to know what size of sub-register we want. Is something alike this:
 
// Defining sub-register indexes
def sub_p0 : SubRegIndex<128,  0>;
def sub_p1 : SubRegIndex<128,128>;
 
def sub_s0 : SubRegIndex<64,  0>;
def sub_s1 : SubRegIndex<64, 64>;
def sub_s2 : ComposedSubRegIndex<sub_p1, sub_s0>;
def sub_s3 : ComposedSubRegIndex<sub_p1, sub_s1>;
 
// Composed register classes
// Paired Registers
class PGR<string n, list<Register> subregs>
      : : RegisterWithSubRegs<n, subregs> {
  let SubRegIndices = [sub_s0, sub_s1];
}
 
// Quad Register
class QGR<string n, list<Register> subregs>
      : RegisterWithSubRegs<n, subregs> {
  let SubRegIndices = [sub_p0, sub_p1];
}
 
// Defining registers
def P0  : PGR< 0,   "$r0r1", [ R0,  R1]>;
def P2  : PGR< 2,   "$r2r3", [ R2,  R3]>;
....
 
def Q0  : QGR< 0,     "$r0r1r2r3", [ P0,  P2]>;
 
//
Now can use any of those 6 sub-index to reference 2 sub-pair registers or any of the 4 single registers.
 
 
Diogo Sampaio
Senior Compiler Engineer • Kalray
Phone:
dsampaio at kalrayinc.com • www.kalrayinc.com


|
|
Intelligent Data Processing
From Cloud to Edge
|



From: Fraser <llvm-dev at lists.llvm.org>
To: jackie <jackie_linzz at 126.com>
Cc: llvm-dev <llvm-dev at lists.llvm.org>
Date: Tuesday, 10 August 2021 2:15 PM CEST
Subject: Re: [llvm-dev] How to define subreg relationship in td file?

Hi,

You can (I'm hesitant to say you "must") model this with extra "fake"
(in some sense) physical registers which represent the paired and
quadrupled registers. This will also tell the register allocator that
allocating VRPair0 will clobber both VR0 *and VR1*, for example.

So you have half the number of VRPair registers which each have two VRs
as subregisters, then half that again of VRQuad registers which have
two VRPairs as subregisters. The subregister properties will apply
transitively so your VRQuads will have four VR subregisters using
composed subregister indices which LLVM will either automatically infer
or you can specify yourself with ComposedSubRegIndex.

Take a look at RISCVRegisterInfo.td for inspriation. Each vector V
register is paired into VM2 which are in turn paried into VM4s and then
into VM8s.

Cheers,
Fraser

On Tue, 2021-08-10 at 19:54 +0800, 林政宗 via llvm-dev wrote:
> Hi, there.
>
> I met a problem about defining SubReg relationship when defining
> Registers in td file.
> The target has a kind of vector register named VR which is of type
> v4f32. 
> 2 VR makes 1 DVR. 4 VR makes 1 QVR.
> I have some code like this:
> -------------------------------------------------------------------
> -----------------------------------
> def VRPairs : RegisterTuples<[vsub_0, vsub_1],
>                              [(decimate (rotl VRegs, 0), 2),
>                               (decimate (rotl VRegs, 1), 2)],
>                              []>;
>
> def VRQuads : RegisterTuples<[vsub_0, vsub_1, vsub_2, vsub_3],
>                              [(decimate (rotl VRegs, 0), 4),
>                               (decimate (rotl VRegs, 1), 4),
>                               (decimate (rotl VRegs, 2), 4),
>                               (decimate (rotl VRegs, 3), 4)],
>                              []>;
> def DVRRegs : RegisterClass<"xxx", [v8f32], 256, (add VRPairs)>;
> 
> def QVRRegs : RegisterClass<"xxx", [v16f32], 512, (add VRQuads)>;
> -------------------------------------------------------------------
> -----------------------------------
> But also, 2 DVR makes 1 QVR. QVR has two subregs, each of which is 1
> DVR.
> How can I describe the SubReg relationship between DVR and QVR?
> Could anyone help? Thanks in advance!
>
>
> BR,
> Jerry
>
>
>
> 
>
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
>
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>

_______________________________________________
LLVM Developers mailing list
llvm-dev at lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev


 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20210814/b88dd222/attachment.html>


More information about the llvm-dev mailing list