It seems SimplifySetcc likes to turns (i1 (setcc ne (and x, 1), 1)) into (i1 (setcc eq (i1 (trunc x)), 0) which becomes (i1 (xor (i1 (trunc x)), 1)). If its used by a select, the xor gets removed by swapping the true/false values. Then type legalization comes along and turns the trunc into (i8 (and x, 1)). So in the end we have no setcc.
I attempted to make (i1 (setcc eq (and x, 1), 0)) also produce (i1 (xor (i1 (trunc x)), 1) so they would be the same, but discovered that broke this code.
This patch teachs the code in LowerSELECT to handle this alternate possibility. I moved the code above the call to LowerSETCC because I don't think we need to do that before doing this check.
Ultimately, this is step towards improving this code. Which currently produces a BT and SETAE instruction. But produces arithmetic/logic operations if you use "icmp ne i64 %a17, 1" or if you use "icmp ne i64 %a17, 0" and swap the select operands.
define void @foo(i64 %x, i32 %c.0282.in, i32 %d.0280, i32* %ptr0, i32* %ptr1) { %c.0282 = and i32 %c.0282.in, 268435455 %a16 = lshr i64 32508, %x %a17 = and i64 %a16, 1 %tobool = icmp eq i64 %a17, 0 %. = select i1 %tobool, i32 1, i32 2 %.286 = select i1 %tobool, i32 27, i32 26 %shr97 = lshr i32 %c.0282, %. %shl98 = shl i32 %c.0282.in, %.286 %or99 = or i32 %shr97, %shl98 %shr100 = lshr i32 %d.0280, %. %shl101 = shl i32 %d.0280, %.286 %or102 = or i32 %shr100, %shl101 store i32 %or99, i32* %ptr0 store i32 %or102, i32* %ptr1 ret void }