This implements
(logic_op (op x...), (op y...)) -> (op (logic_op x, y))
when op is an extend, a shift, or an and.
This is similar to DAGCombiner::hoistLogicOpWithSameOpcodeHands (with a bunch of missing cases, e.g. G_TRUNC, G_BITCAST, etc.)
This is implemented so it works both pre and post-legalization.
I'm not entirely happy with the idea of creating (but not inserting) instructions in the match step, but it seems cleaner than passing around a bunch of registers etc. No strong opinions either way.
= default?