interesting minor llvm optimizer flaw

if I write:

int z, x;
z = (x >= k); -- where k is a constant

The compiler always wants to translate this into:

z = (x > (k-1));

In general this can often lead to better code (and it does for Mips 16 for sure), except at
the boundary condition where k==-32768

Then it creates the literal -32769 which cannot be placed in a simple immediate field.
That creates a lot of extra code for Mips 16.

I had originally written a pattern for setge when the right operand is a constant.

def: Mips16Pat
   <(setge CPU16Regs:$lhs, immZExt16:$rhs),
    (XorRxRxRy16 (SltiCCRxImmX16 CPU16Regs:$lhs, immZExt16:$rhs),
    (LiRxImmX16 1))>;

I was able to work around this boundary case by doing the reverse transformation at the boundary.


z = (x > (k-1)) => z = (x >= k)

def: Mips16Pat
   <(setgt CPU16Regs:$lhs, -32769),
    (XorRxRxRy16 (SltiCCRxImmX16 CPU16Regs:$lhs, -32768),
    (LiRxImmX16 1))>;

sorry;;; original pattern was

def: Mips16Pat
   <(setge CPU16Regs:$lhs, immSExt16:$rhs),
    (XorRxRxRy16 (SltiCCRxImmX16 CPU16Regs:$lhs, immSExt16:$rhs), (LiRxImmX16 1))>;

(cut and pasted immZExt16:$rhs into example accidentally)

This is more an canonicalization than optimization. The canonicalization reduces the number of cases which later optimization phases have to worry about. Targets usually handle the edge cases in lowering phase (e.g. ARM).