[LLVMdev] How to define complicated instruction in TableGen (Direct3D shader instruction)
Chris Lattner
sabre at nondot.org
Tue Aug 2 15:11:24 PDT 2005
On Fri, 29 Jul 2005, Morten Ofstad wrote:
> Actually the problems that Tzu-Chien Chiu are encountering are similar to
> what should be done for generating SSE code in the X86 backend and also other
> SIMD instruction sets. I think LLVM neeeds to add instructions for permuting
> components, extracting and injecting elements in packed types. If the
> architecture has instructions which can do permutations for each instruction
> (for example 'add' with permutation) it should be the role of the pattern
> instruction selector to recognise the shuffle+add combination and emit a
> single instruction.
Agreed 100%.
-Chris
> Tzu-Chien Chiu wrote:
>> Each register is a 4-component (namely, r, g, b, a) vector register. They
>> are actually defined as llvm packed [4xfloat].
>>
>> The instruction:
>>
>> add_sat r0.a, r1_bias.xxyy, r3_x2.zzzz
>>
>> Explaination:
>>
>> '.a' is a writemask. only the specified component will be update
>>
>> '.xxyy' and '.zzzz' are swizzle masks, specify the component
>> permutation, simliar to the Intel SSE permutation instruction SHUFPD
>>
>> '_bias' and '_x2' are modifiers. they modify the value of source
>> operands and send the modified values to the adder. '_bias' = source -
>> 0.5, '_x2' = source * 2
>>
>> '_sat' is an instruction modifier. when specified, it saturates (or
>> clamps) the instruction result to the range [0, 1] before writing to
>> the destination register.
>>
>> All of these 'writemask', 'swizzle', 'source modifier', and
>> 'instruction modifiers' are optionally specified.
>>
>> How should I define the instruction in a TableGen .td file?
>>
>> I have two alternatives:
>>
>> 1. class WriteMask : Operand<i8> {}
>> def WM : WriteMask;
>>
>> class Swizzle : Operand<8> {}
>> def SW: Swizzle;
>>
>> class InstructionModifier : Operand<i8> {}
>> def IM: InstructionModifier ;
>> class SourceModifier : Operand<i8> {}
>> def SM: SourceModifier ;
>>
>> def ADD<0x01, (ops GPR:$dest, ops WM:$wm, IM:$im, GPR:$src0,
>> SW:$sw0, SM:$sm0,
>> GPR:$src1, SW:$sw1 SM:$sm1 ), ... >
>>
>> 2. add llvm intrinsics:
>>
>> ; add_sat r0.a, r1_bias.xxyy, r3_x2.zzzz
>> r1_1 = llvm.bias( r1_0 )
>> r1_2 = llvm.shuffle( xxyy )
>> r3_1 = llvm.x2( r3_0 )
>> r3_2 = llvm.shuffle( zzzz )
>> r0_0 = add r1_2, r3_2
>> r0_1 = llvm.sature( r0_0 )
>> r0_2 = llvm.select( a )
>>
>> but it makes the implementing the instruction selector very diffifult.
>> in this example, llvm.select() and llvm.sature() are encountered frist
>> (bootm-up), but they must be 'remembered' and the instruction cannot
>> be generated (BuildMI) until the opcode is known.
>>
>> Which one should I do?
>>
>
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
-Chris
--
http://nondot.org/sabre/
http://llvm.org/
More information about the llvm-dev
mailing list