The InstCombine phase did the following optimization:
V >= Lo && V < Hi --> V - Lo u< Hi - Lo V < Lo || V >= Hi --> V - Lo u>= Hi - Lo
This generates code like below:
V.off = V - Lo ConstV = Hi - Lo Cond = V.off u< ConstV if (Cond) ... ... V is used ...
The current linux verifier is not able to handle such a sequence
and may reject the prog as it did not used refined value range
for V at the place of "V is used".
Previous attempt, https://reviews.llvm.org/D70372, is to disable
this optimization under BPF target. But it violates the principle
that InstCombiner is target independent.
This patch implemented an IR pass to make the code more friendly
to the verifier. The IR pass will transform the undo the above
InstCombine optimization.
V - Lo u< Hi - Lo --> V >= Lo && V < Hi V - Lo u>= Hi - Lo --> V < Lo || V >= Hi
In addition, the following two cases are also handled.
V - Lo u<= Hi - Lo --> V >= Lo && V <= Hi V - Lo u> Hi - Lo --> V < Lo || V > Hi
As a concrete example, the source code:
#pragma clang loop unroll(disable) for (i = 0; i < 100; ++i) { ret = ext_test(value + off); if (ret <= 0 || ret > 7) return 0; off += ret & 7; }
The assembly code with -mcpu=v3:
LBB0_1: r1 = value ll r1 += r6 call ext_test if w0 s< 1 goto LBB0_4 if w0 s> 7 goto LBB0_4 r1 = w0 r1 <<= 32 r1 >>= 32 r6 += r1 w7 += -1 if w7 != 0 goto LBB0_1