1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[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

llvm-svn: 296035
This commit is contained in:
Sanjoy Das 2017-02-23 22:50:52 +00:00
parent 828acceeb5
commit c1d9ef40b5
3 changed files with 88 additions and 0 deletions

View File

@ -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;

View File

@ -122,6 +122,29 @@ bool Instruction::hasNoSignedWrap() const {
return cast<OverflowingBinaryOperator>(this)->hasNoSignedWrap();
}
void Instruction::dropPoisonGeneratingFlags() {
switch (getOpcode()) {
case Instruction::Add:
case Instruction::Sub:
case Instruction::Mul:
case Instruction::Shl:
cast<OverflowingBinaryOperator>(this)->setHasNoUnsignedWrap(false);
cast<OverflowingBinaryOperator>(this)->setHasNoSignedWrap(false);
break;
case Instruction::UDiv:
case Instruction::SDiv:
case Instruction::AShr:
case Instruction::LShr:
cast<PossiblyExactOperator>(this)->setIsExact(false);
break;
case Instruction::GetElementPtr:
cast<GetElementPtrInst>(this)->setIsInBounds(false);
break;
}
}
bool Instruction::isExact() const {
return cast<PossiblyExactOperator>(this)->isExact();
}

View File

@ -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 <memory>
@ -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<NoFolder> B(Ctx);
B.SetInsertPoint(OnlyBB);
{
auto *UI =
cast<Instruction>(B.CreateUDiv(Arg0, Arg0, "", /*isExact*/ true));
ASSERT_TRUE(UI->isExact());
UI->dropPoisonGeneratingFlags();
ASSERT_FALSE(UI->isExact());
}
{
auto *ShrI =
cast<Instruction>(B.CreateLShr(Arg0, Arg0, "", /*isExact*/ true));
ASSERT_TRUE(ShrI->isExact());
ShrI->dropPoisonGeneratingFlags();
ASSERT_FALSE(ShrI->isExact());
}
{
auto *AI = cast<Instruction>(
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<Instruction>(
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<Instruction>(
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<GetElementPtrInst>(B.CreateInBoundsGEP(GEPBase, {Arg0}));
ASSERT_TRUE(GI->isInBounds());
GI->dropPoisonGeneratingFlags();
ASSERT_FALSE(GI->isInBounds());
}
}
} // end anonymous namespace
} // end namespace llvm