BitCode in iOS
When an iOS app is compiled with bitcode enabled, the compiler generates an intermediate representation of the app’s code, instead of generating machine code for a specific device architecture. This intermediate representation, called LLVM IR (LLVM Intermediate Representation), is architecture-agnostic and can be optimized for different device architectures by Apple’s App Store servers at the time of download.
The app binary that is uploaded to the App Store includes this LLVM IR, along with some metadata that describes the original target architecture and other information about the app. When a user downloads the app, the App Store server downloads the LLVM IR and optimizes it for the user’s specific device architecture.
This optimization process can include various transformations to the LLVM IR, such as inlining functions, removing dead code, and reordering instructions. The optimized LLVM IR is then compiled into machine code for the user’s device and loaded into memory, allowing the app to run.
Using bitcode can lead to smaller app binaries, faster downloads, and improved app performance on new devices. However, there can be some trade-offs in terms of compile time and debugging, as the bitcode is not directly executable and cannot be easily inspected or modified.
How LLVM IR works
The optimization of LLVM IR is performed by a tool called the LLVM optimizer. The LLVM optimizer uses a variety of optimization techniques, such as constant propagation, dead code elimination, loop unrolling, and function inlining, to improve the performance of the app on the target device.
After the LLVM optimizer has performed its optimizations, the optimized LLVM IR is passed to the LLVM code generator, which generates machine code for the user’s device. The generated machine code is then loaded into memory and executed by the device’s processor.
The use of LLVM IR in app downloading and optimization allows for a more flexible and efficient approach to app compilation and optimization.It enables the App Store to optimize apps for different device architectures and future devices without requiring developers to submit new versions of their apps.