From 077d0eb1bd54b71143139a5184d291454d638ebc Mon Sep 17 00:00:00 2001 From: Reid Spencer Date: Mon, 4 Dec 2006 05:19:50 +0000 Subject: [PATCH] For PR950: Fix constant expressions to properly support ICmp and FCmp type expressions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32170 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/VMCore/Constants.cpp | 186 ++++++++++++++++++++++++++------------- 1 file changed, 127 insertions(+), 59 deletions(-) diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 10fdda504c3..4d833caf5e3 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -442,6 +442,10 @@ bool ConstantExpr::isCast() const { return Instruction::isCast(getOpcode()); } +bool ConstantExpr::isCompare() const { + return getOpcode() == Instruction::ICmp || getOpcode() == Instruction::FCmp; +} + /// ConstantExpr::get* - Return some common constants without having to /// specify the full Instruction::OPCODE identifier. /// @@ -510,23 +514,6 @@ Constant *ConstantExpr::getSetLE(Constant *C1, Constant *C2) { Constant *ConstantExpr::getSetGE(Constant *C1, Constant *C2) { return get(Instruction::SetGE, C1, C2); } -Constant * -ConstantExpr::getICmp(unsigned short pred, Constant* LHS, Constant* RHS) { - assert(LHS->getType() == RHS->getType()); - assert(pred >= ICmpInst::FIRST_ICMP_PREDICATE && - pred <= ICmpInst::LAST_ICMP_PREDICATE && "Invalid ICmp Predicate"); - CompareConstantExpr *Result = - new CompareConstantExpr(Instruction::ICmp, pred, LHS, RHS); - return Result; -} -Constant * -ConstantExpr::getFCmp(unsigned short pred, Constant* LHS, Constant* RHS) { - assert(LHS->getType() == RHS->getType()); - assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && "Invalid ICmp Predicate"); - CompareConstantExpr *Result = - new CompareConstantExpr(Instruction::FCmp, pred, LHS, RHS); - return Result; -} unsigned ConstantExpr::getPredicate() const { assert(getOpcode() == Instruction::FCmp || getOpcode() == Instruction::ICmp); return dynamic_cast(this)->predicate; @@ -1370,41 +1357,68 @@ void UndefValue::destroyConstant() { //---- ConstantExpr::get() implementations... // -typedef std::pair > ExprMapKeyType; +struct ExprMapKeyType { + explicit ExprMapKeyType(unsigned opc, std::vector ops, + unsigned short pred = 0) : opcode(opc), operands(ops), predicate(pred) { } + unsigned opcode; + std::vector operands; + unsigned short predicate; + bool operator==(const ExprMapKeyType& that) const { + return this->opcode == that.opcode && + this->predicate == that.predicate && + this->operands == that.operands; + } + bool operator<(const ExprMapKeyType & that) const { + return this->opcode < that.opcode || + (this->opcode == that.opcode && this->predicate < that.predicate) || + (this->opcode == that.opcode && this->predicate == that.predicate && + this->operands < that.operands); + } + + bool operator!=(const ExprMapKeyType& that) const { + return !(*this == that); + } +}; namespace llvm { template<> struct ConstantCreator { static ConstantExpr *create(const Type *Ty, const ExprMapKeyType &V, unsigned short pred = 0) { - if (Instruction::isCast(V.first)) - return new UnaryConstantExpr(V.first, V.second[0], Ty); - if ((V.first >= Instruction::BinaryOpsBegin && - V.first < Instruction::BinaryOpsEnd) || - V.first == Instruction::Shl || - V.first == Instruction::LShr || - V.first == Instruction::AShr) - return new BinaryConstantExpr(V.first, V.second[0], V.second[1]); - if (V.first == Instruction::Select) - return new SelectConstantExpr(V.second[0], V.second[1], V.second[2]); - if (V.first == Instruction::ExtractElement) - return new ExtractElementConstantExpr(V.second[0], V.second[1]); - if (V.first == Instruction::InsertElement) - return new InsertElementConstantExpr(V.second[0], V.second[1], - V.second[2]); - if (V.first == Instruction::ShuffleVector) - return new ShuffleVectorConstantExpr(V.second[0], V.second[1], - V.second[2]); - if (V.first == Instruction::ICmp) - return new CompareConstantExpr(Instruction::ICmp, pred, - V.second[0], V.second[1]); - if (V.first == Instruction::FCmp) - return new CompareConstantExpr(Instruction::FCmp, pred, - V.second[0], V.second[1]); - - assert(V.first == Instruction::GetElementPtr && "Invalid ConstantExpr!"); - std::vector IdxList(V.second.begin()+1, V.second.end()); - return new GetElementPtrConstantExpr(V.second[0], IdxList, Ty); + if (Instruction::isCast(V.opcode)) + return new UnaryConstantExpr(V.opcode, V.operands[0], Ty); + if ((V.opcode >= Instruction::BinaryOpsBegin && + V.opcode < Instruction::BinaryOpsEnd) || + V.opcode == Instruction::Shl || + V.opcode == Instruction::LShr || + V.opcode == Instruction::AShr) + return new BinaryConstantExpr(V.opcode, V.operands[0], V.operands[1]); + if (V.opcode == Instruction::Select) + return new SelectConstantExpr(V.operands[0], V.operands[1], + V.operands[2]); + if (V.opcode == Instruction::ExtractElement) + return new ExtractElementConstantExpr(V.operands[0], V.operands[1]); + if (V.opcode == Instruction::InsertElement) + return new InsertElementConstantExpr(V.operands[0], V.operands[1], + V.operands[2]); + if (V.opcode == Instruction::ShuffleVector) + return new ShuffleVectorConstantExpr(V.operands[0], V.operands[1], + V.operands[2]); + if (V.opcode == Instruction::GetElementPtr) { + std::vector IdxList(V.operands.begin()+1, V.operands.end()); + return new GetElementPtrConstantExpr(V.operands[0], IdxList, Ty); + } + + // The compare instructions are weird. We have to encode the predicate + // value and it is combined with the instruction opcode by multiplying + // the opcode by one hundred. We must decode this to get the predicate. + if (V.opcode == Instruction::ICmp) + return new CompareConstantExpr(Instruction::ICmp, V.predicate, + V.operands[0], V.operands[1]); + if (V.opcode == Instruction::FCmp) + return new CompareConstantExpr(Instruction::FCmp, V.predicate, + V.operands[0], V.operands[1]); + assert(0 && "Invalid ConstantExpr!"); } }; @@ -1465,7 +1479,8 @@ static ExprMapKeyType getValType(ConstantExpr *CE) { Operands.reserve(CE->getNumOperands()); for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) Operands.push_back(cast(CE->getOperand(i))); - return ExprMapKeyType(CE->getOpcode(), Operands); + return ExprMapKeyType(CE->getOpcode(), Operands, + CE->isCompare() ? CE->getPredicate() : 0); } static ManagedStatic argVec(1, C); - ExprMapKeyType Key = std::make_pair(opc, argVec); + ExprMapKeyType Key(opc, argVec); return ExprConstants->getOrCreate(Ty, Key); } @@ -1627,10 +1642,15 @@ Constant *ConstantExpr::getPtrPtrFromArrayPtr(Constant *C) { } Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode, - Constant *C1, Constant *C2) { + Constant *C1, Constant *C2, unsigned short pred) { if (Opcode == Instruction::Shl || Opcode == Instruction::LShr || Opcode == Instruction::AShr) return getShiftTy(ReqTy, Opcode, C1, C2); + if (Opcode == Instruction::ICmp) + return getICmp(pred, C1, C2); + if (Opcode == Instruction::FCmp) + return getFCmp(pred, C1, C2); + // Check the operands for consistency first assert(Opcode >= Instruction::BinaryOpsBegin && Opcode < Instruction::BinaryOpsEnd && @@ -1644,11 +1664,11 @@ Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode, return FC; // Fold a few common cases... std::vector argVec(1, C1); argVec.push_back(C2); - ExprMapKeyType Key = std::make_pair(Opcode, argVec); + ExprMapKeyType Key(Opcode, argVec, pred); return ExprConstants->getOrCreate(ReqTy, Key); } -Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) { +Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2, unsigned short pred) { #ifndef NDEBUG switch (Opcode) { case Instruction::Add: @@ -1696,6 +1716,10 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) { case Instruction::SetGE: case Instruction::SetEQ: case Instruction::SetNE: assert(C1->getType() == C2->getType() && "Op types should be identical!"); break; + case Instruction::FCmp: + case Instruction::ICmp: + assert(C1->getType() == C2->getType() && "Op types should be identical!"); + break; case Instruction::Shl: case Instruction::LShr: case Instruction::AShr: @@ -1709,9 +1733,9 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) { #endif if (Instruction::isComparison(Opcode)) - return getTy(Type::BoolTy, Opcode, C1, C2); + return getTy(Type::BoolTy, Opcode, C1, C2, pred); else - return getTy(C1->getType(), Opcode, C1, C2); + return getTy(C1->getType(), Opcode, C1, C2, pred); } Constant *ConstantExpr::getSelectTy(const Type *ReqTy, Constant *C, @@ -1727,7 +1751,7 @@ Constant *ConstantExpr::getSelectTy(const Type *ReqTy, Constant *C, std::vector argVec(3, C); argVec[1] = V1; argVec[2] = V2; - ExprMapKeyType Key = std::make_pair(Instruction::Select, argVec); + ExprMapKeyType Key(Instruction::Select, argVec); return ExprConstants->getOrCreate(ReqTy, Key); } @@ -1747,7 +1771,7 @@ Constant *ConstantExpr::getShiftTy(const Type *ReqTy, unsigned Opcode, // Look up the constant in the table first to ensure uniqueness std::vector argVec(1, C1); argVec.push_back(C2); - ExprMapKeyType Key = std::make_pair(Opcode, argVec); + ExprMapKeyType Key(Opcode, argVec); return ExprConstants->getOrCreate(ReqTy, Key); } @@ -1768,7 +1792,7 @@ Constant *ConstantExpr::getGetElementPtrTy(const Type *ReqTy, Constant *C, ArgVec.push_back(C); for (unsigned i = 0, e = IdxList.size(); i != e; ++i) ArgVec.push_back(cast(IdxList[i])); - const ExprMapKeyType &Key = std::make_pair(Instruction::GetElementPtr,ArgVec); + const ExprMapKeyType Key(Instruction::GetElementPtr,ArgVec); return ExprConstants->getOrCreate(ReqTy, Key); } @@ -1792,6 +1816,41 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, return getGetElementPtrTy(PointerType::get(Ty), C, IdxList); } +Constant * +ConstantExpr::getICmp(unsigned short pred, Constant* LHS, Constant* RHS) { + assert(LHS->getType() == RHS->getType()); + assert(pred >= ICmpInst::FIRST_ICMP_PREDICATE && + pred <= ICmpInst::LAST_ICMP_PREDICATE && "Invalid ICmp Predicate"); + + if (Constant *FC = ConstantFoldCompare(Instruction::ICmp, LHS, RHS, pred)) + return FC; // Fold a few common cases... + + // Look up the constant in the table first to ensure uniqueness + std::vector ArgVec; + ArgVec.push_back(LHS); + ArgVec.push_back(RHS); + // Fake up an opcode value that encodes both the opcode and predicate + const ExprMapKeyType Key(Instruction::ICmp, ArgVec, pred); + return ExprConstants->getOrCreate(Type::BoolTy, Key); +} + +Constant * +ConstantExpr::getFCmp(unsigned short pred, Constant* LHS, Constant* RHS) { + assert(LHS->getType() == RHS->getType()); + assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && "Invalid FCmp Predicate"); + + if (Constant *FC = ConstantFoldCompare(Instruction::FCmp, LHS, RHS, pred)) + return FC; // Fold a few common cases... + + // Look up the constant in the table first to ensure uniqueness + std::vector ArgVec; + ArgVec.push_back(LHS); + ArgVec.push_back(RHS); + // Fake up an opcode value that encodes both the opcode and predicate + const ExprMapKeyType Key(Instruction::FCmp, ArgVec, pred); + return ExprConstants->getOrCreate(Type::BoolTy, Key); +} + Constant *ConstantExpr::getExtractElementTy(const Type *ReqTy, Constant *Val, Constant *Idx) { if (Constant *FC = ConstantFoldExtractElementInstruction(Val, Idx)) @@ -1799,7 +1858,7 @@ Constant *ConstantExpr::getExtractElementTy(const Type *ReqTy, Constant *Val, // Look up the constant in the table first to ensure uniqueness std::vector ArgVec(1, Val); ArgVec.push_back(Idx); - const ExprMapKeyType &Key = std::make_pair(Instruction::ExtractElement,ArgVec); + const ExprMapKeyType Key(Instruction::ExtractElement,ArgVec); return ExprConstants->getOrCreate(ReqTy, Key); } @@ -1820,7 +1879,7 @@ Constant *ConstantExpr::getInsertElementTy(const Type *ReqTy, Constant *Val, std::vector ArgVec(1, Val); ArgVec.push_back(Elt); ArgVec.push_back(Idx); - const ExprMapKeyType &Key = std::make_pair(Instruction::InsertElement,ArgVec); + const ExprMapKeyType Key(Instruction::InsertElement,ArgVec); return ExprConstants->getOrCreate(ReqTy, Key); } @@ -1844,7 +1903,7 @@ Constant *ConstantExpr::getShuffleVectorTy(const Type *ReqTy, Constant *V1, std::vector ArgVec(1, V1); ArgVec.push_back(V2); ArgVec.push_back(Mask); - const ExprMapKeyType &Key = std::make_pair(Instruction::ShuffleVector,ArgVec); + const ExprMapKeyType Key(Instruction::ShuffleVector,ArgVec); return ExprConstants->getOrCreate(ReqTy, Key); } @@ -2071,6 +2130,15 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, if (C2 == From) C2 = To; if (C3 == From) C3 = To; Replacement = ConstantExpr::getShuffleVector(C1, C2, C3); + } else if (isCompare()) { + Constant *C1 = getOperand(0); + Constant *C2 = getOperand(1); + if (C1 == From) C1 = To; + if (C2 == From) C2 = To; + if (getOpcode() == Instruction::ICmp) + Replacement = ConstantExpr::getICmp(getPredicate(), C1, C2); + else + Replacement = ConstantExpr::getFCmp(getPredicate(), C1, C2); } else if (getNumOperands() == 2) { Constant *C1 = getOperand(0); Constant *C2 = getOperand(1); -- 2.34.1