Alex Susu via llvm-dev
2016-Jun-13 18:44 UTC
[llvm-dev] LLVM IR intrinsics placeholder for strings [was Re: Back end with special loop instructions (using LLVM IR intrinsics)]
Hello.
I come back to this thread. But I want to ask a slightly different
question.
Is there a way to have LLVM IR language intrinsics that are given at
construction
time a string that is written at assembly generation time as it is? (so,
basically having
placeholders of strings in LLVM that remain untouched until the end, including
code
generation time.)
More exactly, I would like to give something LIKE this in a middle-tier
pass (I
haven't tried this code in LLVM):
Value *instrinsicFunc = Intrinsic::getDeclaration(M,
Intrinsic::my_intrinsic);
myIRBuilder.CreateCall(repeatFunc,
"string_that_llc_codegen_should_output_as_assembly");
So my intrinsic would be accepting a general string which will be used at
codegen to
be output. I guess I would have to define it like this in a .td file:
def int_my_intrinsic : Intrinsic<[], [string], []>;
The other option that can work but is more complex without any benefit is
to define
several intrinsics in the .td files, one for EACH possible string:
// To put in the Intrinsics_....td file:
def int_my_intrinsic1 : Intrinsic<[], [], []>;
...
def int_my_intrinsicN : Intrinsic<[], [], []>;
// To put in the InstrInfo.td file something like:
def STR_PLACEHOLDER1 : ImmediateInstruction< 0b111111,
(outs),
(ins),
"string_that_llc_codegen_should_output_as_assembly1",
[(int_my_intrinsic1)] >;
def STR_PLACEHOLDER2 : ImmediateInstruction< 0b111110,
(outs),
(ins),
"string_that_llc_codegen_should_output_as_assembly2",
[(int_my_intrinsic2)] >;
Best regards,
Alex
On 6/5/2016 5:21 PM, Alex Susu wrote:> Hello.
> Hal, the source file you mention (lib/Target/PowerPC/PPCCTRLoops.cpp)
makes use of
> LLVM IR intrinsics, in this case defined at
> [LLVM_repo]/llvm/include/llvm/IR/IntrinsicsPowerPC.td, such as:
> // Intrinsics used to generate ctr-based loops. These should
only be
> // generated by the PowerPC backend!
> def int_ppc_mtctr : Intrinsic<[], [llvm_anyint_ty], []>;
> def int_ppc_is_decremented_ctr_nonzero : Intrinsic<[llvm_i1_ty],
[], []>;
>
> And these intrinsics are instantiated in the LLVM program, for example
with the
> following code in PPCCTRLoops.cpp:
> IRBuilder<> CountBuilder(Preheader->getTerminator());
> Module *M = Preheader->getParent()->getParent();
> Value *MTCTRFunc = Intrinsic::getDeclaration(M,
Intrinsic::ppc_mtctr,CountType);
> CountBuilder.CreateCall(MTCTRFunc, ECValue);
>
> I have defined also some intrinsics for my loop instructions in my
file
> Intrinsics_Connex.td: 1 intrinsic for REPEAT_X_TIMES and 1 for END_REPEAT.
> /* following Intrinsics.td:
> class Intrinsic<list<LLVMType> ret_types,
> list<LLVMType> param_types = [],
> list<IntrinsicProperty> properties = [],
> string name = "">
> */
> def int_connex_repeat_x_times : Intrinsic<[], [], []>;
> def int_connex_end_repeat : Intrinsic<[llvm_i1_ty], [], []>;
> and added C++ code doing CreateCall() like the one above.
>
> I'm looking now at http://llvm.org/docs/ExtendingLLVM.html on how
to specify the
> instruction selection of this intrinsic. They write there:
> "Once the intrinsic has been added to the system, you must add
code generator
> support for it. Generally you must do the following steps:
> Add support to the .td file for the target(s) of your choice in
lib/Target/*/*.td.
> This is usually a matter of adding a pattern to the .td file that
matches the
> intrinsic, though it may obviously require adding the instructions you want
to generate as
> well. There are lots of examples in the PowerPC and X86 backend to
follow."
>
> Then in my pass I create a call to the respective intrinsic:
> /* See
http://llvm.org/docs/doxygen/html/classllvm_1_1TargetIntrinsicInfo.html :
> "Create or insert an LLVM Function declaration for an intrinsic, and
return it."
> * This creates a line in the LLVM program like: declare void
> @llvm.connex.repeat.x.times() #2 .
> * This line is required, otherwise llc will complain:
> * <<error: use of undefined value
'@llvm.connex.repeat.x.times'
> call void @llvm.connex.repeat.x.times()>>
> */
> Value *repeatFunc = Intrinsic::getDeclaration(M,
>
Intrinsic::connex_repeat_x_times);
>
> // See http://llvm.org/docs/doxygen/html/classllvm_1_1IRBuilder.html
> aB.CreateCall(repeatFunc); //, ECValue);
>
>
> Then, in the back end, in InstrInfo.td I write:
> let hasSideEffects = 1, isCodeGenOnly = 1 in {
> //let Pattern = [(int_connex_repeat_x_times)] in
> def REPEAT_X_TIMES : ImmediateInstruction< 0b111111,
> (outs),
> (ins),
>
"REPEAT_X_TIMES(1001)",
> [(int_connex_repeat_x_times)]
>;
> }
>
>
> Then, when I run opt and llc I obtain the expected behavior.
>
> Thank you,
> Alex
>
>
David Chisnall via llvm-dev
2016-Jun-14 09:12 UTC
[llvm-dev] LLVM IR intrinsics placeholder for strings [was Re: Back end with special loop instructions (using LLVM IR intrinsics)]
Hi, Is there a reason that you can’t use inline assembly for this? David> On 13 Jun 2016, at 19:44, Alex Susu via llvm-dev <llvm-dev at lists.llvm.org> wrote: > > Hello. > I come back to this thread. But I want to ask a slightly different question. > Is there a way to have LLVM IR language intrinsics that are given at construction time a string that is written at assembly generation time as it is? (so, basically having placeholders of strings in LLVM that remain untouched until the end, including code generation time.) > > More exactly, I would like to give something LIKE this in a middle-tier pass (I haven't tried this code in LLVM): > Value *instrinsicFunc = Intrinsic::getDeclaration(M, > Intrinsic::my_intrinsic); > myIRBuilder.CreateCall(repeatFunc, > "string_that_llc_codegen_should_output_as_assembly"); > So my intrinsic would be accepting a general string which will be used at codegen to be output. I guess I would have to define it like this in a .td file: > def int_my_intrinsic : Intrinsic<[], [string], []>; > > > The other option that can work but is more complex without any benefit is to define several intrinsics in the .td files, one for EACH possible string: > // To put in the Intrinsics_....td file: > def int_my_intrinsic1 : Intrinsic<[], [], []>; > ... > def int_my_intrinsicN : Intrinsic<[], [], []>; > // To put in the InstrInfo.td file something like: > def STR_PLACEHOLDER1 : ImmediateInstruction< 0b111111, > (outs), > (ins), > "string_that_llc_codegen_should_output_as_assembly1", > [(int_my_intrinsic1)] >; > def STR_PLACEHOLDER2 : ImmediateInstruction< 0b111110, > (outs), > (ins), > "string_that_llc_codegen_should_output_as_assembly2", > [(int_my_intrinsic2)] >; > > > Best regards, > Alex > > On 6/5/2016 5:21 PM, Alex Susu wrote: >> Hello. >> Hal, the source file you mention (lib/Target/PowerPC/PPCCTRLoops.cpp) makes use of >> LLVM IR intrinsics, in this case defined at >> [LLVM_repo]/llvm/include/llvm/IR/IntrinsicsPowerPC.td, such as: >> // Intrinsics used to generate ctr-based loops. These should only be >> // generated by the PowerPC backend! >> def int_ppc_mtctr : Intrinsic<[], [llvm_anyint_ty], []>; >> def int_ppc_is_decremented_ctr_nonzero : Intrinsic<[llvm_i1_ty], [], []>; >> >> And these intrinsics are instantiated in the LLVM program, for example with the >> following code in PPCCTRLoops.cpp: >> IRBuilder<> CountBuilder(Preheader->getTerminator()); >> Module *M = Preheader->getParent()->getParent(); >> Value *MTCTRFunc = Intrinsic::getDeclaration(M, Intrinsic::ppc_mtctr,CountType); >> CountBuilder.CreateCall(MTCTRFunc, ECValue); >> >> I have defined also some intrinsics for my loop instructions in my file >> Intrinsics_Connex.td: 1 intrinsic for REPEAT_X_TIMES and 1 for END_REPEAT. >> /* following Intrinsics.td: >> class Intrinsic<list<LLVMType> ret_types, >> list<LLVMType> param_types = [], >> list<IntrinsicProperty> properties = [], >> string name = ""> >> */ >> def int_connex_repeat_x_times : Intrinsic<[], [], []>; >> def int_connex_end_repeat : Intrinsic<[llvm_i1_ty], [], []>; >> and added C++ code doing CreateCall() like the one above. >> >> I'm looking now at http://llvm.org/docs/ExtendingLLVM.html on how to specify the >> instruction selection of this intrinsic. They write there: >> "Once the intrinsic has been added to the system, you must add code generator >> support for it. Generally you must do the following steps: >> Add support to the .td file for the target(s) of your choice in lib/Target/*/*.td. >> This is usually a matter of adding a pattern to the .td file that matches the >> intrinsic, though it may obviously require adding the instructions you want to generate as >> well. There are lots of examples in the PowerPC and X86 backend to follow." >> >> Then in my pass I create a call to the respective intrinsic: >> /* See http://llvm.org/docs/doxygen/html/classllvm_1_1TargetIntrinsicInfo.html : >> "Create or insert an LLVM Function declaration for an intrinsic, and return it." >> * This creates a line in the LLVM program like: declare void >> @llvm.connex.repeat.x.times() #2 . >> * This line is required, otherwise llc will complain: >> * <<error: use of undefined value '@llvm.connex.repeat.x.times' >> call void @llvm.connex.repeat.x.times()>> >> */ >> Value *repeatFunc = Intrinsic::getDeclaration(M, >> Intrinsic::connex_repeat_x_times); >> >> // See http://llvm.org/docs/doxygen/html/classllvm_1_1IRBuilder.html >> aB.CreateCall(repeatFunc); //, ECValue); >> >> >> Then, in the back end, in InstrInfo.td I write: >> let hasSideEffects = 1, isCodeGenOnly = 1 in { >> //let Pattern = [(int_connex_repeat_x_times)] in >> def REPEAT_X_TIMES : ImmediateInstruction< 0b111111, >> (outs), >> (ins), >> "REPEAT_X_TIMES(1001)", >> [(int_connex_repeat_x_times)] >; >> } >> >> >> Then, when I run opt and llc I obtain the expected behavior. >> >> Thank you, >> Alex >> >> > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev-------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 3719 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160614/6bf6fb9d/attachment-0001.bin>
Alex Susu via llvm-dev
2016-Jun-14 23:47 UTC
[llvm-dev] LLVM IR intrinsics placeholder for strings (inline assembly)
Hello.
David, thank you for pointing out inline assembly expressions.
I found: http://clang.llvm.org/compatibility.html#inline-asm and
http://llvm.org/docs/LangRef.html#inline-assembler-expressions .
So I added in my LLVM program a line like
call void asm sideeffect "MY OWN STRING",
"~{dirflag},~{fpsr},~{flags}"() #1
and compiled it with llc and it worked as expected.
More importantly, to programmatically insert assembly expressions in an
LLVM pass we
need to give something like:
// Inspired from http://reviews.llvm.org/D15399?id=42353 (see also
http://stackoverflow.com/questions/28787799/insert-inline-assembly-expressions-using-llvm-pass)
std::vector<llvm::Value*> Args;
Type *ResultType;
ResultType = Type::getVoidTy(getGlobalContext());
// See http://llvm.org/docs/doxygen/html/classllvm_1_1FunctionType.html
FunctionType *fTy = FunctionType::get(
/* Result */ ResultType,
/* NO Params */
false);
StringRef asmString = "test_ASM_inline_string!";
bool hasSideEffect = true;
InlineAsm::AsmDialect asmDialect = InlineAsm::AD_ATT;
/*
* Note: Extreme care with the constraints.
* Info about them at
http://llvm.org/docs/LangRef.html#inline-asm-constraint-string
* (and https://doc.rust-lang.org/book/inline-assembly.html)
*
* When using e.g.:
* std::string constraints = "*";
* I got this error:
* Assertion `Verify(getFunctionType(), constraints) &&
"Function type not
legal for constraints!"' failed.
*/
std::string constraints = "";
InlineAsm *iaExpr = InlineAsm::get(fTy, asmString, constraints,
hasSideEffect,
/* IsAlignStack */ false, asmDialect);
CallInst *Result = Builder.CreateCall(iaExpr, Args);
Result->addAttribute(AttributeSet::FunctionIndex,
Attribute::NoUnwind);
Best regards,
Alex
On 6/14/2016 12:12 PM, David Chisnall wrote:> Hi,
>
> Is there a reason that you can’t use inline assembly for this?
>
> David
>
>> On 13 Jun 2016, at 19:44, Alex Susu via llvm-dev <llvm-dev at
lists.llvm.org> wrote:
>>
>> Hello. I come back to this thread. But I want to ask a slightly
different question.
>> Is there a way to have LLVM IR language intrinsics that are given at
construction
>> time a string that is written at assembly generation time as it is?
(so, basically
>> having placeholders of strings in LLVM that remain untouched until the
end, including
>> code generation time.)
>>
>> More exactly, I would like to give something LIKE this in a middle-tier
pass (I
>> haven't tried this code in LLVM): Value *instrinsicFunc >>
Intrinsic::getDeclaration(M, Intrinsic::my_intrinsic);
>> myIRBuilder.CreateCall(repeatFunc,
>> "string_that_llc_codegen_should_output_as_assembly"); So my
intrinsic would be
>> accepting a general string which will be used at codegen to be output.
I guess I
>> would have to define it like this in a .td file: def int_my_intrinsic :
Intrinsic<[],
>> [string], []>;
>>
>>
>> The other option that can work but is more complex without any benefit
is to define
>> several intrinsics in the .td files, one for EACH possible string: //
To put in the
>> Intrinsics_....td file: def int_my_intrinsic1 : Intrinsic<[], [],
[]>; ... def
>> int_my_intrinsicN : Intrinsic<[], [], []>; // To put in the
InstrInfo.td file
>> something like: def STR_PLACEHOLDER1 : ImmediateInstruction<
0b111111, (outs),
>> (ins), "string_that_llc_codegen_should_output_as_assembly1",
[(int_my_intrinsic1)]
>> >; def STR_PLACEHOLDER2 : ImmediateInstruction< 0b111110, (outs),
(ins),
>> "string_that_llc_codegen_should_output_as_assembly2",
[(int_my_intrinsic2)] >;
>>
>>
>> Best regards, Alex
>>
>> On 6/5/2016 5:21 PM, Alex Susu wrote:
>>> Hello. Hal, the source file you mention
(lib/Target/PowerPC/PPCCTRLoops.cpp) makes
>>> use of LLVM IR intrinsics, in this case defined at
>>> [LLVM_repo]/llvm/include/llvm/IR/IntrinsicsPowerPC.td, such as: //
Intrinsics used
>>> to generate ctr-based loops. These should only be // generated by
the PowerPC
>>> backend! def int_ppc_mtctr : Intrinsic<[], [llvm_anyint_ty],
[]>; def
>>> int_ppc_is_decremented_ctr_nonzero : Intrinsic<[llvm_i1_ty], [],
[]>;
>>>
>>> And these intrinsics are instantiated in the LLVM program, for
example with the
>>> following code in PPCCTRLoops.cpp: IRBuilder<>
>>> CountBuilder(Preheader->getTerminator()); Module *M >>>
Preheader->getParent()->getParent(); Value *MTCTRFunc >>>
Intrinsic::getDeclaration(M, Intrinsic::ppc_mtctr,CountType);
>>> CountBuilder.CreateCall(MTCTRFunc, ECValue);
>>>
>>> I have defined also some intrinsics for my loop instructions in my
file
>>> Intrinsics_Connex.td: 1 intrinsic for REPEAT_X_TIMES and 1 for
END_REPEAT. /*
>>> following Intrinsics.td: class Intrinsic<list<LLVMType>
ret_types, list<LLVMType>
>>> param_types = [], list<IntrinsicProperty> properties = [],
string name = ""> */ def
>>> int_connex_repeat_x_times : Intrinsic<[], [], []>; def
int_connex_end_repeat :
>>> Intrinsic<[llvm_i1_ty], [], []>; and added C++ code doing
CreateCall() like the one
>>> above.
>>>
>>> I'm looking now at http://llvm.org/docs/ExtendingLLVM.html on
how to specify the
>>> instruction selection of this intrinsic. They write there:
"Once the intrinsic has
>>> been added to the system, you must add code generator support for
it. Generally you
>>> must do the following steps: Add support to the .td file for the
target(s) of your
>>> choice in lib/Target/*/*.td. This is usually a matter of adding a
pattern to the
>>> .td file that matches the intrinsic, though it may obviously
require adding the
>>> instructions you want to generate as well. There are lots of
examples in the
>>> PowerPC and X86 backend to follow."
>>>
>>> Then in my pass I create a call to the respective intrinsic: /* See
>>>
http://llvm.org/docs/doxygen/html/classllvm_1_1TargetIntrinsicInfo.html :
"Create
>>> or insert an LLVM Function declaration for an intrinsic, and return
it." * This
>>> creates a line in the LLVM program like: declare void
@llvm.connex.repeat.x.times()
>>> #2 . * This line is required, otherwise llc will complain: *
<<error:
>>> use of undefined value '@llvm.connex.repeat.x.times' call
void
>>> @llvm.connex.repeat.x.times()>> */ Value *repeatFunc
>>> Intrinsic::getDeclaration(M, Intrinsic::connex_repeat_x_times);
>>>
>>> // See
http://llvm.org/docs/doxygen/html/classllvm_1_1IRBuilder.html
>>> aB.CreateCall(repeatFunc); //, ECValue);
>>>
>>>
>>> Then, in the back end, in InstrInfo.td I write: let hasSideEffects
= 1,
>>> isCodeGenOnly = 1 in { //let Pattern =
[(int_connex_repeat_x_times)] in def
>>> REPEAT_X_TIMES : ImmediateInstruction< 0b111111, (outs), (ins),
>>> "REPEAT_X_TIMES(1001)", [(int_connex_repeat_x_times)]
>; }
>>>
>>>
>>> Then, when I run opt and llc I obtain the expected behavior.
>>>
>>> Thank you, Alex
>>>
>>>
>> _______________________________________________ LLVM Developers mailing
list
>> llvm-dev at lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>