Tzu-Chien Chiu
2005-Jul-23 01:36 UTC
[LLVMdev] How to partition registers into different RegisterClass?
2005/7/23, Chris Lattner <sabre at nondot.org>:> > What does a 'read only' register mean? Is it a constant (e.g. returns > 1.0)? Otherwise, how can it be a useful value?Yes, it's a constant register. Because the instruction cannot contain an immediate value, a constant value may be stored in a constant register, and it's defined _before_ the program starts by API. For example: SetConstantValue( 5, Vector4( 1, 2, 3, 4 ); // C5 = <1,2,3,4> HANDLE handle = LoadCodeFromFile( filename ); SetCode( handle ); // C5 is referenced here Execute(); -- Tzu-Chien Chiu, 3D Graphics Hardware Enginner, <URL:http://www.csie.nctu.edu.tw/~jwchiu>
Chris Lattner
2005-Jul-23 16:26 UTC
[LLVMdev] How to partition registers into different RegisterClass?
On Sat, 23 Jul 2005, Tzu-Chien Chiu wrote:> 2005/7/23, Chris Lattner <sabre at nondot.org>: >> What does a 'read only' register mean? Is it a constant (e.g. returns >> 1.0)? Otherwise, how can it be a useful value? > > Yes, it's a constant register. > > Because the instruction cannot contain an immediate value, a constant > value may be stored in a constant register, and it's defined _before_ > the program starts by API. For example: > > SetConstantValue( 5, Vector4( 1, 2, 3, 4 ); // C5 = <1,2,3,4> > HANDLE handle = LoadCodeFromFile( filename ); > SetCode( handle ); // C5 is referenced here > Execute();Ah, ok. In that case, you want to put all of the registers in one register file, and not make the constant register allocatable (e.g. see X86RegisterInfo.td, and note how the register classes include EBP and ESP, but do not register allocate them (through the definition of allocation_order_end()). -Chris -- http://nondot.org/sabre/ http://llvm.org/
Tzu-Chien Chiu
2005-Jul-25 09:38 UTC
[LLVMdev] How to partition registers into different RegisterClass?
Thanks, I think it can solve my problem. But please allow me to explain the hardware in detail. Hope there is more elegant way to solve it. The hardware is a "stream processor". That is, It processes samples one by one. Each sample is associated with several 128-bit four-element vector registers, namely: * input registers - the attributes of the sample, the values of the registers are different and initialized for each sample before execution. READ-ONLY (can only be declared once by 'dcl' instruction). * constant registers - sample-invariant. READ-ONLY (can only be defined once by 'def' instruction). All samples shares the same set of constant register values. * general purpose registers - values are not initialized before the execution and destroyed after execution. They can be read and written. * output registers - WRITE-ONLY. Sample program converted to pseudo-LLVM assembly (SSA): %Vec4 = type < 4 x float> // declare input registers and // define constant register values %v1 = dcl %Vec4 xyz %v2 = dcl %Vec4 color %c1 = def %Vec4 <1,2,3,4> // v1, v2, c1 are not allowed to be destination register // of any instruction hereafter. %r1 = add %Vec4 v1, c1 %r2 = mul %Vec4 v1, c2 %o1 = mul %Vec4 r2, v2 // write the output register 'o1' I planed to partition the register into different RegisterClass: input, output, general purpose, constant, etc. def GeneralPurposeRC : RegisterClass<packed, 128, [R0, R1]>; def InputRC : RegisterClass<packed, 128, [V0, V1]>; def ConstantRC : RegisterClass<packed, 128, [C0, C1]>; def ADDgg : BinaryInst<0x51, ( ops GeneralPurposeRC :$dest, ope GeneralPurposeRC :$src), "add $dest, $src">; def ADDgi : BinaryInst<0x52, ( ops GeneralPurposeRC :$dest, ope InputRC :$src), "add $dest, $src">; def ADDgc : BinaryInst<0x52, ( ops GeneralPurposeRC :$dest, ope ConstantRC :$src), "add $dest, $src">; The problem is: SDOperand alwasy return the 'type' of the value (in this case, 'packed', the first argument of RegisterClass<>), but not the 'RegisterClass'. With two 'packed' operands, the instruction selector doesn't know whether a ADDgg, ADDgi, or an ADDgc should be generated (BuildMI() function). The same problem exists when there are two types of costant registers, floating point and integer, and each is declared 'packed' ([4xfloat] and [4xint]). The instruction selector doesn't know which instruction it should produce because the newly defined MVT type 'packed' is always used for all operands (registers), even if it's acutally a [4xfloat] or [4xint]. 2005/7/24, Chris Lattner <sabre at nondot.org>:> On Sat, 23 Jul 2005, Tzu-Chien Chiu wrote: > > 2005/7/23, Chris Lattner <sabre at nondot.org>: > >> What does a 'read only' register mean? Is it a constant (e.g. returns > >> 1.0)? Otherwise, how can it be a useful value? > > > > Yes, it's a constant register. > > > > Because the instruction cannot contain an immediate value, a constant > > value may be stored in a constant register, and it's defined _before_ > > the program starts by API. For example: > > > > SetConstantValue( 5, Vector4( 1, 2, 3, 4 ); // C5 = <1,2,3,4> > > HANDLE handle = LoadCodeFromFile( filename ); > > SetCode( handle ); // C5 is referenced here > > Execute(); > > Ah, ok. In that case, you want to put all of the registers in one register > file, and not make the constant register allocatable (e.g. see > X86RegisterInfo.td, and note how the register classes include EBP and ESP, > but do not register allocate them (through the definition of > allocation_order_end()). > > -Chris > > -- > http://nondot.org/sabre/ > http://llvm.org/ >-- Tzu-Chien Chiu, 3D Graphics Hardware Enginner, <URL:http://www.csie.nctu.edu.tw/~jwchiu>
Tzu-Chien Chiu
2005-Jul-25 09:56 UTC
[LLVMdev] How to partition registers into different RegisterClass?
2005/7/24, Chris Lattner <sabre at nondot.org>:> Ah, ok. In that case, you want to put all of the registers in one register > file, and not make the constant register allocatable (e.g. see > X86RegisterInfo.td, and note how the register classes include EBP and ESP, > but do not register allocate them (through the definition of > allocation_order_end()). > > -ChrisHope I understand you correctly: def C0 : ConstFpReg<0, "c0">; ... def C200 : ConstFpReg<199, "c200">; def I0 : ConstIntReg<0, "i0">; ... def I100 : ConstIntReg<100, "i100">; def R0 : TempReg<0, "r0">; def R32 : TempReg<31, "r32">; def V0 : InputReg<0, "v0">; .. def V10 : InputReg<9, "v10">; def O0 : OutputReg<0, "o0">; .. def O4 : OutputReg<4, "o4">; def FloatingPointRC : RegisterClass<packed, 128, [R0, R1, R2, ..., R32, C0, C1, ..., C200, V0, ..., V10, O1, O2, O3, O4]> { let Methods = [{ iterator allocation_order_end(MachineFunction &MF) const { return end()-(4+10+200); // only TempReg can be allocated }]; } def IntegerRC : RegisterClass<packed, 128, [I0, I1, ..., I100]>; And linearly assigning the read-only registers for each definition of them? -- Tzu-Chien Chiu, 3D Graphics Hardware Enginner, <URL:http://www.csie.nctu.edu.tw/~jwchiu>
Maybe Matching Threads
- [LLVMdev] How to partition registers into different RegisterClass?
- [LLVMdev] How to partition registers into different RegisterClass?
- PXE stack access via com32
- Sending UDP packets from comboot
- [LLVMdev] [llvm] r210424 - Revert "Do materialize for floating point"