//
//===----------------------------------------------------------------------===//
-#include "llvm/Support/MathExtras.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Intrinsics.h"
+#include "llvm/Analysis/ConstantFolding.h"
+#include "llvm/Support/GetElementPtrTypeIterator.h"
+#include "llvm/Support/MathExtras.h"
#include <cerrno>
#include <cmath>
using namespace llvm;
// If we reach here, all incoming values are the same constant.
return Result;
- } else if (CallInst *CI = dyn_cast<CallInst>(I)) {
- if (Function *F = CI->getCalledFunction())
- if (canConstantFoldCallTo(F)) {
- std::vector<Constant*> Args;
- for (unsigned i = 1, e = CI->getNumOperands(); i != e; ++i)
- if (Constant *Op = dyn_cast<Constant>(CI->getOperand(i)))
- Args.push_back(Op);
- else
- return 0;
- return ConstantFoldCall(F, Args);
- }
- return 0;
}
Constant *Op0 = 0, *Op1 = 0;
case 0: return 0;
}
- if (isa<BinaryOperator>(I) || isa<ShiftInst>(I))
- return ConstantExpr::get(I->getOpcode(), Op0, Op1);
+ if (isa<BinaryOperator>(I) || isa<ShiftInst>(I)) {
+ if (Constant *Op0 = dyn_cast<Constant>(I->getOperand(0)))
+ if (Constant *Op1 = dyn_cast<Constant>(I->getOperand(1)))
+ return ConstantExpr::get(I->getOpcode(), Op0, Op1);
+ return 0; // Operands not constants.
+ }
+
+ // Scan the operand list, checking to see if the are all constants, if so,
+ // hand off to ConstantFoldInstOperands.
+ std::vector<Constant*> Ops;
+ for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
+ if (Constant *Op = dyn_cast<Constant>(I->getOperand(i)))
+ Ops.push_back(Op);
+ else
+ return 0; // All operands not constant!
- switch (I->getOpcode()) {
+ return ConstantFoldInstOperands(I->getOpcode(), I->getType(), Ops);
+}
+
+/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the
+/// specified opcode and operands. If successful, the constant result is
+/// returned, if not, null is returned. Note that this function can fail when
+/// attempting to fold instructions like loads and stores, which have no
+/// constant expression form.
+///
+Constant *llvm::ConstantFoldInstOperands(unsigned Opc, const Type *DestTy,
+ const std::vector<Constant*> &Ops) {
+ if (Opc >= Instruction::BinaryOpsBegin && Opc < Instruction::BinaryOpsEnd)
+ return ConstantExpr::get(Opc, Ops[0], Ops[1]);
+
+ switch (Opc) {
default: return 0;
+ case Instruction::Call:
+ if (Function *F = dyn_cast<Function>(Ops[0])) {
+ if (canConstantFoldCallTo(F)) {
+ std::vector<Constant*> Args(Ops.begin()+1, Ops.end());
+ return ConstantFoldCall(F, Args);
+ }
+ }
+ return 0;
+ case Instruction::Shl:
+ case Instruction::Shr:
+ return ConstantExpr::get(Opc, Ops[0], Ops[1]);
case Instruction::Cast:
- return ConstantExpr::getCast(Op0, I->getType());
+ return ConstantExpr::getCast(Ops[0], DestTy);
case Instruction::Select:
- if (Constant *Op2 = dyn_cast<Constant>(I->getOperand(2)))
- return ConstantExpr::getSelect(Op0, Op1, Op2);
- return 0;
+ return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2]);
+ case Instruction::ExtractElement:
+ return ConstantExpr::getExtractElement(Ops[0], Ops[1]);
+ case Instruction::InsertElement:
+ return ConstantExpr::getInsertElement(Ops[0], Ops[1], Ops[2]);
+ case Instruction::ShuffleVector:
+ return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]);
case Instruction::GetElementPtr:
- std::vector<Constant*> IdxList;
- IdxList.reserve(I->getNumOperands()-1);
- if (Op1) IdxList.push_back(Op1);
- for (unsigned i = 2, e = I->getNumOperands(); i != e; ++i)
- if (Constant *C = dyn_cast<Constant>(I->getOperand(i)))
- IdxList.push_back(C);
- else
- return 0; // Non-constant operand
- return ConstantExpr::getGetElementPtr(Op0, IdxList);
+ return ConstantExpr::getGetElementPtr(Ops[0],
+ std::vector<Constant*>(Ops.begin()+1,
+ Ops.end()));
}
}
return false;
}
-/// canConstantFoldCallTo - Return true if its even possible to fold a call to
-/// the specified function.
-bool llvm::canConstantFoldCallTo(Function *F) {
- const std::string &Name = F->getName();
-
- switch (F->getIntrinsicID()) {
- case Intrinsic::isunordered: return true;
- default: break;
- }
-
- return Name == "sin" || Name == "cos" || Name == "tan" || Name == "sqrt" ||
- Name == "log" || Name == "log10" || Name == "exp" || Name == "pow" ||
- Name == "acos" || Name == "asin" || Name == "atan" || Name == "fmod";
-}
-
-static Constant *ConstantFoldFP(double (*NativeFP)(double), double V,
- const Type *Ty) {
- errno = 0;
- V = NativeFP(V);
- if (errno == 0)
- return ConstantFP::get(Ty, V);
- return 0;
-}
-
-/// ConstantFoldCall - Attempt to constant fold a call to the specified function
-/// with the specified arguments, returning null if unsuccessful.
-Constant *llvm::ConstantFoldCall(Function *F,
- const std::vector<Constant*> &Operands) {
- const std::string &Name = F->getName();
- const Type *Ty = F->getReturnType();
-
- if (Operands.size() == 1) {
- if (ConstantFP *Op = dyn_cast<ConstantFP>(Operands[0])) {
- double V = Op->getValue();
- if (Name == "sin")
- return ConstantFP::get(Ty, sin(V));
- else if (Name == "cos")
- return ConstantFP::get(Ty, cos(V));
- else if (Name == "tan")
- return ConstantFP::get(Ty, tan(V));
- else if (Name == "sqrt" && V >= 0)
- return ConstantFP::get(Ty, sqrt(V));
- else if (Name == "exp")
- return ConstantFP::get(Ty, exp(V));
- else if (Name == "log" && V > 0)
- return ConstantFP::get(Ty, log(V));
- else if (Name == "log10")
- return ConstantFoldFP(log10, V, Ty);
- else if (Name == "acos")
- return ConstantFoldFP(acos, V, Ty);
- else if (Name == "asin")
- return ConstantFoldFP(asin, V, Ty);
- else if (Name == "atan")
- return ConstantFP::get(Ty, atan(V));
- }
- } else if (Operands.size() == 2) {
- if (ConstantFP *Op1 = dyn_cast<ConstantFP>(Operands[0]))
- if (ConstantFP *Op2 = dyn_cast<ConstantFP>(Operands[1])) {
- double Op1V = Op1->getValue(), Op2V = Op2->getValue();
-
- if (Name == "llvm.isunordered")
- return ConstantBool::get(IsNAN(Op1V) || IsNAN(Op2V));
+/// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a
+/// getelementptr constantexpr, return the constant value being addressed by the
+/// constant expression, or null if something is funny and we can't decide.
+Constant *llvm::ConstantFoldLoadThroughGEPConstantExpr(Constant *C,
+ ConstantExpr *CE) {
+ if (CE->getOperand(1) != Constant::getNullValue(CE->getOperand(1)->getType()))
+ return 0; // Do not allow stepping over the value!
+
+ // Loop over all of the operands, tracking down which value we are
+ // addressing...
+ gep_type_iterator I = gep_type_begin(CE), E = gep_type_end(CE);
+ for (++I; I != E; ++I)
+ if (const StructType *STy = dyn_cast<StructType>(*I)) {
+ ConstantUInt *CU = cast<ConstantUInt>(I.getOperand());
+ assert(CU->getValue() < STy->getNumElements() &&
+ "Struct index out of range!");
+ unsigned El = (unsigned)CU->getValue();
+ if (ConstantStruct *CS = dyn_cast<ConstantStruct>(C)) {
+ C = CS->getOperand(El);
+ } else if (isa<ConstantAggregateZero>(C)) {
+ C = Constant::getNullValue(STy->getElementType(El));
+ } else if (isa<UndefValue>(C)) {
+ C = UndefValue::get(STy->getElementType(El));
+ } else {
+ return 0;
+ }
+ } else if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand())) {
+ if (const ArrayType *ATy = dyn_cast<ArrayType>(*I)) {
+ if ((uint64_t)CI->getRawValue() >= ATy->getNumElements())
+ return 0;
+ if (ConstantArray *CA = dyn_cast<ConstantArray>(C))
+ C = CA->getOperand((unsigned)CI->getRawValue());
+ else if (isa<ConstantAggregateZero>(C))
+ C = Constant::getNullValue(ATy->getElementType());
+ else if (isa<UndefValue>(C))
+ C = UndefValue::get(ATy->getElementType());
else
- if (Name == "pow") {
- errno = 0;
- double V = pow(Op1V, Op2V);
- if (errno == 0)
- return ConstantFP::get(Ty, V);
- } else if (Name == "fmod") {
- errno = 0;
- double V = fmod(Op1V, Op2V);
- if (errno == 0)
- return ConstantFP::get(Ty, V);
- }
+ return 0;
+ } else if (const PackedType *PTy = dyn_cast<PackedType>(*I)) {
+ if ((uint64_t)CI->getRawValue() >= PTy->getNumElements())
+ return 0;
+ if (ConstantPacked *CP = dyn_cast<ConstantPacked>(C))
+ C = CP->getOperand((unsigned)CI->getRawValue());
+ else if (isa<ConstantAggregateZero>(C))
+ C = Constant::getNullValue(PTy->getElementType());
+ else if (isa<UndefValue>(C))
+ C = UndefValue::get(PTy->getElementType());
+ else
+ return 0;
+ } else {
+ return 0;
}
- }
- return 0;
+ } else {
+ return 0;
+ }
+ return C;
}
-
-
//===----------------------------------------------------------------------===//
// Local dead code elimination...
//
bool llvm::isInstructionTriviallyDead(Instruction *I) {
- return I->use_empty() && !I->mayWriteToMemory() && !isa<TerminatorInst>(I);
+ if (!I->use_empty() || isa<TerminatorInst>(I)) return false;
+
+ if (!I->mayWriteToMemory()) return true;
+
+ if (CallInst *CI = dyn_cast<CallInst>(I))
+ if (Function *F = CI->getCalledFunction()) {
+ unsigned IntrinsicID = F->getIntrinsicID();
+#define GET_SIDE_EFFECT_INFO
+#include "llvm/Intrinsics.gen"
+#undef GET_SIDE_EFFECT_INFO
+ }
+ return false;
}
// dceInstruction - Inspect the instruction at *BBI and figure out if it's
}
return false;
}
-
-//===----------------------------------------------------------------------===//
-// PHI Instruction Simplification
-//
-
-/// hasConstantValue - If the specified PHI node always merges together the same
-/// value, return the value, otherwise return null.
-///
-Value *llvm::hasConstantValue(PHINode *PN) {
- // If the PHI node only has one incoming value, eliminate the PHI node...
- if (PN->getNumIncomingValues() == 1)
- return PN->getIncomingValue(0);
-
- // Otherwise if all of the incoming values are the same for the PHI, replace
- // the PHI node with the incoming value.
- //
- Value *InVal = 0;
- for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
- if (PN->getIncomingValue(i) != PN && // Not the PHI node itself...
- !isa<UndefValue>(PN->getIncomingValue(i)))
- if (InVal && PN->getIncomingValue(i) != InVal)
- return 0; // Not the same, bail out.
- else
- InVal = PN->getIncomingValue(i);
-
- // The only case that could cause InVal to be null is if we have a PHI node
- // that only has entries for itself. In this case, there is no entry into the
- // loop, so kill the PHI.
- //
- if (InVal == 0) InVal = UndefValue::get(PN->getType());
-
- // All of the incoming values are the same, return the value now.
- return InVal;
-}