[llvm-dev] LLVM IR intrinsics placeholder for strings (inline assembly)
Alex Susu via llvm-dev
llvm-dev at lists.llvm.org
Tue Jun 14 16:47:36 PDT 2016
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
>
More information about the llvm-dev
mailing list