mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
101 lines
2.7 KiB
ReStructuredText
101 lines
2.7 KiB
ReStructuredText
Known Bits Analysis
|
|
===================
|
|
|
|
The Known Bits Analysis pass makes information about the known values of bits
|
|
available to other passes to enable transformations like those in the examples
|
|
below. The information is lazily computed so you should only pay for what you
|
|
use.
|
|
|
|
Examples
|
|
--------
|
|
|
|
A simple example is that transforming::
|
|
|
|
a + 1
|
|
|
|
into::
|
|
|
|
a | 1
|
|
|
|
is only valid when the addition doesn't carry. In other words it's only valid
|
|
if ``a & 1`` is zero.
|
|
|
|
Another example is:
|
|
|
|
.. code-block:: none
|
|
|
|
%1:(s32) = G_CONSTANT i32 0xFF0
|
|
%2:(s32) = G_AND %0, %1
|
|
%3:(s32) = G_CONSTANT i32 0x0FF
|
|
%4:(s32) = G_AND %2, %3
|
|
|
|
We can use the constants and the definition of ``G_AND`` to determine the known
|
|
bits:
|
|
|
|
.. code-block:: none
|
|
|
|
; %0 = 0x????????
|
|
%1:(s32) = G_CONSTANT i32 0xFF0 ; %1 = 0x00000FF0
|
|
%2:(s32) = G_AND %0, %1 ; %2 = 0x00000??0
|
|
%3:(s32) = G_CONSTANT i32 0x0FF ; %3 = 0x000000FF
|
|
%4:(s32) = G_AND %2, %3 ; %4 = 0x000000?0
|
|
|
|
and then use this to simplify the expression:
|
|
|
|
.. code-block:: none
|
|
|
|
; %0 = 0x????????
|
|
%5:(s32) = G_CONSTANT i32 0x0F0 ; %5 = 0x00000FF0
|
|
%4:(s32) = G_AND %0, %5 ; %4 = 0x000000?0
|
|
|
|
Note that ``%4`` still has the same known bits as before the transformation.
|
|
Many transformations share this property. The main exception being when the
|
|
transform causes undefined bits to become defined to either zero, one, or
|
|
defined but unknown.
|
|
|
|
Usage
|
|
-----
|
|
|
|
To use Known Bits Analysis in a pass, first include the header and register the
|
|
dependency with ``INITIALIZE_PASS_DEPENDENCY``.
|
|
|
|
.. code-block:: c++
|
|
|
|
#include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
|
|
|
|
...
|
|
|
|
INITIALIZE_PASS_BEGIN(...)
|
|
INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis)
|
|
INITIALIZE_PASS_END(...)
|
|
|
|
and require the pass in ``getAnalysisUsage``.
|
|
|
|
.. code-block:: c++
|
|
|
|
void MyPass::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
AU.addRequired<GISelKnownBitsAnalysis>();
|
|
// Optional: If your pass preserves known bits analysis (many do) then
|
|
// indicate that it's preserved for re-use by another pass here.
|
|
AU.addPreserved<GISelKnownBitsAnalysis>();
|
|
}
|
|
|
|
Then it's just a matter of fetching the analysis and using it:
|
|
|
|
.. code-block:: c++
|
|
|
|
bool MyPass::runOnMachineFunction(MachineFunction &MF) {
|
|
...
|
|
GISelKnownBits &KB = getAnalysis<GISelKnownBitsAnalysis>().get(MF);
|
|
...
|
|
MachineInstr *MI = ...;
|
|
KnownBits Known = KB->getKnownBits(MI->getOperand(0).getReg());
|
|
if (Known.Zeros & 1) {
|
|
// Bit 0 is known to be zero
|
|
}
|
|
...
|
|
}
|
|
|
|
There are many more API's beyond ``getKnownBits()``. See the `API reference
|
|
<https://llvm.org/doxygen>`_ for more information
|