-Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
- const Constant *V1,
- const Constant *V2) {
- Constant *C = 0;
- switch (Opcode) {
- default: break;
- case Instruction::Add: C = ConstRules::get(V1, V2).add(V1, V2); break;
- case Instruction::Sub: C = ConstRules::get(V1, V2).sub(V1, V2); break;
- case Instruction::Mul: C = ConstRules::get(V1, V2).mul(V1, V2); break;
- case Instruction::Div: C = ConstRules::get(V1, V2).div(V1, V2); break;
- case Instruction::Rem: C = ConstRules::get(V1, V2).rem(V1, V2); break;
- case Instruction::And: C = ConstRules::get(V1, V2).op_and(V1, V2); break;
- case Instruction::Or: C = ConstRules::get(V1, V2).op_or (V1, V2); break;
- case Instruction::Xor: C = ConstRules::get(V1, V2).op_xor(V1, V2); break;
- case Instruction::Shl: C = ConstRules::get(V1, V2).shl(V1, V2); break;
- case Instruction::Shr: C = ConstRules::get(V1, V2).shr(V1, V2); break;
- case Instruction::SetEQ: C = ConstRules::get(V1, V2).equalto(V1, V2); break;
- case Instruction::SetLT: C = ConstRules::get(V1, V2).lessthan(V1, V2);break;
- case Instruction::SetGT: C = ConstRules::get(V1, V2).lessthan(V2, V1);break;
- case Instruction::SetNE: // V1 != V2 === !(V1 == V2)
- C = ConstRules::get(V1, V2).equalto(V1, V2);
- if (C) return ConstantExpr::get(Instruction::Xor, C, ConstantBool::True);
- break;
- case Instruction::SetLE: // V1 <= V2 === !(V2 < V1)
- C = ConstRules::get(V1, V2).lessthan(V2, V1);
- if (C) return ConstantExpr::get(Instruction::Xor, C, ConstantBool::True);
- break;
- case Instruction::SetGE: // V1 >= V2 === !(V1 < V2)
- C = ConstRules::get(V1, V2).lessthan(V1, V2);
- if (C) return ConstantExpr::get(Instruction::Xor, C, ConstantBool::True);
- break;
+Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred,
+ const Constant *C1,
+ const Constant *C2) {
+
+ // Handle some degenerate cases first
+ if (isa<UndefValue>(C1) || isa<UndefValue>(C2))
+ return UndefValue::get(Type::Int1Ty);
+
+ // icmp eq/ne(null,GV) -> false/true
+ if (C1->isNullValue()) {
+ if (const GlobalValue *GV = dyn_cast<GlobalValue>(C2))
+ if (!GV->hasExternalWeakLinkage()) // External weak GV can be null
+ if (pred == ICmpInst::ICMP_EQ)
+ return ConstantInt::getFalse();
+ else if (pred == ICmpInst::ICMP_NE)
+ return ConstantInt::getTrue();
+ // icmp eq/ne(GV,null) -> false/true
+ } else if (C2->isNullValue()) {
+ if (const GlobalValue *GV = dyn_cast<GlobalValue>(C1))
+ if (!GV->hasExternalWeakLinkage()) // External weak GV can be null
+ if (pred == ICmpInst::ICMP_EQ)
+ return ConstantInt::getFalse();
+ else if (pred == ICmpInst::ICMP_NE)
+ return ConstantInt::getTrue();
+ }
+
+ if (isa<ConstantInt>(C1) && isa<ConstantInt>(C2) &&
+ C1->getType() == Type::Int1Ty && C2->getType() == Type::Int1Ty) {
+ bool C1Val = cast<ConstantInt>(C1)->getZExtValue();
+ bool C2Val = cast<ConstantInt>(C2)->getZExtValue();
+ switch (pred) {
+ default: assert(0 && "Invalid ICmp Predicate"); return 0;
+ case ICmpInst::ICMP_EQ:
+ return ConstantInt::get(Type::Int1Ty, C1Val == C2Val);
+ case ICmpInst::ICMP_NE:
+ return ConstantInt::get(Type::Int1Ty, C1Val != C2Val);
+ case ICmpInst::ICMP_ULT:
+ return ConstantInt::get(Type::Int1Ty, C1Val < C2Val);
+ case ICmpInst::ICMP_UGT:
+ return ConstantInt::get(Type::Int1Ty, C1Val > C2Val);
+ case ICmpInst::ICMP_ULE:
+ return ConstantInt::get(Type::Int1Ty, C1Val <= C2Val);
+ case ICmpInst::ICMP_UGE:
+ return ConstantInt::get(Type::Int1Ty, C1Val >= C2Val);
+ case ICmpInst::ICMP_SLT:
+ return ConstantInt::get(Type::Int1Ty, C1Val < C2Val);
+ case ICmpInst::ICMP_SGT:
+ return ConstantInt::get(Type::Int1Ty, C1Val > C2Val);
+ case ICmpInst::ICMP_SLE:
+ return ConstantInt::get(Type::Int1Ty, C1Val <= C2Val);
+ case ICmpInst::ICMP_SGE:
+ return ConstantInt::get(Type::Int1Ty, C1Val >= C2Val);
+ }
+ } else if (isa<ConstantInt>(C1) && isa<ConstantInt>(C2)) {
+ if (ICmpInst::isSignedPredicate(ICmpInst::Predicate(pred))) {
+ int64_t V1 = cast<ConstantInt>(C1)->getSExtValue();
+ int64_t V2 = cast<ConstantInt>(C2)->getSExtValue();
+ switch (pred) {
+ default: assert(0 && "Invalid ICmp Predicate"); return 0;
+ case ICmpInst::ICMP_SLT:return ConstantInt::get(Type::Int1Ty, V1 < V2);
+ case ICmpInst::ICMP_SGT:return ConstantInt::get(Type::Int1Ty, V1 > V2);
+ case ICmpInst::ICMP_SLE:return ConstantInt::get(Type::Int1Ty, V1 <= V2);
+ case ICmpInst::ICMP_SGE:return ConstantInt::get(Type::Int1Ty, V1 >= V2);
+ }
+ } else {
+ uint64_t V1 = cast<ConstantInt>(C1)->getZExtValue();
+ uint64_t V2 = cast<ConstantInt>(C2)->getZExtValue();
+ switch (pred) {
+ default: assert(0 && "Invalid ICmp Predicate"); return 0;
+ case ICmpInst::ICMP_EQ: return ConstantInt::get(Type::Int1Ty, V1 == V2);
+ case ICmpInst::ICMP_NE: return ConstantInt::get(Type::Int1Ty, V1 != V2);
+ case ICmpInst::ICMP_ULT:return ConstantInt::get(Type::Int1Ty, V1 < V2);
+ case ICmpInst::ICMP_UGT:return ConstantInt::get(Type::Int1Ty, V1 > V2);
+ case ICmpInst::ICMP_ULE:return ConstantInt::get(Type::Int1Ty, V1 <= V2);
+ case ICmpInst::ICMP_UGE:return ConstantInt::get(Type::Int1Ty, V1 >= V2);
+ }
+ }
+ } else if (isa<ConstantFP>(C1) && isa<ConstantFP>(C2)) {
+ double C1Val = cast<ConstantFP>(C1)->getValue();
+ double C2Val = cast<ConstantFP>(C2)->getValue();
+ switch (pred) {
+ default: assert(0 && "Invalid FCmp Predicate"); return 0;
+ case FCmpInst::FCMP_FALSE: return ConstantInt::getFalse();
+ case FCmpInst::FCMP_TRUE: return ConstantInt::getTrue();
+ case FCmpInst::FCMP_UNO:
+ return ConstantInt::get(Type::Int1Ty, C1Val != C1Val || C2Val != C2Val);
+ case FCmpInst::FCMP_ORD:
+ return ConstantInt::get(Type::Int1Ty, C1Val == C1Val && C2Val == C2Val);
+ case FCmpInst::FCMP_UEQ:
+ if (C1Val != C1Val || C2Val != C2Val)
+ return ConstantInt::getTrue();
+ /* FALL THROUGH */
+ case FCmpInst::FCMP_OEQ:
+ return ConstantInt::get(Type::Int1Ty, C1Val == C2Val);
+ case FCmpInst::FCMP_UNE:
+ if (C1Val != C1Val || C2Val != C2Val)
+ return ConstantInt::getTrue();
+ /* FALL THROUGH */
+ case FCmpInst::FCMP_ONE:
+ return ConstantInt::get(Type::Int1Ty, C1Val != C2Val);
+ case FCmpInst::FCMP_ULT:
+ if (C1Val != C1Val || C2Val != C2Val)
+ return ConstantInt::getTrue();
+ /* FALL THROUGH */
+ case FCmpInst::FCMP_OLT:
+ return ConstantInt::get(Type::Int1Ty, C1Val < C2Val);
+ case FCmpInst::FCMP_UGT:
+ if (C1Val != C1Val || C2Val != C2Val)
+ return ConstantInt::getTrue();
+ /* FALL THROUGH */
+ case FCmpInst::FCMP_OGT:
+ return ConstantInt::get(Type::Int1Ty, C1Val > C2Val);
+ case FCmpInst::FCMP_ULE:
+ if (C1Val != C1Val || C2Val != C2Val)
+ return ConstantInt::getTrue();
+ /* FALL THROUGH */
+ case FCmpInst::FCMP_OLE:
+ return ConstantInt::get(Type::Int1Ty, C1Val <= C2Val);
+ case FCmpInst::FCMP_UGE:
+ if (C1Val != C1Val || C2Val != C2Val)
+ return ConstantInt::getTrue();
+ /* FALL THROUGH */
+ case FCmpInst::FCMP_OGE:
+ return ConstantInt::get(Type::Int1Ty, C1Val >= C2Val);
+ }
+ } else if (const ConstantPacked *CP1 = dyn_cast<ConstantPacked>(C1)) {
+ if (const ConstantPacked *CP2 = dyn_cast<ConstantPacked>(C2)) {
+ if (pred == FCmpInst::FCMP_OEQ || pred == FCmpInst::FCMP_UEQ) {
+ for (unsigned i = 0, e = CP1->getNumOperands(); i != e; ++i) {
+ Constant *C= ConstantExpr::getFCmp(FCmpInst::FCMP_OEQ,
+ const_cast<Constant*>(CP1->getOperand(i)),
+ const_cast<Constant*>(CP2->getOperand(i)));
+ if (ConstantInt *CB = dyn_cast<ConstantInt>(C))
+ return CB;
+ }
+ // Otherwise, could not decide from any element pairs.
+ return 0;
+ } else if (pred == ICmpInst::ICMP_EQ) {
+ for (unsigned i = 0, e = CP1->getNumOperands(); i != e; ++i) {
+ Constant *C = ConstantExpr::getICmp(ICmpInst::ICMP_EQ,
+ const_cast<Constant*>(CP1->getOperand(i)),
+ const_cast<Constant*>(CP2->getOperand(i)));
+ if (ConstantInt *CB = dyn_cast<ConstantInt>(C))
+ return CB;
+ }
+ // Otherwise, could not decide from any element pairs.
+ return 0;
+ }
+ }