Skip to content

Commit

Permalink
[ConstnatFolding] Teach the folder how to fold ConstantVector
Browse files Browse the repository at this point in the history
A ConstantVector can have ConstantExpr operands and vice versa.
However, the folder had no ability to fold ConstantVectors which, in
some cases, was an optimization barrier.

Instead, rephrase the folder in terms of Constants instead of
ConstantExprs and teach callers how to deal with failure.

llvm-svn: 277099
  • Loading branch information
majnemer committed Jul 29, 2016
1 parent c7de3a1 commit d536f23
Show file tree
Hide file tree
Showing 13 changed files with 114 additions and 109 deletions.
11 changes: 6 additions & 5 deletions llvm/include/llvm/Analysis/ConstantFolding.h
Expand Up @@ -25,6 +25,7 @@ class APInt;
template <typename T> class ArrayRef;
class Constant;
class ConstantExpr;
class ConstantVector;
class DataLayout;
class Function;
class GlobalValue;
Expand All @@ -45,11 +46,11 @@ bool IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV, APInt &Offset,
Constant *ConstantFoldInstruction(Instruction *I, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr);

/// ConstantFoldConstantExpression - Attempt to fold the constant expression
/// using the specified DataLayout. If successful, the constant result is
/// result is returned, if not, null is returned.
Constant *
ConstantFoldConstantExpression(const ConstantExpr *CE, const DataLayout &DL,
/// ConstantFoldConstant - Attempt to fold the constant using the
/// specified DataLayout.
/// If successful, the constant result is result is returned, if not,
/// null is returned.
Constant *ConstantFoldConstant(const Constant *C, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr);

/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the
Expand Down
5 changes: 2 additions & 3 deletions llvm/include/llvm/Analysis/TargetFolder.h
Expand Up @@ -34,9 +34,8 @@ class TargetFolder {

/// Fold - Fold the constant using target specific information.
Constant *Fold(Constant *C) const {
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
if (Constant *CF = ConstantFoldConstantExpression(CE, DL))
return CF;
if (Constant *CF = ConstantFoldConstant(C, DL))
return CF;
return C;
}

Expand Down
117 changes: 60 additions & 57 deletions llvm/lib/Analysis/ConstantFolding.cpp
Expand Up @@ -714,10 +714,8 @@ Constant *CastGEPIndices(Type *SrcElemTy, ArrayRef<Constant *> Ops,
return nullptr;

Constant *C = ConstantExpr::getGetElementPtr(SrcElemTy, Ops[0], NewIdxs);
if (auto *CE = dyn_cast<ConstantExpr>(C)) {
if (Constant *Folded = ConstantFoldConstantExpression(CE, DL, TLI))
C = Folded;
}
if (Constant *Folded = ConstantFoldConstant(C, DL, TLI))
C = Folded;

return C;
}
Expand Down Expand Up @@ -775,10 +773,8 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
Constant *Res = ConstantExpr::getPtrToInt(Ptr, CE->getType());
Res = ConstantExpr::getSub(Res, CE->getOperand(1));
Res = ConstantExpr::getIntToPtr(Res, ResTy);
if (auto *ResCE = dyn_cast<ConstantExpr>(Res))
if (auto *FoldedRes =
ConstantFoldConstantExpression(ResCE, DL, TLI))
Res = FoldedRes;
if (auto *FoldedRes = ConstantFoldConstant(Res, DL, TLI))
Res = FoldedRes;
return Res;
}
}
Expand Down Expand Up @@ -968,12 +964,59 @@ Constant *ConstantFoldInstOperandsImpl(const Value *InstOrCE, Type *DestTy,
// Constant Folding public APIs
//===----------------------------------------------------------------------===//

namespace {

Constant *
ConstantFoldConstantImpl(const Constant *C, const DataLayout &DL,
const TargetLibraryInfo *TLI,
SmallDenseMap<Constant *, Constant *> &FoldedOps) {
if (!isa<ConstantVector>(C) && !isa<ConstantExpr>(C))
return nullptr;

SmallVector<Constant *, 8> Ops;
for (const Use &NewU : C->operands()) {
auto *NewC = cast<Constant>(&NewU);
// Recursively fold the ConstantExpr's operands. If we have already folded
// a ConstantExpr, we don't have to process it again.
if (isa<ConstantVector>(NewC) || isa<ConstantExpr>(NewC)) {
auto It = FoldedOps.find(NewC);
if (It == FoldedOps.end()) {
if (auto *FoldedC =
ConstantFoldConstantImpl(NewC, DL, TLI, FoldedOps)) {
NewC = FoldedC;
FoldedOps.insert({NewC, FoldedC});
} else {
FoldedOps.insert({NewC, NewC});
}
} else {
NewC = It->second;
}
}
Ops.push_back(NewC);
}

if (auto *CE = dyn_cast<ConstantExpr>(C)) {
if (CE->isCompare())
return ConstantFoldCompareInstOperands(CE->getPredicate(), Ops[0], Ops[1],
DL, TLI);

return ConstantFoldInstOperandsImpl(CE, CE->getType(), CE->getOpcode(), Ops,
DL, TLI);
}

assert(isa<ConstantVector>(C));
return ConstantVector::get(Ops);
}

} // end anonymous namespace

Constant *llvm::ConstantFoldInstruction(Instruction *I, const DataLayout &DL,
const TargetLibraryInfo *TLI) {
// Handle PHI nodes quickly here...
if (auto *PN = dyn_cast<PHINode>(I)) {
Constant *CommonValue = nullptr;

SmallDenseMap<Constant *, Constant *> FoldedOps;
for (Value *Incoming : PN->incoming_values()) {
// If the incoming value is undef then skip it. Note that while we could
// skip the value if it is equal to the phi node itself we choose not to
Expand All @@ -986,17 +1029,15 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const DataLayout &DL,
if (!C)
return nullptr;
// Fold the PHI's operands.
if (auto *NewC = dyn_cast<ConstantExpr>(C))
if (auto *FoldedC = ConstantFoldConstantExpression(NewC, DL, TLI))
C = FoldedC;
if (auto *FoldedC = ConstantFoldConstantImpl(C, DL, TLI, FoldedOps))
C = FoldedC;
// If the incoming value is a different constant to
// the one we saw previously, then give up.
if (CommonValue && C != CommonValue)
return nullptr;
CommonValue = C;
}


// If we reach here, all incoming values are the same constant or undef.
return CommonValue ? CommonValue : UndefValue::get(PN->getType());
}
Expand All @@ -1006,13 +1047,13 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const DataLayout &DL,
if (!all_of(I->operands(), [](Use &U) { return isa<Constant>(U); }))
return nullptr;

SmallDenseMap<Constant *, Constant *> FoldedOps;
SmallVector<Constant *, 8> Ops;
for (const Use &OpU : I->operands()) {
auto *Op = cast<Constant>(&OpU);
// Fold the Instruction's operands.
if (auto *NewCE = dyn_cast<ConstantExpr>(Op))
if (auto *FoldedOp = ConstantFoldConstantExpression(NewCE, DL, TLI))
Op = FoldedOp;
if (auto *FoldedOp = ConstantFoldConstantImpl(Op, DL, TLI, FoldedOps))
Op = FoldedOp;

Ops.push_back(Op);
}
Expand Down Expand Up @@ -1040,48 +1081,10 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const DataLayout &DL,
return ConstantFoldInstOperands(I, Ops, DL, TLI);
}

namespace {

Constant *ConstantFoldConstantExpressionImpl(
const ConstantExpr *CE, const DataLayout &DL, const TargetLibraryInfo *TLI,
SmallDenseMap<ConstantExpr *, Constant *> &FoldedOps) {
SmallVector<Constant *, 8> Ops;
for (const Use &NewU : CE->operands()) {
auto *NewC = cast<Constant>(&NewU);
// Recursively fold the ConstantExpr's operands. If we have already folded
// a ConstantExpr, we don't have to process it again.
if (auto *NewCE = dyn_cast<ConstantExpr>(NewC)) {
auto It = FoldedOps.find(NewCE);
if (It == FoldedOps.end()) {
if (auto *FoldedC =
ConstantFoldConstantExpressionImpl(NewCE, DL, TLI, FoldedOps)) {
NewC = FoldedC;
FoldedOps.insert({NewCE, FoldedC});
} else {
FoldedOps.insert({NewCE, NewCE});
}
} else {
NewC = It->second;
}
}
Ops.push_back(NewC);
}

if (CE->isCompare())
return ConstantFoldCompareInstOperands(CE->getPredicate(), Ops[0], Ops[1],
DL, TLI);

return ConstantFoldInstOperandsImpl(CE, CE->getType(), CE->getOpcode(), Ops,
DL, TLI);
}

} // end anonymous namespace

Constant *llvm::ConstantFoldConstantExpression(const ConstantExpr *CE,
const DataLayout &DL,
const TargetLibraryInfo *TLI) {
SmallDenseMap<ConstantExpr *, Constant *> FoldedOps;
return ConstantFoldConstantExpressionImpl(CE, DL, TLI, FoldedOps);
Constant *llvm::ConstantFoldConstant(const Constant *C, const DataLayout &DL,
const TargetLibraryInfo *TLI) {
SmallDenseMap<Constant *, Constant *> FoldedOps;
return ConstantFoldConstantImpl(C, DL, TLI, FoldedOps);
}

Constant *llvm::ConstantFoldInstOperands(Instruction *I,
Expand Down
6 changes: 3 additions & 3 deletions llvm/lib/Analysis/Lint.cpp
Expand Up @@ -680,9 +680,9 @@ Value *Lint::findValueImpl(Value *V, bool OffsetOk,
if (Instruction *Inst = dyn_cast<Instruction>(V)) {
if (Value *W = SimplifyInstruction(Inst, *DL, TLI, DT, AC))
return findValueImpl(W, OffsetOk, Visited);
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
if (Value *W = ConstantFoldConstantExpression(CE, *DL, TLI))
if (W != V)
} else if (auto *C = dyn_cast<Constant>(V)) {
if (Value *W = ConstantFoldConstant(C, *DL, TLI))
if (W && W != V)
return findValueImpl(W, OffsetOk, Visited);
}

Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
Expand Up @@ -1764,7 +1764,7 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) {
// If the code isn't optimized, there may be outstanding folding
// opportunities. Attempt to fold the expression using DataLayout as a
// last resort before giving up.
if (Constant *C = ConstantFoldConstantExpression(CE, getDataLayout()))
if (Constant *C = ConstantFoldConstant(CE, getDataLayout()))
if (C != CE)
return lowerConstant(C);

Expand Down Expand Up @@ -2299,7 +2299,7 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV,
// If the constant expression's size is greater than 64-bits, then we have
// to emit the value in chunks. Try to constant fold the value and emit it
// that way.
Constant *New = ConstantFoldConstantExpression(CE, DL);
Constant *New = ConstantFoldConstant(CE, DL);
if (New && New != CE)
return emitGlobalConstantImpl(DL, New, AP);
}
Expand Down
14 changes: 7 additions & 7 deletions llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
Expand Up @@ -1848,9 +1848,9 @@ void NVPTXAsmPrinter::bufferLEByte(const Constant *CPV, int Bytes,
ConvertIntToBytes<>(ptr, int32);
aggBuffer->addBytes(ptr, 4, Bytes);
break;
} else if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
if (const ConstantInt *constInt = dyn_cast<ConstantInt>(
ConstantFoldConstantExpression(Cexpr, DL))) {
} else if (const auto *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
if (const auto *constInt = dyn_cast_or_null<ConstantInt>(
ConstantFoldConstant(Cexpr, DL))) {
int int32 = (int)(constInt->getZExtValue());
ConvertIntToBytes<>(ptr, int32);
aggBuffer->addBytes(ptr, 4, Bytes);
Expand All @@ -1871,8 +1871,8 @@ void NVPTXAsmPrinter::bufferLEByte(const Constant *CPV, int Bytes,
aggBuffer->addBytes(ptr, 8, Bytes);
break;
} else if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
if (const ConstantInt *constInt = dyn_cast<ConstantInt>(
ConstantFoldConstantExpression(Cexpr, DL))) {
if (const auto *constInt = dyn_cast_or_null<ConstantInt>(
ConstantFoldConstant(Cexpr, DL))) {
long long int64 = (long long)(constInt->getZExtValue());
ConvertIntToBytes<>(ptr, int64);
aggBuffer->addBytes(ptr, 8, Bytes);
Expand Down Expand Up @@ -2074,8 +2074,8 @@ NVPTXAsmPrinter::lowerConstantForGV(const Constant *CV, bool ProcessingGeneric)
// If the code isn't optimized, there may be outstanding folding
// opportunities. Attempt to fold the expression using DataLayout as a
// last resort before giving up.
if (Constant *C = ConstantFoldConstantExpression(CE, getDataLayout()))
if (C != CE)
if (Constant *C = ConstantFoldConstant(CE, getDataLayout()))
if (C && C != CE)
return lowerConstantForGV(C, ProcessingGeneric);

// Otherwise report the problem to the user.
Expand Down
6 changes: 3 additions & 3 deletions llvm/lib/Transforms/IPO/GlobalOpt.cpp
Expand Up @@ -2079,10 +2079,10 @@ OptimizeGlobalVars(Module &M, TargetLibraryInfo *TLI,
GV->setLinkage(GlobalValue::InternalLinkage);
// Simplify the initializer.
if (GV->hasInitializer())
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(GV->getInitializer())) {
if (auto *C = dyn_cast<Constant>(GV->getInitializer())) {
auto &DL = M.getDataLayout();
Constant *New = ConstantFoldConstantExpression(CE, DL, TLI);
if (New && New != CE)
Constant *New = ConstantFoldConstant(C, DL, TLI);
if (New && New != C)
GV->setInitializer(New);
}

Expand Down
5 changes: 2 additions & 3 deletions llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
Expand Up @@ -161,9 +161,8 @@ Value *InstCombiner::EvaluateInDifferentType(Value *V, Type *Ty,
if (Constant *C = dyn_cast<Constant>(V)) {
C = ConstantExpr::getIntegerCast(C, Ty, isSigned /*Sext or ZExt*/);
// If we got a constantexpr back, try to simplify it with DL info.
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
if (Constant *FoldedC = ConstantFoldConstantExpression(CE, DL, TLI))
C = FoldedC;
if (Constant *FoldedC = ConstantFoldConstant(C, DL, TLI))
C = FoldedC;
return C;
}

Expand Down
6 changes: 4 additions & 2 deletions llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
Expand Up @@ -194,8 +194,10 @@ static Value *GetShiftedValue(Value *V, unsigned NumBits, bool isLeftShift,
else
V = IC.Builder->CreateLShr(C, NumBits);
// If we got a constantexpr back, try to simplify it with TD info.
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
V = ConstantFoldConstantExpression(CE, DL, IC.getTargetLibraryInfo());
if (auto *C = dyn_cast<Constant>(V))
if (auto *FoldedC =
ConstantFoldConstant(C, DL, IC.getTargetLibraryInfo()))
V = FoldedC;
return V;
}

Expand Down
14 changes: 7 additions & 7 deletions llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
Expand Up @@ -2981,7 +2981,7 @@ static bool AddReachableCodeToWorklist(BasicBlock *BB, const DataLayout &DL,
Worklist.push_back(BB);

SmallVector<Instruction*, 128> InstrsForInstCombineWorklist;
DenseMap<ConstantExpr*, Constant*> FoldedConstants;
DenseMap<Constant *, Constant *> FoldedConstants;

do {
BB = Worklist.pop_back_val();
Expand Down Expand Up @@ -3017,17 +3017,17 @@ static bool AddReachableCodeToWorklist(BasicBlock *BB, const DataLayout &DL,
// See if we can constant fold its operands.
for (User::op_iterator i = Inst->op_begin(), e = Inst->op_end(); i != e;
++i) {
ConstantExpr *CE = dyn_cast<ConstantExpr>(i);
if (CE == nullptr)
if (!isa<ConstantVector>(i) && !isa<ConstantExpr>(i))
continue;

Constant *&FoldRes = FoldedConstants[CE];
auto *C = cast<Constant>(i);
Constant *&FoldRes = FoldedConstants[C];
if (!FoldRes)
FoldRes = ConstantFoldConstantExpression(CE, DL, TLI);
FoldRes = ConstantFoldConstant(C, DL, TLI);
if (!FoldRes)
FoldRes = CE;
FoldRes = C;

if (FoldRes != CE) {
if (FoldRes != C) {
*i = FoldRes;
MadeIRChange = true;
}
Expand Down
15 changes: 9 additions & 6 deletions llvm/lib/Transforms/Scalar/GVN.cpp
Expand Up @@ -725,8 +725,9 @@ static Value *CoerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy,
assert(CanCoerceMustAliasedValueToLoad(StoredVal, LoadedTy, DL) &&
"precondition violation - materialization can't fail");

if (auto *CExpr = dyn_cast<ConstantExpr>(StoredVal))
StoredVal = ConstantFoldConstantExpression(CExpr, DL);
if (auto *C = dyn_cast<Constant>(StoredVal))
if (auto *FoldedStoredVal = ConstantFoldConstant(C, DL))
StoredVal = FoldedStoredVal;

// If this is already the right type, just return it.
Type *StoredValTy = StoredVal->getType();
Expand Down Expand Up @@ -759,8 +760,9 @@ static Value *CoerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy,
StoredVal = IRB.CreateIntToPtr(StoredVal, LoadedTy);
}

if (auto *CExpr = dyn_cast<ConstantExpr>(StoredVal))
StoredVal = ConstantFoldConstantExpression(CExpr, DL);
if (auto *C = dyn_cast<ConstantExpr>(StoredVal))
if (auto *FoldedStoredVal = ConstantFoldConstant(C, DL))
StoredVal = FoldedStoredVal;

return StoredVal;
}
Expand Down Expand Up @@ -804,8 +806,9 @@ static Value *CoerceAvailableValueToLoadType(Value *StoredVal, Type *LoadedTy,
StoredVal = IRB.CreateBitCast(StoredVal, LoadedTy, "bitcast");
}

if (auto *CExpr = dyn_cast<ConstantExpr>(StoredVal))
StoredVal = ConstantFoldConstantExpression(CExpr, DL);
if (auto *C = dyn_cast<Constant>(StoredVal))
if (auto *FoldedStoredVal = ConstantFoldConstant(C, DL))
StoredVal = FoldedStoredVal;

return StoredVal;
}
Expand Down

0 comments on commit d536f23

Please sign in to comment.