This handles expressions:

`(~(a | b) & c) | ~(a | (b | c))` -> `~(a | b)`

`(~(a | b) & c) | ~(b | (a | c))` -> `~(a | b)`

and swapped case:

`(~(a & b) | c) & ~(a & (b & c))` -> `~(a & b)`

`(~(a & b) | c) & ~(b & (a & c))` -> `~(a & b)`

The expression `(~(a | b) & c) | ~((a | b) | c)` is just an

`(~x & c) | ~(x | c)` and will be simplified without this

patch but two cases above need reassociation.

---------------------------------------- define i4 @src(i4 %a, i4 %b, i4 %c) { %0: %or1 = or i4 %c, %a %or2 = or i4 %or1, %b %not1 = xor i4 %or2, 15 %or3 = or i4 %a, %b %not2 = xor i4 %or3, 15 %and2 = and i4 %not2, %c %or4 = or i4 %and2, %not1 ret i4 %or4 } => define i4 @tgt(i4 %a, i4 %b, i4 %c) { %0: %or = or i4 %a, %b %not = xor i4 %or, 15 ret i4 %not } Transformation seems to be correct!

---------------------------------------- define i4 @src(i4 %a, i4 %b, i4 %c) { %0: %and1 = and i4 %c, %a %and2 = and i4 %and1, %b %not1 = xor i4 %and2, 15 %and3 = and i4 %a, %b %not2 = xor i4 %and3, 15 %or2 = or i4 %not2, %c %and4 = and i4 %or2, %not1 ret i4 %and4 } => define i4 @tgt(i4 %a, i4 %b, i4 %c) { %0: %and = and i4 %a, %b %not = xor i4 %and, 15 ret i4 %not } Transformation seems to be correct!