[llvm-dev] Kaleidoscope tutorial: comments, corrections and Windows support
Mehdi Amini via llvm-dev
llvm-dev at lists.llvm.org
Sat Feb 11 11:04:25 PST 2017
> On Feb 11, 2017, at 10:15 AM, Moritz Kroll <Moritz.Kroll at gmx.de> wrote:
>
> Hi Mehdi,
>
> I submitted a patch:
>
> [PATCH] D29864: Update Kaleidoscope tutorial and improve Windows support
>
> https://reviews.llvm.org/D29864
Thanks!
>
>
> An open question: Why doesn't CSE work for sin and cos as shown at the end of section 4.4?
CSE works on functions marked as “readnone” , the JIT does not does add the attributes automatically.
My guess is that it is the responsibility of the frontend to either emit a call to the intrinsic or call a function sin() with the proper set of attributes.
—
Mehdi
> It looks like, they are not recognized as intrinsics and don't get the according attributes in Function::Function.
> Function::recalculateIntrinsicID requires the function name to start with "llvm.".
> Maybe this worked in a previous version of LLVM?
>
> Optimizing sin and cos is specifically mentioned in AliasAnalysis.h:
>
> llvm-3.9.1.src\include\llvm\Analysis\AliasAnalysis.h:
>
> /// Checks if the specified call is known to never read or write memory.
> ///
> /// Note that if the call only reads from known-constant memory, it is also
> /// legal to return true. Also, calls that unwind the stack are legal for
> /// this predicate.
> ///
> /// Many optimizations (such as CSE and LICM) can be performed on such calls
> /// without worrying about aliasing properties, and many calls have this
> /// property (e.g. calls to 'sin' and 'cos').
> ///
> /// This property corresponds to the GCC 'const' attribute.
> bool doesNotAccessMemory(ImmutableCallSite CS) {
> return getModRefBehavior(CS) == FMRB_DoesNotAccessMemory;
> }
>
> Best regards
> Moritz
>
>
> On 07.02.2017 08:02, Mehdi Amini wrote:
>>
>>> On Feb 6, 2017, at 5:07 PM, Moritz Kroll via llvm-dev <llvm-dev at lists.llvm.org> wrote:
>>>
>>> Hi,
>>>
>>> I'm currently working my way through the tutorial with LLVM 3.9.1 on Windows (finished chapter 4) and stumbled over a few things which could be improved:
>>
>> Any chance you would submit a patch to fix all this?
>>
>> http://llvm.org/docs/DeveloperPolicy.html
>> http://llvm.org/docs/Phabricator.html
>>
>> Thanks,
>>
>> —
>> Mehdi
>>
>>
>>>
>>> - "LLVMContext" does not exist as a variable -> "TheContext"
>>> - Chapter 3: 5 times
>>> - Chapter 4: 1 time
>>> - Chapter 5: 4 times
>>> - Chapter 6: 2 times
>>> - Chapter 7: 2 times
>>>
>>> 3.4. Function Code Generation
>>>
>>> - Wouldn't it make sense to have a
>>> "Type *DoubleTy = Type::getDoubleTy(TheContext);"?
>>> - "Function *TheFunction = TheModule->getFunction(Proto->getName());"
>>> The new getName method is unexpected, the tutorial user has to lookup
>>> and copy the definition from the full listing.
>>>
>>> 3.5. Driver Changes and Closing Thoughts
>>>
>>> - "When you quit the current demo"
>>> -> "When you quit the current demo (by sending an EOF
>>> via CTRL+D on Linux or CTRL+Z and ENTER on Windows)"
>>> (Windows users normally don't send EOF characters so they
>>> usually don't know this shortcut)
>>>
>>> 4.3. LLVM Optimization Passes
>>>
>>> - Code for InitializeModuleAndPassManager:
>>> - Remove "Context LLVMContext;"
>>> - "TheJIT" comes out of nowhere and thus is not defined in the code
>>> of the tutorial user. Setting the data layout could be added in
>>> 4.4, as it is at least not required for showing the improved body
>>> of "test"
>>> - "createBasicAliasAnalysisPass" does not exist anymore (llvm-3.9.1).
>>> Also requires adaption of the text
>>>
>>> 4.4. Adding a JIT Compiler
>>>
>>> - Code for main:
>>> - "TheJIT = llvm::make_unique<KaleidoscopeJIT>();" will cause a crash
>>> due to an invalid read in "Datalayout::operator=" as
>>> "EngineBuilder().selectTarget()" returns a nullptr when
>>> "InitializeNativeTarget" has not been called yet.
>>> Other problems occur if the other InitializeNative* functions are
>>> not called. So you should add them here.
>>> - The (silently added) "TheModule->print" call from chapter 3
>>> is missing
>>>
>>> - "The KaleidoscopeJIT class is a simple JIT built specifically for
>>> these tutorials.":
>>> It would be nice to mention, where to find the include file:
>>> llvm-src/examples/Kaleidoscope/include/KaleidoscopeJIT.h
>>>
>>> - "auto ExprSymbol = TheJIT->findSymbol("__anon_expr");":
>>> On Windows, this will always fail as this function will search for
>>> "ExportedSymbolsOnly" and the exported flag seems to be implemented
>>> incorrectly for COFF in LLVM (see bug report from Russell Wallace:
>>> http://lists.llvm.org/pipermail/llvm-dev/2016-April/097964.html ).
>>> Applied to the current version of Kaleidoscope, he suggested to use
>>> "CompileLayer.findSymbolIn(H, Name, false)" in
>>> "KaleidoscopeJIT::findMangledSymbol" to also allow non-exported
>>> symbols.
>>> I fixed it by changing "COFFObjectFile::getSymbolFlags" in
>>> llvm-src/lib/Object/COFFObjectFile.cpp
>>> to additionally OR SymbolRef::SF_Exported to Result:
>>>
>>>> uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
>>>> COFFSymbolRef Symb = getCOFFSymbol(Ref);
>>>> uint32_t Result = SymbolRef::SF_None;
>>>>
>>>> if (Symb.isExternal() || Symb.isWeakExternal())
>>>> Result |= SymbolRef::SF_Global | SymbolRef::SF_Exported;
>>>
>>> Works and sounds reasonable to me, but maybe you can prove me wrong.
>>>
>>> - "ready> sin(1.0);": On Windows, this fails with "LLVM ERROR: Program
>>> used external function '_sin' which could not be resolved!" because
>>> "DynamicLibrary::SearchForAddressOfSymbol" iterates over all loaded
>>> libraries and uses GetProcAddress to try getting the address.
>>> But for the old "msvcrt.dll" as well as the newer "ucrtbased.dll",
>>> the math functions are exported without a leading underscore.
>>> Additionally, LLVM provides some "explicit" symbols which would
>>> otherwise only exist in form of a macro (see comment in
>>> llvm-src/lib/Support/Windows/DynamicLibrary.inc). These are also only
>>> available in unmangled form, for example "sinf".
>>> Thus I propose to add this code at the end of
>>> "KaleidoscopeJIT::findMangledSymbol":
>>>
>>>> #ifdef LLVM_ON_WIN32
>>>> // For Windows retry without "_" at begining, as RTDyldMemoryManager uses
>>>> // GetProcAddress and standard libraries like msvcrt.dll use names
>>>> // with and without "_" (for example "_itoa" but "sin").
>>>> if (Name.length() > 2 && Name[0] == '_')
>>>> if (auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(
>>>> Name.substr(1)))
>>>> return JITSymbol(SymAddr, JITSymbolFlags::Exported);
>>>> #endif
>>>>
>>>> return nullptr;
>>>> }
>>>
>>> - "ready> sin(1.0);
>>> Read top-level expression:
>>> define double @2() {
>>> entry:
>>> ret double 0x3FEAED548F090CEE
>>> }
>>>
>>> Evaluated to 0.841471":
>>> Actually "sin" is not called at all, LLVM knew "sin" and just returns
>>> the already const-folded value.
>>> In my case, I do see a
>>> "%calltmp = call double @sin(double 1.000000e+00)",
>>> though, inspite of the same optimizations as in your listing...
>>>
>>> - "ready> def foo(x) sin(x)*sin(x) + cos(x)*cos(x);
>>> Read function definition:
>>> define double @foo(double %x) {
>>> entry:
>>> %calltmp = call double @sin(double %x)
>>> %multmp = fmul double %calltmp, %calltmp
>>> %calltmp2 = call double @cos(double %x)
>>> %multmp4 = fmul double %calltmp2, %calltmp2
>>> %addtmp = fadd double %multmp, %multmp4
>>> ret double %addtmp
>>> }":
>>> In my case, the CSE does not work, although it does work for the
>>> example in 4.3:
>>> "ready> def foo(x) sin(x)*sin(x) + cos(x)*cos(x);
>>> ready> Read function definition:
>>> define double @foo(double %x) {
>>> entry:
>>> %calltmp = call double @sin(double %x)
>>> %calltmp1 = call double @sin(double %x)
>>> %multmp = fmul double %calltmp, %calltmp1
>>> %calltmp2 = call double @cos(double %x)
>>> %calltmp3 = call double @cos(double %x)
>>> %multmp4 = fmul double %calltmp2, %calltmp3
>>> %addtmp = fadd double %multmp, %multmp4
>>> ret double %addtmp
>>> }"
>>>
>>> - "extern putchard(x); putchard(120);":
>>> Again, on Windows, this doesn't work. To make it work, you have to
>>> use "extern "C" __declspec(dllexport) double putchard(double X)"
>>> so the function will be found via GetProcAddress for the main module.
>>> This wouldn't hurt for Linux / Mac, would it?
>>>
>>> Best regards
>>> Moritz Kroll
>>> _______________________________________________
>>> 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