forked from OSchip/llvm-project
Fix a bug in IRBuilder that's been there for who knows how long. It
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. llvm-svn: 198538
This commit is contained in:
parent
4002a941fa
commit
0db10c4fef
|
@ -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))
|
||||
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);
|
||||
}
|
||||
|
@ -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))
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#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;
|
||||
|
@ -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());
|
||||
|
|
Loading…
Reference in New Issue