Fix a bug in IRBuilder that's been there for who knows how long. It
authorChandler Carruth <chandlerc@gmail.com>
Sun, 5 Jan 2014 03:22:33 +0000 (03:22 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Sun, 5 Jan 2014 03:22:33 +0000 (03:22 +0000)
failed to correctly propagate the NUW and NSW flags to the constant
folder for two instructions. I've added a unittest to cover flag
propagation for the rest of the instructions and constant expressions.

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

include/llvm/IR/IRBuilder.h
unittests/IR/IRBuilderTest.cpp

index c9c11be89d630b7a11a516e121c8eb573b200ced..617f40de8f552019c74173b212d1f3e035630320 100644 (file)
@@ -638,7 +638,7 @@ public:
                    bool HasNUW = false, bool HasNSW = false) {
     if (Constant *LC = dyn_cast<Constant>(LHS))
       if (Constant *RC = dyn_cast<Constant>(RHS))
                    bool HasNUW = false, bool HasNSW = false) {
     if (Constant *LC = dyn_cast<Constant>(LHS))
       if (Constant *RC = dyn_cast<Constant>(RHS))
-        return Insert(Folder.CreateSub(LC, RC), Name);
+        return Insert(Folder.CreateSub(LC, RC, HasNUW, HasNSW), Name);
     return CreateInsertNUWNSWBinOp(Instruction::Sub, LHS, RHS, Name,
                                    HasNUW, HasNSW);
   }
     return CreateInsertNUWNSWBinOp(Instruction::Sub, LHS, RHS, Name,
                                    HasNUW, HasNSW);
   }
@@ -660,7 +660,7 @@ public:
                    bool HasNUW = false, bool HasNSW = false) {
     if (Constant *LC = dyn_cast<Constant>(LHS))
       if (Constant *RC = dyn_cast<Constant>(RHS))
                    bool HasNUW = false, bool HasNSW = false) {
     if (Constant *LC = dyn_cast<Constant>(LHS))
       if (Constant *RC = dyn_cast<Constant>(RHS))
-        return Insert(Folder.CreateMul(LC, RC), Name);
+        return Insert(Folder.CreateMul(LC, RC, HasNUW, HasNSW), Name);
     return CreateInsertNUWNSWBinOp(Instruction::Mul, LHS, RHS, Name,
                                    HasNUW, HasNSW);
   }
     return CreateInsertNUWNSWBinOp(Instruction::Mul, LHS, RHS, Name,
                                    HasNUW, HasNSW);
   }
index fcb567790734e5a570fbbc221043b09dbbb2d9a7..a0a72e82ed8ad72ceb675abda10535451c279195 100644 (file)
@@ -16,6 +16,7 @@
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Support/NoFolder.h"
 #include "gtest/gtest.h"
 
 using namespace llvm;
 #include "gtest/gtest.h"
 
 using namespace llvm;
@@ -190,6 +191,56 @@ TEST_F(IRBuilderTest, FastMathFlags) {
 
 }
 
 
 }
 
+TEST_F(IRBuilderTest, WrapFlags) {
+  IRBuilder<true, NoFolder> Builder(BB);
+
+  // Test instructions.
+  GlobalVariable *G = new GlobalVariable(*M, Builder.getInt32Ty(), true,
+                                         GlobalValue::ExternalLinkage, 0);
+  Value *V = Builder.CreateLoad(G);
+  EXPECT_TRUE(
+      cast<BinaryOperator>(Builder.CreateNSWAdd(V, V))->hasNoSignedWrap());
+  EXPECT_TRUE(
+      cast<BinaryOperator>(Builder.CreateNSWMul(V, V))->hasNoSignedWrap());
+  EXPECT_TRUE(
+      cast<BinaryOperator>(Builder.CreateNSWSub(V, V))->hasNoSignedWrap());
+  EXPECT_TRUE(cast<BinaryOperator>(
+                  Builder.CreateShl(V, V, "", /* NUW */ false, /* NSW */ true))
+                  ->hasNoSignedWrap());
+
+  EXPECT_TRUE(
+      cast<BinaryOperator>(Builder.CreateNUWAdd(V, V))->hasNoUnsignedWrap());
+  EXPECT_TRUE(
+      cast<BinaryOperator>(Builder.CreateNUWMul(V, V))->hasNoUnsignedWrap());
+  EXPECT_TRUE(
+      cast<BinaryOperator>(Builder.CreateNUWSub(V, V))->hasNoUnsignedWrap());
+  EXPECT_TRUE(cast<BinaryOperator>(
+                  Builder.CreateShl(V, V, "", /* NUW */ true, /* NSW */ false))
+                  ->hasNoUnsignedWrap());
+
+  // Test operators created with constants.
+  Constant *C = Builder.getInt32(42);
+  EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWAdd(C, C))
+                  ->hasNoSignedWrap());
+  EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWSub(C, C))
+                  ->hasNoSignedWrap());
+  EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWMul(C, C))
+                  ->hasNoSignedWrap());
+  EXPECT_TRUE(cast<OverflowingBinaryOperator>(
+                  Builder.CreateShl(C, C, "", /* NUW */ false, /* NSW */ true))
+                  ->hasNoSignedWrap());
+
+  EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWAdd(C, C))
+                  ->hasNoUnsignedWrap());
+  EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWSub(C, C))
+                  ->hasNoUnsignedWrap());
+  EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWMul(C, C))
+                  ->hasNoUnsignedWrap());
+  EXPECT_TRUE(cast<OverflowingBinaryOperator>(
+                  Builder.CreateShl(C, C, "", /* NUW */ true, /* NSW */ false))
+                  ->hasNoUnsignedWrap());
+}
+
 TEST_F(IRBuilderTest, RAIIHelpersTest) {
   IRBuilder<> Builder(BB);
   EXPECT_FALSE(Builder.getFastMathFlags().allowReciprocal());
 TEST_F(IRBuilderTest, RAIIHelpersTest) {
   IRBuilder<> Builder(BB);
   EXPECT_FALSE(Builder.getFastMathFlags().allowReciprocal());