aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/InstCombine/InstCombinePHI.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/InstCombine/InstCombinePHI.cpp')
-rw-r--r--lib/Transforms/InstCombine/InstCombinePHI.cpp101
1 files changed, 55 insertions, 46 deletions
diff --git a/lib/Transforms/InstCombine/InstCombinePHI.cpp b/lib/Transforms/InstCombine/InstCombinePHI.cpp
index f1aa98b5e359..79a4912332ff 100644
--- a/lib/Transforms/InstCombine/InstCombinePHI.cpp
+++ b/lib/Transforms/InstCombine/InstCombinePHI.cpp
@@ -15,8 +15,11 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/InstructionSimplify.h"
+#include "llvm/Analysis/ValueTracking.h"
+#include "llvm/IR/PatternMatch.h"
#include "llvm/Transforms/Utils/Local.h"
using namespace llvm;
+using namespace llvm::PatternMatch;
#define DEBUG_TYPE "instcombine"
@@ -32,15 +35,6 @@ Instruction *InstCombiner::FoldPHIArgBinOpIntoPHI(PHINode &PN) {
Type *LHSType = LHSVal->getType();
Type *RHSType = RHSVal->getType();
- bool isNUW = false, isNSW = false, isExact = false;
- if (OverflowingBinaryOperator *BO =
- dyn_cast<OverflowingBinaryOperator>(FirstInst)) {
- isNUW = BO->hasNoUnsignedWrap();
- isNSW = BO->hasNoSignedWrap();
- } else if (PossiblyExactOperator *PEO =
- dyn_cast<PossiblyExactOperator>(FirstInst))
- isExact = PEO->isExact();
-
// Scan to see if all operands are the same opcode, and all have one use.
for (unsigned i = 1; i != PN.getNumIncomingValues(); ++i) {
Instruction *I = dyn_cast<Instruction>(PN.getIncomingValue(i));
@@ -56,13 +50,6 @@ Instruction *InstCombiner::FoldPHIArgBinOpIntoPHI(PHINode &PN) {
if (CI->getPredicate() != cast<CmpInst>(FirstInst)->getPredicate())
return nullptr;
- if (isNUW)
- isNUW = cast<OverflowingBinaryOperator>(I)->hasNoUnsignedWrap();
- if (isNSW)
- isNSW = cast<OverflowingBinaryOperator>(I)->hasNoSignedWrap();
- if (isExact)
- isExact = cast<PossiblyExactOperator>(I)->isExact();
-
// Keep track of which operand needs a phi node.
if (I->getOperand(0) != LHSVal) LHSVal = nullptr;
if (I->getOperand(1) != RHSVal) RHSVal = nullptr;
@@ -121,9 +108,12 @@ Instruction *InstCombiner::FoldPHIArgBinOpIntoPHI(PHINode &PN) {
BinaryOperator *BinOp = cast<BinaryOperator>(FirstInst);
BinaryOperator *NewBinOp =
BinaryOperator::Create(BinOp->getOpcode(), LHSVal, RHSVal);
- if (isNUW) NewBinOp->setHasNoUnsignedWrap();
- if (isNSW) NewBinOp->setHasNoSignedWrap();
- if (isExact) NewBinOp->setIsExact();
+
+ NewBinOp->copyIRFlags(PN.getIncomingValue(0));
+
+ for (unsigned i = 1, e = PN.getNumIncomingValues(); i != e; ++i)
+ NewBinOp->andIRFlags(PN.getIncomingValue(i));
+
NewBinOp->setDebugLoc(FirstInst->getDebugLoc());
return NewBinOp;
}
@@ -494,7 +484,6 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
// code size and simplifying code.
Constant *ConstantOp = nullptr;
Type *CastSrcTy = nullptr;
- bool isNUW = false, isNSW = false, isExact = false;
if (isa<CastInst>(FirstInst)) {
CastSrcTy = FirstInst->getOperand(0)->getType();
@@ -511,14 +500,6 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
ConstantOp = dyn_cast<Constant>(FirstInst->getOperand(1));
if (!ConstantOp)
return FoldPHIArgBinOpIntoPHI(PN);
-
- if (OverflowingBinaryOperator *BO =
- dyn_cast<OverflowingBinaryOperator>(FirstInst)) {
- isNUW = BO->hasNoUnsignedWrap();
- isNSW = BO->hasNoSignedWrap();
- } else if (PossiblyExactOperator *PEO =
- dyn_cast<PossiblyExactOperator>(FirstInst))
- isExact = PEO->isExact();
} else {
return nullptr; // Cannot fold this operation.
}
@@ -534,13 +515,6 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
} else if (I->getOperand(1) != ConstantOp) {
return nullptr;
}
-
- if (isNUW)
- isNUW = cast<OverflowingBinaryOperator>(I)->hasNoUnsignedWrap();
- if (isNSW)
- isNSW = cast<OverflowingBinaryOperator>(I)->hasNoSignedWrap();
- if (isExact)
- isExact = cast<PossiblyExactOperator>(I)->isExact();
}
// Okay, they are all the same operation. Create a new PHI node of the
@@ -581,9 +555,11 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(FirstInst)) {
BinOp = BinaryOperator::Create(BinOp->getOpcode(), PhiVal, ConstantOp);
- if (isNUW) BinOp->setHasNoUnsignedWrap();
- if (isNSW) BinOp->setHasNoSignedWrap();
- if (isExact) BinOp->setIsExact();
+ BinOp->copyIRFlags(PN.getIncomingValue(0));
+
+ for (unsigned i = 1, e = PN.getNumIncomingValues(); i != e; ++i)
+ BinOp->andIRFlags(PN.getIncomingValue(i));
+
BinOp->setDebugLoc(FirstInst->getDebugLoc());
return BinOp;
}
@@ -641,6 +617,16 @@ static bool PHIsEqualValue(PHINode *PN, Value *NonPhiInVal,
return true;
}
+/// Return an existing non-zero constant if this phi node has one, otherwise
+/// return constant 1.
+static ConstantInt *GetAnyNonZeroConstInt(PHINode &PN) {
+ assert(isa<IntegerType>(PN.getType()) && "Expect only intger type phi");
+ for (Value *V : PN.operands())
+ if (auto *ConstVA = dyn_cast<ConstantInt>(V))
+ if (!ConstVA->isZeroValue())
+ return ConstVA;
+ return ConstantInt::get(cast<IntegerType>(PN.getType()), 1);
+}
namespace {
struct PHIUsageRecord {
@@ -768,7 +754,7 @@ Instruction *InstCombiner::SliceUpIllegalIntegerPHI(PHINode &FirstPhi) {
// If we have no users, they must be all self uses, just nuke the PHI.
if (PHIUsers.empty())
- return ReplaceInstUsesWith(FirstPhi, UndefValue::get(FirstPhi.getType()));
+ return replaceInstUsesWith(FirstPhi, UndefValue::get(FirstPhi.getType()));
// If this phi node is transformable, create new PHIs for all the pieces
// extracted out of it. First, sort the users by their offset and size.
@@ -864,22 +850,22 @@ Instruction *InstCombiner::SliceUpIllegalIntegerPHI(PHINode &FirstPhi) {
}
// Replace the use of this piece with the PHI node.
- ReplaceInstUsesWith(*PHIUsers[UserI].Inst, EltPHI);
+ replaceInstUsesWith(*PHIUsers[UserI].Inst, EltPHI);
}
// Replace all the remaining uses of the PHI nodes (self uses and the lshrs)
// with undefs.
Value *Undef = UndefValue::get(FirstPhi.getType());
for (unsigned i = 1, e = PHIsToSlice.size(); i != e; ++i)
- ReplaceInstUsesWith(*PHIsToSlice[i], Undef);
- return ReplaceInstUsesWith(FirstPhi, Undef);
+ replaceInstUsesWith(*PHIsToSlice[i], Undef);
+ return replaceInstUsesWith(FirstPhi, Undef);
}
// PHINode simplification
//
Instruction *InstCombiner::visitPHINode(PHINode &PN) {
if (Value *V = SimplifyInstruction(&PN, DL, TLI, DT, AC))
- return ReplaceInstUsesWith(PN, V);
+ return replaceInstUsesWith(PN, V);
if (Instruction *Result = FoldPHIArgZextsIntoPHI(PN))
return Result;
@@ -905,7 +891,7 @@ Instruction *InstCombiner::visitPHINode(PHINode &PN) {
SmallPtrSet<PHINode*, 16> PotentiallyDeadPHIs;
PotentiallyDeadPHIs.insert(&PN);
if (DeadPHICycle(PU, PotentiallyDeadPHIs))
- return ReplaceInstUsesWith(PN, UndefValue::get(PN.getType()));
+ return replaceInstUsesWith(PN, UndefValue::get(PN.getType()));
}
// If this phi has a single use, and if that use just computes a value for
@@ -917,7 +903,30 @@ Instruction *InstCombiner::visitPHINode(PHINode &PN) {
if (PHIUser->hasOneUse() &&
(isa<BinaryOperator>(PHIUser) || isa<GetElementPtrInst>(PHIUser)) &&
PHIUser->user_back() == &PN) {
- return ReplaceInstUsesWith(PN, UndefValue::get(PN.getType()));
+ return replaceInstUsesWith(PN, UndefValue::get(PN.getType()));
+ }
+ // When a PHI is used only to be compared with zero, it is safe to replace
+ // an incoming value proved as known nonzero with any non-zero constant.
+ // For example, in the code below, the incoming value %v can be replaced
+ // with any non-zero constant based on the fact that the PHI is only used to
+ // be compared with zero and %v is a known non-zero value:
+ // %v = select %cond, 1, 2
+ // %p = phi [%v, BB] ...
+ // icmp eq, %p, 0
+ auto *CmpInst = dyn_cast<ICmpInst>(PHIUser);
+ // FIXME: To be simple, handle only integer type for now.
+ if (CmpInst && isa<IntegerType>(PN.getType()) && CmpInst->isEquality() &&
+ match(CmpInst->getOperand(1), m_Zero())) {
+ ConstantInt *NonZeroConst = nullptr;
+ for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) {
+ Instruction *CtxI = PN.getIncomingBlock(i)->getTerminator();
+ Value *VA = PN.getIncomingValue(i);
+ if (isKnownNonZero(VA, DL, 0, AC, CtxI, DT)) {
+ if (!NonZeroConst)
+ NonZeroConst = GetAnyNonZeroConstInt(PN);
+ PN.setIncomingValue(i, NonZeroConst);
+ }
+ }
}
}
@@ -951,7 +960,7 @@ Instruction *InstCombiner::visitPHINode(PHINode &PN) {
if (InValNo == NumIncomingVals) {
SmallPtrSet<PHINode*, 16> ValueEqualPHIs;
if (PHIsEqualValue(&PN, NonPhiInVal, ValueEqualPHIs))
- return ReplaceInstUsesWith(PN, NonPhiInVal);
+ return replaceInstUsesWith(PN, NonPhiInVal);
}
}
}