angr.analyses.decompiler.peephole_optimizations.cmp_masked_shift¶
- class angr.analyses.decompiler.peephole_optimizations.cmp_masked_shift.CmpMaskedShift¶
Bases:
PeepholeOptimizationExprBaseRewrite an equality comparison against a right-shifted value back into a masked comparison, which reads better for flag/discriminant checks.
(x >> n) == c ==> (x & mask) == (c << n) Convert(N->M, x >> n) == c ==> (x & mask) == (c << n)
where
maskselects the compared bits[n, n+width-1]ofxandwidthis the truncated widthM(orN - nwhen there is no Convert). This is the inverse of a simplification that can turn(x & high_mask) == c(a mask that clears the low bits) into the shift/extract form: the masked compare is the clearer form in decompiled output, so restore it.As a special case, when the compared bits are all bits above
nand the constant is 0, the comparison is an unsigned bound check (libVEX 3.27+ spechelpers foldx <=u 2**n-1into this form), so emit the bound check instead:(x >> n) == 0 ==> x <=u 2**n - 1 (x >> n) != 0 ==> x >u 2**n - 1
Only logical right shifts and unsigned truncations are handled, and only
n > 0(a low-mask compare,n == 0, already reads as a cast).- NAME = '(x >> n) == c => (x & mask) == (c << n)'¶
- expr_classes = (<class 'angr.ailment.expression.BinaryOp'>,)¶