[llvm-dev] LLVM IR intrinsics placeholder for strings (inline assembly)

Alex Susu via llvm-dev
Tue, 14 Jun 2016 23:47:36 -0000

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
>