From 9e36975287f1bb9a571570b9af578ebcd69c2c72 Mon Sep 17 00:00:00 2001 From: Sanjoy Das Date: Thu, 23 Feb 2017 22:50:52 +0000 Subject: [PATCH] [IR] Add a Instruction::dropPoisonGeneratingFlags helper Summary: The helper will be used in a later change. This change itself is NFC since the only user of this new function is its unit test. Reviewers: majnemer, efriedma Reviewed By: efriedma Subscribers: efriedma, mcrosier, llvm-commits Differential Revision: https://reviews.llvm.org/D30184 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296035 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/Instruction.h | 4 ++ lib/IR/Instruction.cpp | 23 ++++++++++++ unittests/IR/InstructionsTest.cpp | 61 +++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index fd7c54d69b6..9978730a8c6 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -276,6 +276,10 @@ public: /// Determine whether the no signed wrap flag is set. bool hasNoSignedWrap() const; + /// Drops flags that may cause this instruction to evaluate to poison despite + /// having non-poison inputs. + void dropPoisonGeneratingFlags(); + /// Determine whether the exact flag is set. bool isExact() const; diff --git a/lib/IR/Instruction.cpp b/lib/IR/Instruction.cpp index 2fa03489081..516cdbe3416 100644 --- a/lib/IR/Instruction.cpp +++ b/lib/IR/Instruction.cpp @@ -122,6 +122,29 @@ bool Instruction::hasNoSignedWrap() const { return cast(this)->hasNoSignedWrap(); } +void Instruction::dropPoisonGeneratingFlags() { + switch (getOpcode()) { + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + case Instruction::Shl: + cast(this)->setHasNoUnsignedWrap(false); + cast(this)->setHasNoSignedWrap(false); + break; + + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::AShr: + case Instruction::LShr: + cast(this)->setIsExact(false); + break; + + case Instruction::GetElementPtr: + cast(this)->setIsInBounds(false); + break; + } +} + bool Instruction::isExact() const { return cast(this)->isExact(); } diff --git a/unittests/IR/InstructionsTest.cpp b/unittests/IR/InstructionsTest.cpp index 0dac7c1bcfb..dd599ed74ce 100644 --- a/unittests/IR/InstructionsTest.cpp +++ b/unittests/IR/InstructionsTest.cpp @@ -19,6 +19,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Module.h" +#include "llvm/IR/NoFolder.h" #include "llvm/IR/Operator.h" #include "gtest/gtest.h" #include @@ -579,5 +580,65 @@ TEST(InstructionsTest, AlterInvokeBundles) { EXPECT_TRUE(Clone->getOperandBundle("after").hasValue()); } +TEST_F(ModuleWithFunctionTest, DropPoisonGeneratingFlags) { + auto *OnlyBB = BasicBlock::Create(Ctx, "bb", F); + auto *Arg0 = &*F->arg_begin(); + + IRBuilder B(Ctx); + B.SetInsertPoint(OnlyBB); + + { + auto *UI = + cast(B.CreateUDiv(Arg0, Arg0, "", /*isExact*/ true)); + ASSERT_TRUE(UI->isExact()); + UI->dropPoisonGeneratingFlags(); + ASSERT_FALSE(UI->isExact()); + } + + { + auto *ShrI = + cast(B.CreateLShr(Arg0, Arg0, "", /*isExact*/ true)); + ASSERT_TRUE(ShrI->isExact()); + ShrI->dropPoisonGeneratingFlags(); + ASSERT_FALSE(ShrI->isExact()); + } + + { + auto *AI = cast( + B.CreateAdd(Arg0, Arg0, "", /*HasNUW*/ true, /*HasNSW*/ false)); + ASSERT_TRUE(AI->hasNoUnsignedWrap()); + AI->dropPoisonGeneratingFlags(); + ASSERT_FALSE(AI->hasNoUnsignedWrap()); + ASSERT_FALSE(AI->hasNoSignedWrap()); + } + + { + auto *SI = cast( + B.CreateAdd(Arg0, Arg0, "", /*HasNUW*/ false, /*HasNSW*/ true)); + ASSERT_TRUE(SI->hasNoSignedWrap()); + SI->dropPoisonGeneratingFlags(); + ASSERT_FALSE(SI->hasNoUnsignedWrap()); + ASSERT_FALSE(SI->hasNoSignedWrap()); + } + + { + auto *ShlI = cast( + B.CreateShl(Arg0, Arg0, "", /*HasNUW*/ true, /*HasNSW*/ true)); + ASSERT_TRUE(ShlI->hasNoSignedWrap()); + ASSERT_TRUE(ShlI->hasNoUnsignedWrap()); + ShlI->dropPoisonGeneratingFlags(); + ASSERT_FALSE(ShlI->hasNoUnsignedWrap()); + ASSERT_FALSE(ShlI->hasNoSignedWrap()); + } + + { + Value *GEPBase = Constant::getNullValue(B.getInt8PtrTy()); + auto *GI = cast(B.CreateInBoundsGEP(GEPBase, {Arg0})); + ASSERT_TRUE(GI->isInBounds()); + GI->dropPoisonGeneratingFlags(); + ASSERT_FALSE(GI->isInBounds()); + } +} + } // end anonymous namespace } // end namespace llvm -- 2.50.1