Add support to the pattern match library for matching NSW and NUW
authorChandler Carruth <chandlerc@gmail.com>
Sun, 5 Jan 2014 03:28:29 +0000 (03:28 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Sun, 5 Jan 2014 03:28:29 +0000 (03:28 +0000)
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!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198541 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Support/PatternMatch.h
unittests/IR/PatternMatch.cpp

index 240bb81d31a797fb8796aa7922bc969b7107c63e..97739b08694d7ad6cc58b058f22eca8c0df423ce 100644 (file)
@@ -498,6 +498,96 @@ m_AShr(const LHS &L, const RHS &R) {
   return BinaryOp_match<LHS, RHS, Instruction::AShr>(L, 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.
 //
 //===----------------------------------------------------------------------===//
 // Class that matches two different binary ops.
 //
index b593648bb32a598879f7d6c96146219aea63129b..150f1657b9c21dbd0281bec539ad575bd191645c 100644 (file)
@@ -201,4 +201,78 @@ TEST_F(PatternMatchTest, FloatingPointUnorderedMax) {
   EXPECT_EQ(R, MatchR);
 }
 
   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.
 } // anonymous namespace.