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!