diff options
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 10 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/combine-and.ll | 3 |
2 files changed, 7 insertions, 6 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index cc8edb79a57..e8f76a2bb70 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -3998,10 +3998,12 @@ SDValue DAGCombiner::visitAND(SDNode *N) { if (SDValue RAND = ReassociateOps(ISD::AND, SDLoc(N), N0, N1)) return RAND; // fold (and (or x, C), D) -> D if (C & D) == D - if (N1C && N0.getOpcode() == ISD::OR) - if (ConstantSDNode *ORI = isConstOrConstSplat(N0.getOperand(1))) - if (N1C->getAPIntValue().isSubsetOf(ORI->getAPIntValue())) - return N1; + auto MatchSubset = [](ConstantSDNode *LHS, ConstantSDNode *RHS) { + return RHS->getAPIntValue().isSubsetOf(LHS->getAPIntValue()); + }; + if (N0.getOpcode() == ISD::OR && + matchBinaryPredicate(N0.getOperand(1), N1, MatchSubset)) + return N1; // fold (and (any_ext V), c) -> (zero_ext V) if 'and' only clears top bits. if (N1C && N0.getOpcode() == ISD::ANY_EXTEND) { SDValue N0Op0 = N0.getOperand(0); diff --git a/llvm/test/CodeGen/X86/combine-and.ll b/llvm/test/CodeGen/X86/combine-and.ll index df89ee49173..c2da74a1646 100644 --- a/llvm/test/CodeGen/X86/combine-and.ll +++ b/llvm/test/CodeGen/X86/combine-and.ll @@ -223,8 +223,7 @@ define <4 x i32> @and_or_v4i32(<4 x i32> %a0) { define <8 x i16> @and_or_v8i16(<8 x i16> %a0) { ; CHECK-LABEL: and_or_v8i16: ; CHECK: # %bb.0: -; CHECK-NEXT: orps {{.*}}(%rip), %xmm0 -; CHECK-NEXT: andps {{.*}}(%rip), %xmm0 +; CHECK-NEXT: movaps {{.*#+}} xmm0 = [15,7,3,1,14,10,2,32767] ; CHECK-NEXT: retq %1 = or <8 x i16> %a0, <i16 255, i16 127, i16 63, i16 31, i16 15, i16 31, i16 63, i16 -1> %2 = and <8 x i16> %1, <i16 15, i16 7, i16 3, i16 1, i16 14, i16 10, i16 2, i16 32767> |