Changes in directory llvm/lib/VMCore:
ConstantFolding.cpp updated: 1.80 -> 1.81 --- Log message: Implement a few symbolic constant folding things. X ? Y : Y is Y. Fold: seteq ({ short }* cast (int 1 to { short }*), { short }* null) setlt ({ short }* cast (int 1 to { short }*), { short }* cast (int 2 to { short }*)) to false/true. These last two commonly occur in the output of compilers that tag integers, like cozmic's scheme compiler. Tested by Regression/Assembler/ConstantExprFold.llx --- Diffs of the changes: (+32 -7) ConstantFolding.cpp | 39 ++++++++++++++++++++++++++++++++------- 1 files changed, 32 insertions(+), 7 deletions(-) Index: llvm/lib/VMCore/ConstantFolding.cpp diff -u llvm/lib/VMCore/ConstantFolding.cpp:1.80 llvm/lib/VMCore/ConstantFolding.cpp:1.81 --- llvm/lib/VMCore/ConstantFolding.cpp:1.80 Thu Jan 5 01:19:51 2006 +++ llvm/lib/VMCore/ConstantFolding.cpp Thu Jan 5 01:49:30 2006 @@ -720,6 +720,7 @@ if (isa<UndefValue>(V1)) return const_cast<Constant*>(V2); if (isa<UndefValue>(V2)) return const_cast<Constant*>(V1); if (isa<UndefValue>(Cond)) return const_cast<Constant*>(V1); + if (V1 == V2) return const_cast<Constant*>(V1); return 0; } @@ -786,16 +787,27 @@ /// constants (like ConstantInt) to be the simplest, followed by /// GlobalValues, followed by ConstantExpr's (the most complex). /// -static Instruction::BinaryOps evaluateRelation(const Constant *V1, - const Constant *V2) { +static Instruction::BinaryOps evaluateRelation(Constant *V1, Constant *V2) { assert(V1->getType() == V2->getType() && "Cannot compare different types of values!"); if (V1 == V2) return Instruction::SetEQ; if (!isa<ConstantExpr>(V1) && !isa<GlobalValue>(V1)) { + if (!isa<GlobalValue>(V2) && !isa<ConstantExpr>(V2)) { + // We distilled this down to a simple case, use the standard constant + // folder. + ConstantBool *R = dyn_cast<ConstantBool>(ConstantExpr::getSetEQ(V1, V2)); + if (R == ConstantBool::True) return Instruction::SetEQ; + R = dyn_cast<ConstantBool>(ConstantExpr::getSetLT(V1, V2)); + if (R == ConstantBool::True) return Instruction::SetLT; + R = dyn_cast<ConstantBool>(ConstantExpr::getSetGT(V1, V2)); + if (R == ConstantBool::True) return Instruction::SetGT; + + // If we couldn't figure it out, bail. + return Instruction::BinaryOpsEnd; + } + // If the first operand is simple, swap operands. - assert((isa<GlobalValue>(V2) || isa<ConstantExpr>(V2)) && - "Simple cases should have been handled by caller!"); Instruction::BinaryOps SwappedRelation = evaluateRelation(V2, V1); if (SwappedRelation != Instruction::BinaryOpsEnd) return SetCondInst::getSwappedCondition(SwappedRelation); @@ -826,7 +838,7 @@ } else { // Ok, the LHS is known to be a constantexpr. The RHS can be any of a // constantexpr, a CPR, or a simple constant. - const ConstantExpr *CE1 = cast<ConstantExpr>(V1); + ConstantExpr *CE1 = cast<ConstantExpr>(V1); Constant *CE1Op0 = CE1->getOperand(0); switch (CE1->getOpcode()) { @@ -834,9 +846,21 @@ // If the cast is not actually changing bits, and the second operand is a // null pointer, do the comparison with the pre-casted value. if (V2->isNullValue() && - CE1->getType()->isLosslesslyConvertibleTo(CE1Op0->getType())) + (isa<PointerType>(CE1->getType()) || CE1->getType()->isIntegral())) return evaluateRelation(CE1Op0, Constant::getNullValue(CE1Op0->getType())); + + // If the dest type is a pointer type, and the RHS is a constantexpr cast + // from the same type as the src of the LHS, evaluate the inputs. This is + // important for things like "seteq (cast 4 to int*), (cast 5 to int*)", + // which happens a lot in compilers with tagged integers. + if (ConstantExpr *CE2 = dyn_cast<ConstantExpr>(V2)) + if (isa<PointerType>(CE1->getType()) && + CE2->getOpcode() == Instruction::Cast && + CE1->getOperand(0)->getType() == CE2->getOperand(0)->getType() && + CE1->getOperand(0)->getType()->isIntegral()) { + return evaluateRelation(CE1->getOperand(0), CE2->getOperand(0)); + } break; case Instruction::GetElementPtr: @@ -977,7 +1001,8 @@ if (SetCondInst::isRelational(Opcode)) { if (isa<UndefValue>(V1) || isa<UndefValue>(V2)) return UndefValue::get(Type::BoolTy); - switch (evaluateRelation(V1, V2)) { + switch (evaluateRelation(const_cast<Constant*>(V1), + const_cast<Constant*>(V2))) { default: assert(0 && "Unknown relational!"); case Instruction::BinaryOpsEnd: break; // Couldn't determine anything about these constants. _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits