diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -14668,6 +14668,22 @@ if (N0.getOpcode() == ISD::BITCAST) return DAG.getBitcast(VT, N0.getOperand(0)); + // fold (conv (logicop (conv x), (c))) -> (logicop x, (conv c)) + // iff the current bitwise logicop type isn't legal + if (ISD::isBitwiseLogicOp(N0.getOpcode()) && VT.isInteger() && + !TLI.isTypeLegal(N0.getOperand(0).getValueType())) { + auto IsFreeBitcast = [VT](SDValue V) { + return (V.getOpcode() == ISD::BITCAST && + V.getOperand(0).getValueType() == VT) || + (ISD::isBuildVectorOfConstantSDNodes(V.getNode()) && + V->hasOneUse()); + }; + if (IsFreeBitcast(N0.getOperand(0)) && IsFreeBitcast(N0.getOperand(1))) + return DAG.getNode(N0.getOpcode(), SDLoc(N), VT, + DAG.getBitcast(VT, N0.getOperand(0)), + DAG.getBitcast(VT, N0.getOperand(1))); + } + // fold (conv (load x)) -> (load (conv*)x) // If the resultant load doesn't need a higher alignment than the original! if (ISD::isNormalLoad(N0.getNode()) && N0.hasOneUse() && diff --git a/llvm/test/CodeGen/AMDGPU/fneg.ll b/llvm/test/CodeGen/AMDGPU/fneg.ll --- a/llvm/test/CodeGen/AMDGPU/fneg.ll +++ b/llvm/test/CodeGen/AMDGPU/fneg.ll @@ -218,13 +218,8 @@ ret half %fadd } -; FIXME: This is terrible ; FUNC-LABEL: {{^}}s_fneg_v2i16: -; SI: s_and_b32 s5, s4, 0xffff0000 -; SI: s_xor_b32 s4, s4, 0x8000 -; SI: s_and_b32 s4, s4, 0xffff -; SI: s_or_b32 s4, s4, s5 -; SI: s_add_i32 s4, s4, 0x80000000 +; SI: s_xor_b32 s4, s4, 0x80008000 ; VI: s_lshr_b32 s5, s4, 16 ; VI: s_xor_b32 s4, s4, 0x8000