From c77d50a97eb77d0f17e014f7d9b13240cc01ad67 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Sun, 5 Jan 2014 03:28:29 +0000 Subject: [PATCH] Add support to the pattern match library for matching NSW and NUW instructions. I needed this for a quick experiment I was making, and while I've no idea if that will ever get committed, I didn't want to throw away the pattern match code and for anyone else to have to write it again. I've added unittests to make sure this works correctly. In fun news, this also uncovered the IRBuilder bug. Doh! llvm-svn: 198541 --- llvm/include/llvm/Support/PatternMatch.h | 90 ++++++++++++++++++++++++ llvm/unittests/IR/PatternMatch.cpp | 74 +++++++++++++++++++ 2 files changed, 164 insertions(+) diff --git a/llvm/include/llvm/Support/PatternMatch.h b/llvm/include/llvm/Support/PatternMatch.h index 240bb81d31a7..97739b08694d 100644 --- a/llvm/include/llvm/Support/PatternMatch.h +++ b/llvm/include/llvm/Support/PatternMatch.h @@ -498,6 +498,96 @@ m_AShr(const LHS &L, const RHS &R) { return BinaryOp_match(L, R); } +template +struct OverflowingBinaryOp_match { + LHS_t L; + RHS_t R; + + OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + + template + bool match(OpTy *V) { + if (OverflowingBinaryOperator *Op = dyn_cast(V)) { + if (Op->getOpcode() != Opcode) + return false; + if (WrapFlags & OverflowingBinaryOperator::NoUnsignedWrap && + !Op->hasNoUnsignedWrap()) + return false; + if (WrapFlags & OverflowingBinaryOperator::NoSignedWrap && + !Op->hasNoSignedWrap()) + return false; + return L.match(Op->getOperand(0)) && R.match(Op->getOperand(1)); + } + return false; + } +}; + +template +inline OverflowingBinaryOp_match +m_NSWAdd(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match( + L, R); +} +template +inline OverflowingBinaryOp_match +m_NSWSub(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match( + L, R); +} +template +inline OverflowingBinaryOp_match +m_NSWMul(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match( + L, R); +} +template +inline OverflowingBinaryOp_match +m_NSWShl(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match( + L, R); +} + +template +inline OverflowingBinaryOp_match +m_NUWAdd(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match( + L, R); +} +template +inline OverflowingBinaryOp_match +m_NUWSub(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match( + L, R); +} +template +inline OverflowingBinaryOp_match +m_NUWMul(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match( + L, R); +} +template +inline OverflowingBinaryOp_match +m_NUWShl(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match( + L, R); +} + //===----------------------------------------------------------------------===// // Class that matches two different binary ops. // diff --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp index b593648bb32a..150f1657b9c2 100644 --- a/llvm/unittests/IR/PatternMatch.cpp +++ b/llvm/unittests/IR/PatternMatch.cpp @@ -201,4 +201,78 @@ TEST_F(PatternMatchTest, FloatingPointUnorderedMax) { EXPECT_EQ(R, MatchR); } +TEST_F(PatternMatchTest, OverflowingBinOps) { + Value *L = IRB.getInt32(1); + Value *R = IRB.getInt32(2); + Value *MatchL, *MatchR; + + EXPECT_TRUE( + m_NSWAdd(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWAdd(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE( + m_NSWSub(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWSub(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE( + m_NSWMul(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWMul(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE(m_NSWShl(m_Value(MatchL), m_Value(MatchR)).match( + IRB.CreateShl(L, R, "", /* NUW */ false, /* NSW */ true))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + + EXPECT_TRUE( + m_NUWAdd(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWAdd(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE( + m_NUWSub(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWSub(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE( + m_NUWMul(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWMul(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE(m_NUWShl(m_Value(MatchL), m_Value(MatchR)).match( + IRB.CreateShl(L, R, "", /* NUW */ true, /* NSW */ false))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + + EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateAdd(L, R))); + EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R))); + EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateNSWSub(L, R))); + EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateSub(L, R))); + EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateNUWSub(L, R))); + EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R))); + EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateMul(L, R))); + EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateNUWMul(L, R))); + EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R))); + EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match(IRB.CreateShl(L, R))); + EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match( + IRB.CreateShl(L, R, "", /* NUW */ true, /* NSW */ false))); + EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R))); + + EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateAdd(L, R))); + EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R))); + EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateNUWSub(L, R))); + EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateSub(L, R))); + EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateNSWSub(L, R))); + EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R))); + EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateMul(L, R))); + EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateNSWMul(L, R))); + EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R))); + EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match(IRB.CreateShl(L, R))); + EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match( + IRB.CreateShl(L, R, "", /* NUW */ false, /* NSW */ true))); + EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R))); +} + } // anonymous namespace.