Forums - Snapdragon LLVM with CMake

7 posts / 0 new
Last post
Snapdragon LLVM with CMake
the.sound.of.ye...
Join Date: 19 Feb 14
Posts: 5
Posted: Tue, 2014-03-04 08:04

Dear all,

The pdf that comes with the snapdragon LLVM specifies the usage of the llvm via ndk-build, so at this moment it is not very clear to me how to make the transition from gcc to snapdragonclang using cmake. 

The current setup uses: 

  1. -- android-ndk-r8e/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++
  2. -- android-ndk-r8e/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc
  •  

However I would like to switch to the snapdragonclang toolchain. As far as I understand that would be

  • -- /android-ndk-r8e/toolchains/arm-linux-androideabi-snapdragonclang3.3.1/snapdragon-clang
  • -- /android-ndk-r8e/toolchains/arm-linux-androideabi-snapdragonclang3.3.1/snapdragon-clang++

 

 

When running cmake, the following file is used:

-DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake  ( https://code.google.com/p/android-cmake/source/browse/toolchain/android.toolchain.cmake)

I scanned through this file and I do not see there how to point to the snapdragon llvm, or whether it is supported. Perhaps since this file is more generic and the snapdragon llvm is made by qualcomm.

I originally call cmake like this:

cmake $TRACE_OPT -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G "Eclipse CDT4 - Unix Makefiles" -DOPT_NEON="ON" -DANDROID_ABI="armeabi-v7a with NEON" -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake -DANDROID_FORCE_ARM_BUILD=ON -DANDROID_STL=gnustl_static ../$SOURCE_FOLDER

So I modified it to:

cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -G "Eclipse CDT4 - Unix Makefiles" -DOPT_NEON="ON" -DANDROID_ABI="armeabi-v7a with NEON" -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake -DANDROID_FORCE_ARM_BUILD=ON -DANDROID_STL=gnustl_static -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.7 -DCMAKE_C_COMPILER=/development/android-ndk-r8e/toolchains/arm-linux-androideabi-snapdragonclang3.3.1/snapdragon-clang -DCMAKE_CXX_COMPILER=/development/android-ndk-r8e/toolchains/arm-linux-androideabi-snapdragonclang3.3.1/snapdragon-clang++ ../$SOURCE_FOLDER
 
where I specify the C and C++ compilers. Although by doing this, I leave other variables unspecified, namely:
<UNSET_VARIABLES> CMAKE_ASM_COMPILER, CMAKE_STRIP, CMAKE_AR, CMAKE_LINKER, CMAKE_NM, CMAKE_OBJCOPY, CMAKE_OBJDUMP, CMAKE_RANLIB
 
So I try:
        NDK_TOOLCHAIN=4.7 make VERBOSE=1
 
and I  get:
CMAKE_AR-NOTFOUND cr ../../../libs/armeabi-v7a/libmodule.a output.o
Error running link command: No such file or directory
 
 
Question 1: Should I link all the <UNSET_VARIABLES>  to the binaries in:
android-ndk-r8e/toolchains/arm-linux-androideabi-snapdragonclang3.3.1/Snapdragon_LLVM_for_Android_3.3.1/bin/    ?
(llvm-as, llvm-ar, clang, etc)
 
Question 2: Does it even make sense to try and reuse android.toolchain.cmake ? Or is it just better to define a separate cmake file? (I would still need to know which compiler, assembler, linker to point to.)
 
Question 3: Is it truly enough to extract the toolchain into $NDK_ROOT/toolchains ? Or do I need to run some script so that the ndk becomes 'aware' that the snapdragon llvm is there? I ask this because probably ndk-build takes care of some updates via the setup.mk file. But again, it is not clear to me how this can be mapped to cmake.
 
Thanks in advance and sorry for the long post.
 

 

 

 

 

 

  • Up0
  • Down0
Mandeep
Join Date: 19 Jun 13
Posts: 6
Posted: Wed, 2014-03-05 14:58

Hi,

ndk-build is the recommended way for using Snapdragon LLVM compiler with Android NDK. Is this something you could try instead of cmake?

To use Snapdragon LLVM you can use the following command line:

NDK_TOOLCHAIN_VERSION=snapdragonclang3.3.1 ndk-build -C <some_project>

More responses inline:

Question 1: Should I link all the <UNSET_VARIABLES>  to the binaries in:
android-ndk-r8e/toolchains/arm-linux-androideabi-snapdragonclang3.3.1/Snapdragon_LLVM_for_Android_3.3.1/bin/    ?
(llvm-as, llvm-ar, clang, etc)
[If you use ndk-build, then you should not need to define any variables pointing to the Snapdragon LLVM binaries. The variables inside setup.mk would find the correct toolchain. Using thie with cmake is something which we have not tried doing yet.]
 
Question 2: Does it even make sense to try and reuse android.toolchain.cmake ? Or is it just better to define a separate cmake file? (I would still need to know which compiler, assembler, linker to point to.)
[Again I cannot comment on this since we do not yet support cmake for Android NDK]
 
Question 3: Is it truly enough to extract the toolchain into $NDK_ROOT/toolchains ? Or do I need to run some script so that the ndk becomes 'aware' that the snapdragon llvm is there? I ask this because probably ndk-build takes care of some updates via the setup.mk file. But again, it is not clear to me how this can be mapped to cmake.
[Yes, simply extracting the toolchain under $NDK_ROOT/toolchains is expected to work. You do not need to run any script.]

 

  • Up0
  • Down0
the.sound.of.ye...
Join Date: 19 Feb 14
Posts: 5
Posted: Fri, 2014-03-07 07:23

Hi Mandeep, 

Thanks for your answer.

I will try the ndk-build eventually, but not for the time being. The reason for this is I wanted a quick check of the improvement in performance. I managed to hack it a bit together, but it seems that it would be too much work to do it properly at the moment (given our current setup), and the first results were not that promising anyway. Again this is no related only to the compiler, but also probably to the code itself. 

I only have a question remaining, though. Is there a particular reason why the sructure of the LLVM is different than the clang compilers that come with the android ndk?

 

Thanks again for your help.

Francisco

 

  • Up0
  • Down0
Raja Moderator
Join Date: 17 Apr 13
Posts: 42
Posted: Fri, 2014-03-07 07:40

If by structure you mean the directory structure, it was different in 3.3.x. We have modified the structure in the latest 3.4 release (that came out this week) to match Google's LLVM and GCC compilers.

  • Up0
  • Down0
the.sound.of.ye...
Join Date: 19 Feb 14
Posts: 5
Posted: Mon, 2014-03-10 06:29

Hi Raja, 

Thanks. I have downloaded the 3.4 version and will give it a try. 

A general question: 

I see that in some posts and sites it is claimed that you can see an improvement in performance up to 10% by switching compiler. However I wonder if this is done 'just' by switching compiler, or there are other steps involved; namely ordering neon instructions, or limiting the data to specific sizes, etcetera. 

Is there a description on how this compilers tailors the code for a beter performance on the krait?

regards,

Francisco

 

 

 

  • Up0
  • Down0
Dakip Moderator
Join Date: 17 Apr 13
Posts: 14
Posted: Mon, 2014-03-10 22:17

When measuring the performance impact of using a new compiler, it is important to remember, as with cars – “your mileage may vary”.

Software performance is complex and involves the interplay of many factors including algorithm, workload, and target hardware. A new compiler that is tuned for the target hardware can provide a significant performance boost when it matches specific functions. In the jpeg example that you referred to earlier, the 10% gain was achieved without modifying the source code through the compiler doing a better job of “auto-vectorizing” some of the loops in the source code. Snapdragon’s Krait implementation of the NEON vector unit (VeNum) is unusual among ARM chips in that it is 128 bits wide in hardware; most ARM implementations (if they include NEON) are 64 bits wide. This is one thing that the compiler team has focused on by making sure more loops are vectorized and they better utilize the wider path in hardware.

In rare cases where there is a perfect match, a performance gain can be dramatically more than the 10% in the jpeg example. In some other rare cases performance might even regress with a new compiler. From a whole program perspective, it is more important how the optimizations balance out and if the optimizations benefit critical functions such as improving frames per second or battery life.

We look forward to hearing your experience with Snapdragon LLVM.

If you find a specific case where you feel the compiler should be generating better code we would be happy to investigate this. To do this we will need the problem reduced to a test case along with a data set that exhibits the behavior. Note, it is important that the test case be measurable and reproducible.

  • Up0
  • Down0
cascaval Moderator
Join Date: 14 May 13
Posts: 3
Posted: Mon, 2014-04-28 17:24

It is possible to use the toolchain with cmake if you use a more up-to-date version of the android.toolchain.cmake (available from https://github.com/taka-no-me/android-cmake) and apply a couple small changes around lines 647-691 and 1038-1044 (see below) and then specify -D=arm-linux-androideabi-snapdragon-clang3.4 on your cmake command line.

***************
*** 644,650 ****
  macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath )
   foreach( __toolchain ${${__availableToolchainsLst}} )
    if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" )
!    string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" )
    else()
     set( __gcc_toolchain "${__toolchain}" )
    endif()
--- 633,639 ----
  macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath )
   foreach( __toolchain ${${__availableToolchainsLst}} )
    if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" )
!    string( REGEX REPLACE "androideabi-.*clang3[.][0-9]$" "androideabi-4.8" __gcc_toolchain "${__toolchain}" )
    else()
     set( __gcc_toolchain "${__toolchain}" )
    endif()

*** 688,699 ****
   endif()
   if( NOT __availableToolchains )
    file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" )
!   if( __availableToolchains )
     list(SORT __availableToolchainsLst) # we need clang to go after gcc
    endif()
    __LIST_FILTER( __availableToolchainsLst "^[.]" )
    __LIST_FILTER( __availableToolchainsLst "llvm" )
-   __LIST_FILTER( __availableToolchainsLst "renderscript" )
    __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
    if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 )
     __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" )
--- 677,688 ----
   endif()
   if( NOT __availableToolchains )
    file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" )
!   if( __availableToolchainsLst )
     list(SORT __availableToolchainsLst) # we need clang to go after gcc
    endif()
    __LIST_FILTER( __availableToolchainsLst "^[.]" )
+   __LIST_FILTER( __availableToolchainsLst "^renderscript" ) # broken in r9
    __LIST_FILTER( __availableToolchainsLst "llvm" )
    __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
    if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 )
     __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" )

  # clang
  if( "${ANDROID_TOOLCHAIN_NAME}" STREQUAL "standalone-clang" )
!  set( ANDROID_COMPILER_IS_CLANG 1 )
!  execute_process( COMMAND "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/clang${TOOL_OS_SUFFIX}" --version OUTPUT_VARIABLE ANDROID_CLANG_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE )
!  string( REGEX MATCH "[0-9]+[.][0-9]+" ANDROID_CLANG_VERSION "${ANDROID_CLANG_VERSION}")
  elseif( "${ANDROID_TOOLCHAIN_NAME}" MATCHES "-clang3[.][0-9]?$" )
!  string( REGEX MATCH "3[.][0-9]$" ANDROID_CLANG_VERSION "${ANDROID_TOOLCHAIN_NAME}")
!  string( REGEX REPLACE "androideabi-.*clang${ANDROID_CLANG_VERSION}$" "androideabi-4.8" ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" )
!  # check for the snapdragon clang
!  if( ${ANDROID_TOOLCHAIN_NAME} MATCHES "snapdragon-clang3[.][0-9]?$")
!    set (_android_ndk_clang_prefix "llvm-Snapdragon_LLVM_for_Android_" )
!  else()
!    set (_android_ndk_clang_prefix "llvm-")
!  endif()
!  if( NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${_android_ndk_clang_prefix}${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}/bin/clang${TOOL_OS_SUFFIX}" )
!    message( FATAL_ERROR "Could not find the Clang compiler driver" )
!  endif()
!  set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/${_android_ndk_clang_prefix}${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
!  set( ANDROID_COMPILER_IS_CLANG 1 )
!  unset(_android_ndk_clang_prefix)
  else()
!   set( ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" )
!   unset( ANDROID_COMPILER_IS_CLANG CACHE )
  endif()
 
  string( REPLACE "." "" _clang_name "clang${ANDROID_CLANG_VERSION}" )
  if( NOT EXISTS "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" )

 

Hope this helps!

  • Up0
  • Down0
or Register

Opinions expressed in the content posted here are the personal opinions of the original authors, and do not necessarily reflect those of Qualcomm Incorporated or its subsidiaries (“Qualcomm”). The content is provided for informational purposes only and is not meant to be an endorsement or representation by Qualcomm or any other party. This site may also provide links or references to non-Qualcomm sites and resources. Qualcomm makes no representations, warranties, or other commitments whatsoever about any non-Qualcomm sites or third-party resources that may be referenced, accessible from, or linked to this site.