[llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
Chris Lattner
lattner at cs.uiuc.edu
Thu Jun 19 12:01:03 PDT 2003
Changes in directory llvm/lib/Transforms/Scalar:
InstructionCombining.cpp updated: 1.89 -> 1.90
---
Log message:
Implement the functionality of InstCombine/call.ll
---
Diffs of the changes:
Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.89 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.90
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.89 Thu Jun 5 15:12:51 2003
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Thu Jun 19 12:00:31 2003
@@ -24,6 +24,7 @@
#include "llvm/DerivedTypes.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/InstVisitor.h"
+#include "llvm/Support/CallSite.h"
#include "Support/Statistic.h"
#include <algorithm>
@@ -73,6 +74,8 @@
Instruction *visitSetCondInst(BinaryOperator &I);
Instruction *visitShiftInst(ShiftInst &I);
Instruction *visitCastInst(CastInst &CI);
+ Instruction *visitCallInst(CallInst &CI);
+ Instruction *visitInvokeInst(InvokeInst &II);
Instruction *visitPHINode(PHINode &PN);
Instruction *visitGetElementPtrInst(GetElementPtrInst &GEP);
Instruction *visitAllocationInst(AllocationInst &AI);
@@ -81,6 +84,9 @@
// visitInstruction - Specify what to return for unhandled instructions...
Instruction *visitInstruction(Instruction &I) { return 0; }
+ private:
+ bool transformConstExprCastCall(CallSite CS);
+
// InsertNewInstBefore - insert an instruction New before instruction Old
// in the program. Add the new instruction to the worklist.
//
@@ -107,7 +113,6 @@
// SimplifyCommutative - This performs a few simplifications for commutative
// operators...
bool SimplifyCommutative(BinaryOperator &I);
-
};
RegisterOpt<InstCombiner> X("instcombine", "Combine redundant instructions");
@@ -927,6 +932,145 @@
return 0;
}
+
+// CallInst simplification
+//
+Instruction *InstCombiner::visitCallInst(CallInst &CI) {
+ if (transformConstExprCastCall(&CI)) return 0;
+ return 0;
+}
+
+// InvokeInst simplification
+//
+Instruction *InstCombiner::visitInvokeInst(InvokeInst &II) {
+ if (transformConstExprCastCall(&II)) return 0;
+ return 0;
+}
+
+// getPromotedType - Return the specified type promoted as it would be to pass
+// though a va_arg area...
+static const Type *getPromotedType(const Type *Ty) {
+ switch (Ty->getPrimitiveID()) {
+ case Type::SByteTyID:
+ case Type::ShortTyID: return Type::IntTy;
+ case Type::UByteTyID:
+ case Type::UShortTyID: return Type::UIntTy;
+ case Type::FloatTyID: return Type::DoubleTy;
+ default: return Ty;
+ }
+}
+
+// transformConstExprCastCall - If the callee is a constexpr cast of a function,
+// attempt to move the cast to the arguments of the call/invoke.
+//
+bool InstCombiner::transformConstExprCastCall(CallSite CS) {
+ if (!isa<ConstantExpr>(CS.getCalledValue())) return false;
+ ConstantExpr *CE = cast<ConstantExpr>(CS.getCalledValue());
+ if (CE->getOpcode() != Instruction::Cast ||
+ !isa<ConstantPointerRef>(CE->getOperand(0)))
+ return false;
+ ConstantPointerRef *CPR = cast<ConstantPointerRef>(CE->getOperand(0));
+ if (!isa<Function>(CPR->getValue())) return false;
+ Function *Callee = cast<Function>(CPR->getValue());
+ Instruction *Caller = CS.getInstruction();
+
+ // Okay, this is a cast from a function to a different type. Unless doing so
+ // would cause a type conversion of one of our arguments, change this call to
+ // be a direct call with arguments casted to the appropriate types.
+ //
+ const FunctionType *FT = Callee->getFunctionType();
+ const Type *OldRetTy = Caller->getType();
+
+ if (Callee->isExternal() &&
+ !OldRetTy->isLosslesslyConvertibleTo(FT->getReturnType()))
+ return false; // Cannot transform this return value...
+
+ unsigned NumActualArgs = unsigned(CS.arg_end()-CS.arg_begin());
+ unsigned NumCommonArgs = std::min(FT->getNumParams(), NumActualArgs);
+
+ CallSite::arg_iterator AI = CS.arg_begin();
+ for (unsigned i = 0, e = NumCommonArgs; i != e; ++i, ++AI) {
+ const Type *ParamTy = FT->getParamType(i);
+ bool isConvertible = (*AI)->getType()->isLosslesslyConvertibleTo(ParamTy);
+ if (Callee->isExternal() && !isConvertible) return false;
+ }
+
+ if (FT->getNumParams() < NumActualArgs && !FT->isVarArg() &&
+ Callee->isExternal())
+ return false; // Do not delete arguments unless we have a function body...
+
+ // Okay, we decided that this is a safe thing to do: go ahead and start
+ // inserting cast instructions as necessary...
+ std::vector<Value*> Args;
+ Args.reserve(NumActualArgs);
+
+ AI = CS.arg_begin();
+ for (unsigned i = 0; i != NumCommonArgs; ++i, ++AI) {
+ const Type *ParamTy = FT->getParamType(i);
+ if ((*AI)->getType() == ParamTy) {
+ Args.push_back(*AI);
+ } else {
+ Instruction *Cast = new CastInst(*AI, ParamTy, "tmp");
+ InsertNewInstBefore(Cast, *Caller);
+ Args.push_back(Cast);
+ }
+ }
+
+ // If the function takes more arguments than the call was taking, add them
+ // now...
+ for (unsigned i = NumCommonArgs; i != FT->getNumParams(); ++i)
+ Args.push_back(Constant::getNullValue(FT->getParamType(i)));
+
+ // If we are removing arguments to the function, emit an obnoxious warning...
+ if (FT->getNumParams() < NumActualArgs)
+ if (!FT->isVarArg()) {
+ std::cerr << "WARNING: While resolving call to function '"
+ << Callee->getName() << "' arguments were dropped!\n";
+ } else {
+ // Add all of the arguments in their promoted form to the arg list...
+ for (unsigned i = FT->getNumParams(); i != NumActualArgs; ++i, ++AI) {
+ const Type *PTy = getPromotedType((*AI)->getType());
+ if (PTy != (*AI)->getType()) {
+ // Must promote to pass through va_arg area!
+ Instruction *Cast = new CastInst(*AI, PTy, "tmp");
+ InsertNewInstBefore(Cast, *Caller);
+ Args.push_back(Cast);
+ } else {
+ Args.push_back(*AI);
+ }
+ }
+ }
+
+ if (FT->getReturnType() == Type::VoidTy)
+ Caller->setName(""); // Void type should not have a name...
+
+ Instruction *NC;
+ if (InvokeInst *II = dyn_cast<InvokeInst>(Caller)) {
+ NC = new InvokeInst(Callee, II->getNormalDest(), II->getExceptionalDest(),
+ Args, Caller->getName(), Caller);
+ } else {
+ NC = new CallInst(Callee, Args, Caller->getName(), Caller);
+ }
+
+ // Insert a cast of the return type as necessary...
+ Value *NV = NC;
+ if (Caller->getType() != NV->getType() && !Caller->use_empty()) {
+ if (NV->getType() != Type::VoidTy) {
+ NV = NC = new CastInst(NC, Caller->getType(), "tmp");
+ InsertNewInstBefore(NC, *Caller);
+ AddUsesToWorkList(*Caller);
+ } else {
+ NV = Constant::getNullValue(Caller->getType());
+ }
+ }
+
+ if (Caller->getType() != Type::VoidTy && !Caller->use_empty())
+ Caller->replaceAllUsesWith(NV);
+ Caller->getParent()->getInstList().erase(Caller);
+ removeFromWorkList(Caller);
+ return true;
+}
+
// PHINode simplification
More information about the llvm-commits
mailing list