diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index efb50a6b58c21..9dc8cf90fd983 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -2295,10 +2295,12 @@ m_NSWNeg(const ValTy &V) { } /// Matches a 'Not' as 'xor V, -1' or 'xor -1, V'. +/// NOTE: we first match the 'Not' (by matching '-1'), +/// and only then match the inner matcher! template -inline BinaryOp_match, Instruction::Xor, true> +inline BinaryOp_match, ValTy, Instruction::Xor, true> m_Not(const ValTy &V) { - return m_c_Xor(V, m_AllOnes()); + return m_c_Xor(m_AllOnes(), V); } template struct NotForbidUndef_match { diff --git a/llvm/test/Transforms/InstCombine/D139275_c4001580.ll b/llvm/test/Transforms/InstCombine/D139275_c4001580.ll index 378d87153a160..9eb2e91385846 100644 --- a/llvm/test/Transforms/InstCombine/D139275_c4001580.ll +++ b/llvm/test/Transforms/InstCombine/D139275_c4001580.ll @@ -5,8 +5,10 @@ ; FIXME: this is a miscompile. define i8 @D139275_c4001580(i1 %c0, i1 %c1, i1 %c2, i8 %inner.sel.trueval, i8 %inner.sel.falseval, i8 %outer.sel.trueval) { ; CHECK-LABEL: @D139275_c4001580( -; CHECK-NEXT: [[INNER_SEL:%.*]] = select i1 [[C2:%.*]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_TRUEVAL:%.*]] -; CHECK-NEXT: [[OUTER_SEL:%.*]] = select i1 [[C1:%.*]], i8 [[INNER_SEL]], i8 [[INNER_SEL_FALSEVAL:%.*]] +; CHECK-NEXT: [[INNER_COND:%.*]] = xor i1 [[C0:%.*]], [[C1:%.*]] +; CHECK-NEXT: [[OUTER_COND:%.*]] = and i1 [[C2:%.*]], [[C1]] +; CHECK-NEXT: [[INNER_SEL:%.*]] = select i1 [[INNER_COND]], i8 [[INNER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL_FALSEVAL:%.*]] +; CHECK-NEXT: [[OUTER_SEL:%.*]] = select i1 [[OUTER_COND]], i8 [[OUTER_SEL_TRUEVAL:%.*]], i8 [[INNER_SEL]] ; CHECK-NEXT: ret i8 [[OUTER_SEL]] ; %inner.cond = xor i1 %c0, %c1 diff --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp index ab35df016cdda..6c0395131eb97 100644 --- a/llvm/unittests/IR/PatternMatch.cpp +++ b/llvm/unittests/IR/PatternMatch.cpp @@ -550,6 +550,20 @@ TEST_F(PatternMatchTest, Power2) { EXPECT_TRUE(m_NegatedPower2().match(CNegIntMin)); } +TEST_F(PatternMatchTest, Not) { + Value *C1 = IRB.getInt32(1); + Value *C2 = IRB.getInt32(2); + Value *C3 = IRB.getInt32(3); + Instruction *Not = BinaryOperator::CreateXor(C1, C2); + + // When `m_Not` does not match the `not` itself, + // it should not try to apply the inner matcher. + Value *Val = C3; + EXPECT_FALSE(m_Not(m_Value(Val)).match(Not)); + EXPECT_EQ(Val, C3); + Not->deleteValue(); +} + TEST_F(PatternMatchTest, CommutativeDeferredValue) { Value *X = IRB.getInt32(1); Value *Y = IRB.getInt32(2);