[llvm] r198541 - Add support to the pattern match library for matching NSW and NUW

Chandler Carruth chandlerc at gmail.com
Sat Jan 4 19:28:30 PST 2014


Author: chandlerc
Date: Sat Jan  4 21:28:29 2014
New Revision: 198541

URL: http://llvm.org/viewvc/llvm-project?rev=198541&view=rev
Log:
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!

Modified:
    llvm/trunk/include/llvm/Support/PatternMatch.h
    llvm/trunk/unittests/IR/PatternMatch.cpp

Modified: llvm/trunk/include/llvm/Support/PatternMatch.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/PatternMatch.h?rev=198541&r1=198540&r2=198541&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/PatternMatch.h (original)
+++ llvm/trunk/include/llvm/Support/PatternMatch.h Sat Jan  4 21:28:29 2014
@@ -498,6 +498,96 @@ m_AShr(const LHS &L, const RHS &R) {
   return BinaryOp_match<LHS, RHS, Instruction::AShr>(L, R);
 }
 
+template<typename LHS_t, typename RHS_t, unsigned Opcode, unsigned WrapFlags = 0>
+struct OverflowingBinaryOp_match {
+  LHS_t L;
+  RHS_t R;
+
+  OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
+
+  template<typename OpTy>
+  bool match(OpTy *V) {
+    if (OverflowingBinaryOperator *Op = dyn_cast<OverflowingBinaryOperator>(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 <typename LHS, typename RHS>
+inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Add,
+                                 OverflowingBinaryOperator::NoSignedWrap>
+m_NSWAdd(const LHS &L, const RHS &R) {
+  return OverflowingBinaryOp_match<LHS, RHS, Instruction::Add,
+                                   OverflowingBinaryOperator::NoSignedWrap>(
+      L, R);
+}
+template <typename LHS, typename RHS>
+inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Sub,
+                                 OverflowingBinaryOperator::NoSignedWrap>
+m_NSWSub(const LHS &L, const RHS &R) {
+  return OverflowingBinaryOp_match<LHS, RHS, Instruction::Sub,
+                                   OverflowingBinaryOperator::NoSignedWrap>(
+      L, R);
+}
+template <typename LHS, typename RHS>
+inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Mul,
+                                 OverflowingBinaryOperator::NoSignedWrap>
+m_NSWMul(const LHS &L, const RHS &R) {
+  return OverflowingBinaryOp_match<LHS, RHS, Instruction::Mul,
+                                   OverflowingBinaryOperator::NoSignedWrap>(
+      L, R);
+}
+template <typename LHS, typename RHS>
+inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Shl,
+                                 OverflowingBinaryOperator::NoSignedWrap>
+m_NSWShl(const LHS &L, const RHS &R) {
+  return OverflowingBinaryOp_match<LHS, RHS, Instruction::Shl,
+                                   OverflowingBinaryOperator::NoSignedWrap>(
+      L, R);
+}
+
+template <typename LHS, typename RHS>
+inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Add,
+                                 OverflowingBinaryOperator::NoUnsignedWrap>
+m_NUWAdd(const LHS &L, const RHS &R) {
+  return OverflowingBinaryOp_match<LHS, RHS, Instruction::Add,
+                                   OverflowingBinaryOperator::NoUnsignedWrap>(
+      L, R);
+}
+template <typename LHS, typename RHS>
+inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Sub,
+                                 OverflowingBinaryOperator::NoUnsignedWrap>
+m_NUWSub(const LHS &L, const RHS &R) {
+  return OverflowingBinaryOp_match<LHS, RHS, Instruction::Sub,
+                                   OverflowingBinaryOperator::NoUnsignedWrap>(
+      L, R);
+}
+template <typename LHS, typename RHS>
+inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Mul,
+                                 OverflowingBinaryOperator::NoUnsignedWrap>
+m_NUWMul(const LHS &L, const RHS &R) {
+  return OverflowingBinaryOp_match<LHS, RHS, Instruction::Mul,
+                                   OverflowingBinaryOperator::NoUnsignedWrap>(
+      L, R);
+}
+template <typename LHS, typename RHS>
+inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Shl,
+                                 OverflowingBinaryOperator::NoUnsignedWrap>
+m_NUWShl(const LHS &L, const RHS &R) {
+  return OverflowingBinaryOp_match<LHS, RHS, Instruction::Shl,
+                                   OverflowingBinaryOperator::NoUnsignedWrap>(
+      L, R);
+}
+
 //===----------------------------------------------------------------------===//
 // Class that matches two different binary ops.
 //

Modified: llvm/trunk/unittests/IR/PatternMatch.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/PatternMatch.cpp?rev=198541&r1=198540&r2=198541&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/PatternMatch.cpp (original)
+++ llvm/trunk/unittests/IR/PatternMatch.cpp Sat Jan  4 21:28:29 2014
@@ -201,4 +201,78 @@ TEST_F(PatternMatchTest, FloatingPointUn
   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.





More information about the llvm-commits mailing list