Index: include/llvm/IR/PatternMatch.h =================================================================== --- include/llvm/IR/PatternMatch.h +++ include/llvm/IR/PatternMatch.h @@ -1036,34 +1036,11 @@ template inline LoadClass_match m_Load(const OpTy &Op) { return LoadClass_match(Op); } + //===----------------------------------------------------------------------===// // Matchers for unary operators // -template struct not_match { - LHS_t L; - - not_match(const LHS_t &LHS) : L(LHS) {} - - template bool match(OpTy *V) { - if (auto *O = dyn_cast(V)) - if (O->getOpcode() == Instruction::Xor) { - if (isAllOnes(O->getOperand(1))) - return L.match(O->getOperand(0)); - if (isAllOnes(O->getOperand(0))) - return L.match(O->getOperand(1)); - } - return false; - } - -private: - bool isAllOnes(Value *V) { - return isa(V) && cast(V)->isAllOnesValue(); - } -}; - -template inline not_match m_Not(const LHS &L) { return L; } - template struct neg_match { LHS_t L; @@ -1590,6 +1567,13 @@ return BinaryOp_match(L, R); } +/// Matches a 'Not' as 'xor V, -1' or 'xor -1, V'. +template +inline BinaryOp_match, Instruction::Xor, true> +m_Not(const ValTy &V) { + return m_c_Xor(V, m_AllOnes()); +} + /// Matches an SMin with LHS and RHS in either order. template inline MaxMin_match Index: test/Transforms/InstCombine/sub.ll =================================================================== --- test/Transforms/InstCombine/sub.ll +++ test/Transforms/InstCombine/sub.ll @@ -73,12 +73,9 @@ ret <2 x i8> %sub } -; FIXME: define <2 x i8> @notnotsub_vec_undef_elts(<2 x i8> %x, <2 x i8> %y) { ; CHECK-LABEL: @notnotsub_vec_undef_elts( -; CHECK-NEXT: [[NX:%.*]] = xor <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[NY:%.*]] = xor <2 x i8> [[Y:%.*]], -; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i8> [[NX]], [[NY]] +; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i8> [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: ret <2 x i8> [[SUB]] ; %nx = xor <2 x i8> %x, Index: test/Transforms/InstCombine/vector-xor.ll =================================================================== --- test/Transforms/InstCombine/vector-xor.ll +++ test/Transforms/InstCombine/vector-xor.ll @@ -107,10 +107,8 @@ define <4 x i32> @test_v4i32_not_ashr_not_undef(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: @test_v4i32_not_ashr_not_undef( -; CHECK-NEXT: [[TMP1:%.*]] = xor <4 x i32> [[X:%.*]], -; CHECK-NEXT: [[TMP2:%.*]] = ashr <4 x i32> [[TMP1]], [[Y:%.*]] -; CHECK-NEXT: [[TMP3:%.*]] = xor <4 x i32> [[TMP2]], -; CHECK-NEXT: ret <4 x i32> [[TMP3]] +; CHECK-NEXT: [[TMP1:%.*]] = ashr <4 x i32> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: ret <4 x i32> [[TMP1]] ; %1 = xor <4 x i32> , %x %2 = ashr <4 x i32> %1, %y @@ -142,9 +140,8 @@ define <4 x i32> @test_v4i32_not_ashr_negative_const_undef(<4 x i32> %a0) { ; CHECK-LABEL: @test_v4i32_not_ashr_negative_const_undef( -; CHECK-NEXT: [[TMP1:%.*]] = ashr <4 x i32> , [[A0:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = xor <4 x i32> [[TMP1]], -; CHECK-NEXT: ret <4 x i32> [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = lshr <4 x i32> , [[A0:%.*]] +; CHECK-NEXT: ret <4 x i32> [[TMP1]] ; %1 = ashr <4 x i32> , %a0 %2 = xor <4 x i32> , %1 @@ -175,9 +172,8 @@ define <4 x i32> @test_v4i32_not_lshr_nonnegative_const_undef(<4 x i32> %a0) { ; CHECK-LABEL: @test_v4i32_not_lshr_nonnegative_const_undef( -; CHECK-NEXT: [[TMP1:%.*]] = lshr <4 x i32> , [[A0:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = xor <4 x i32> [[TMP1]], -; CHECK-NEXT: ret <4 x i32> [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = ashr <4 x i32> , [[A0:%.*]] +; CHECK-NEXT: ret <4 x i32> [[TMP1]] ; %1 = lshr <4 x i32> , %a0 %2 = xor <4 x i32> , %1