summaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp131
1 files changed, 43 insertions, 88 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 3a8e04303815..99ea04816681 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -19,6 +19,7 @@
#include "llvm/Analysis/CmpInstAnalysis.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/InstructionSimplify.h"
+#include "llvm/Analysis/Loads.h"
#include "llvm/Analysis/Utils/Local.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/IR/ConstantRange.h"
@@ -110,75 +111,41 @@ static bool isSignTest(ICmpInst::Predicate &Pred, const APInt &C) {
/// If AndCst is non-null, then the loaded value is masked with that constant
/// before doing the comparison. This handles cases like "A[i]&4 == 0".
Instruction *InstCombinerImpl::foldCmpLoadFromIndexedGlobal(
- LoadInst *LI, GetElementPtrInst *GEP, GlobalVariable *GV, CmpInst &ICI,
- ConstantInt *AndCst) {
- if (LI->isVolatile() || LI->getType() != GEP->getResultElementType() ||
- !GV->getValueType()->isArrayTy() || !GV->isConstant() ||
+ LoadInst *LI, GetElementPtrInst *GEP, CmpInst &ICI, ConstantInt *AndCst) {
+ auto *GV = dyn_cast<GlobalVariable>(getUnderlyingObject(GEP));
+ if (LI->isVolatile() || !GV || !GV->isConstant() ||
!GV->hasDefinitiveInitializer())
return nullptr;
- Type *GEPSrcEltTy = GEP->getSourceElementType();
- if (GEPSrcEltTy->isArrayTy())
- GEPSrcEltTy = GEPSrcEltTy->getArrayElementType();
- if (GV->getValueType()->getArrayElementType() != GEPSrcEltTy)
+ Type *EltTy = LI->getType();
+ TypeSize EltSize = DL.getTypeStoreSize(EltTy);
+ if (EltSize.isScalable())
return nullptr;
- Constant *Init = GV->getInitializer();
- if (!isa<ConstantArray>(Init) && !isa<ConstantDataArray>(Init))
+ LinearExpression Expr = decomposeLinearExpression(DL, GEP);
+ if (!Expr.Index || Expr.BasePtr != GV || Expr.Offset.getBitWidth() > 64)
return nullptr;
- uint64_t ArrayElementCount = Init->getType()->getArrayNumElements();
- // Don't blow up on huge arrays.
- if (ArrayElementCount > MaxArraySizeForCombine)
- return nullptr;
+ Constant *Init = GV->getInitializer();
+ TypeSize GlobalSize = DL.getTypeAllocSize(Init->getType());
- // There are many forms of this optimization we can handle, for now, just do
- // the simple index into a single-dimensional array or elements of equal size.
- //
- // Require: GEP [n x i8] GV, 0, Idx {{, constant indices}}
- // Or: GEP i8 GV, Idx
+ Value *Idx = Expr.Index;
+ const APInt &Stride = Expr.Scale;
+ const APInt &ConstOffset = Expr.Offset;
- unsigned GEPIdxOp = 1;
- if (GEP->getSourceElementType()->isArrayTy()) {
- GEPIdxOp = 2;
- if (!match(GEP->getOperand(1), m_ZeroInt()))
- return nullptr;
- }
- if (GEP->getNumOperands() < GEPIdxOp + 1 ||
- isa<Constant>(GEP->getOperand(GEPIdxOp)))
+ // Allow an additional context offset, but only within the stride.
+ if (!ConstOffset.ult(Stride))
return nullptr;
- // Check that indices after the variable are constants and in-range for the
- // type they index. Collect the indices. This is typically for arrays of
- // structs.
- SmallVector<unsigned, 4> LaterIndices;
-
- Type *EltTy = Init->getType()->getArrayElementType();
- for (unsigned i = GEPIdxOp + 1, e = GEP->getNumOperands(); i != e; ++i) {
- ConstantInt *Idx = dyn_cast<ConstantInt>(GEP->getOperand(i));
- if (!Idx)
- return nullptr; // Variable index.
-
- uint64_t IdxVal = Idx->getZExtValue();
- if ((unsigned)IdxVal != IdxVal)
- return nullptr; // Too large array index.
-
- if (StructType *STy = dyn_cast<StructType>(EltTy))
- EltTy = STy->getElementType(IdxVal);
- else if (ArrayType *ATy = dyn_cast<ArrayType>(EltTy)) {
- if (IdxVal >= ATy->getNumElements())
- return nullptr;
- EltTy = ATy->getElementType();
- } else {
- return nullptr; // Unknown type.
- }
-
- LaterIndices.push_back(IdxVal);
- }
+ // Don't handle overlapping loads for now.
+ if (!Stride.uge(EltSize.getFixedValue()))
+ return nullptr;
- Value *Idx = GEP->getOperand(GEPIdxOp);
- // If the index type is non-canonical, wait for it to be canonicalized.
- if (Idx->getType() != DL.getIndexType(GEP->getType()))
+ // Don't blow up on huge arrays.
+ uint64_t ArrayElementCount =
+ divideCeil((GlobalSize.getFixedValue() - ConstOffset.getZExtValue()),
+ Stride.getZExtValue());
+ if (ArrayElementCount > MaxArraySizeForCombine)
return nullptr;
enum { Overdefined = -3, Undefined = -2 };
@@ -211,18 +178,12 @@ Instruction *InstCombinerImpl::foldCmpLoadFromIndexedGlobal(
// Scan the array and see if one of our patterns matches.
Constant *CompareRHS = cast<Constant>(ICI.getOperand(1));
- for (unsigned i = 0, e = ArrayElementCount; i != e; ++i) {
- Constant *Elt = Init->getAggregateElement(i);
+ APInt Offset = ConstOffset;
+ for (unsigned i = 0, e = ArrayElementCount; i != e; ++i, Offset += Stride) {
+ Constant *Elt = ConstantFoldLoadFromConst(Init, EltTy, Offset, DL);
if (!Elt)
return nullptr;
- // If this is indexing an array of structures, get the structure element.
- if (!LaterIndices.empty()) {
- Elt = ConstantFoldExtractValueInstruction(Elt, LaterIndices);
- if (!Elt)
- return nullptr;
- }
-
// If the element is masked, handle it.
if (AndCst) {
Elt = ConstantFoldBinaryOpOperands(Instruction::And, Elt, AndCst, DL);
@@ -309,19 +270,17 @@ Instruction *InstCombinerImpl::foldCmpLoadFromIndexedGlobal(
// Now that we've scanned the entire array, emit our new comparison(s). We
// order the state machines in complexity of the generated code.
- // If inbounds keyword is not present, Idx * ElementSize can overflow.
- // Let's assume that ElementSize is 2 and the wanted value is at offset 0.
+ // If inbounds keyword is not present, Idx * Stride can overflow.
+ // Let's assume that Stride is 2 and the wanted value is at offset 0.
// Then, there are two possible values for Idx to match offset 0:
// 0x00..00, 0x80..00.
// Emitting 'icmp eq Idx, 0' isn't correct in this case because the
// comparison is false if Idx was 0x80..00.
// We need to erase the highest countTrailingZeros(ElementSize) bits of Idx.
- unsigned ElementSize =
- DL.getTypeAllocSize(Init->getType()->getArrayElementType());
auto MaskIdx = [&](Value *Idx) {
- if (!GEP->isInBounds() && llvm::countr_zero(ElementSize) != 0) {
+ if (!Expr.Flags.isInBounds() && Stride.countr_zero() != 0) {
Value *Mask = Constant::getAllOnesValue(Idx->getType());
- Mask = Builder.CreateLShr(Mask, llvm::countr_zero(ElementSize));
+ Mask = Builder.CreateLShr(Mask, Stride.countr_zero());
Idx = Builder.CreateAnd(Idx, Mask);
}
return Idx;
@@ -1997,10 +1956,8 @@ Instruction *InstCombinerImpl::foldICmpAndConstant(ICmpInst &Cmp,
if (auto *C2 = dyn_cast<ConstantInt>(Y))
if (auto *LI = dyn_cast<LoadInst>(X))
if (auto *GEP = dyn_cast<GetElementPtrInst>(LI->getOperand(0)))
- if (auto *GV = dyn_cast<GlobalVariable>(GEP->getOperand(0)))
- if (Instruction *Res =
- foldCmpLoadFromIndexedGlobal(LI, GEP, GV, Cmp, C2))
- return Res;
+ if (Instruction *Res = foldCmpLoadFromIndexedGlobal(LI, GEP, Cmp, C2))
+ return Res;
if (!Cmp.isEquality())
return nullptr;
@@ -4353,10 +4310,9 @@ Instruction *InstCombinerImpl::foldICmpInstWithConstantNotInt(ICmpInst &I) {
// Try to optimize things like "A[i] > 4" to index computations.
if (GetElementPtrInst *GEP =
dyn_cast<GetElementPtrInst>(LHSI->getOperand(0)))
- if (GlobalVariable *GV = dyn_cast<GlobalVariable>(GEP->getOperand(0)))
- if (Instruction *Res =
- foldCmpLoadFromIndexedGlobal(cast<LoadInst>(LHSI), GEP, GV, I))
- return Res;
+ if (Instruction *Res =
+ foldCmpLoadFromIndexedGlobal(cast<LoadInst>(LHSI), GEP, I))
+ return Res;
break;
}
@@ -6375,7 +6331,7 @@ Instruction *InstCombinerImpl::foldICmpWithZextOrSext(ICmpInst &ICmp) {
// If a lossless truncate is possible...
Type *SrcTy = CastOp0->getSrcTy();
- Constant *Res = getLosslessTrunc(C, SrcTy, CastOp0->getOpcode());
+ Constant *Res = getLosslessInvCast(C, SrcTy, CastOp0->getOpcode(), DL);
if (Res) {
if (ICmp.isEquality())
return new ICmpInst(ICmp.getPredicate(), X, Res);
@@ -8837,10 +8793,9 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) {
break;
case Instruction::Load:
if (auto *GEP = dyn_cast<GetElementPtrInst>(LHSI->getOperand(0)))
- if (auto *GV = dyn_cast<GlobalVariable>(GEP->getOperand(0)))
- if (Instruction *Res = foldCmpLoadFromIndexedGlobal(
- cast<LoadInst>(LHSI), GEP, GV, I))
- return Res;
+ if (Instruction *Res =
+ foldCmpLoadFromIndexedGlobal(cast<LoadInst>(LHSI), GEP, I))
+ return Res;
break;
case Instruction::FPTrunc:
if (Instruction *NV = foldFCmpFpTrunc(I, *LHSI, *RHSC))
@@ -8944,14 +8899,14 @@ Instruction *InstCombinerImpl::visitFCmpInst(FCmpInst &I) {
}
{
- Value *CanonLHS = nullptr, *CanonRHS = nullptr;
+ Value *CanonLHS = nullptr;
match(Op0, m_Intrinsic<Intrinsic::canonicalize>(m_Value(CanonLHS)));
- match(Op1, m_Intrinsic<Intrinsic::canonicalize>(m_Value(CanonRHS)));
-
// (canonicalize(x) == x) => (x == x)
if (CanonLHS == Op1)
return new FCmpInst(Pred, Op1, Op1, "", &I);
+ Value *CanonRHS = nullptr;
+ match(Op1, m_Intrinsic<Intrinsic::canonicalize>(m_Value(CanonRHS)));
// (x == canonicalize(x)) => (x == x)
if (CanonRHS == Op0)
return new FCmpInst(Pred, Op0, Op0, "", &I);