diff --git a/include/llvm/ConstantHandling.h b/include/llvm/ConstantHandling.h index ef0a810b401..2203b9728d5 100644 --- a/include/llvm/ConstantHandling.h +++ b/include/llvm/ConstantHandling.h @@ -72,6 +72,8 @@ public: virtual Constant *mul(const Constant *V1, const Constant *V2) const = 0; virtual Constant *div(const Constant *V1, const Constant *V2) const = 0; virtual Constant *rem(const Constant *V1, const Constant *V2) const = 0; + virtual Constant *shl(const Constant *V1, const Constant *V2) const = 0; + virtual Constant *shr(const Constant *V1, const Constant *V2) const = 0; virtual ConstantBool *lessthan(const Constant *V1, const Constant *V2) const = 0; @@ -155,6 +157,16 @@ inline Constant *operator%(const Constant &V1, const Constant &V2) { return ConstRules::get(V1)->rem(&V1, &V2); } +inline Constant *operator<<(const Constant &V1, const Constant &V2) { + assert(V1.getType()->isIntegral() && V2.getType() == Type::UByteTy); + return ConstRules::get(V1)->shl(&V1, &V2); +} + +inline Constant *operator>>(const Constant &V1, const Constant &V2) { + assert(V1.getType()->isIntegral() && V2.getType() == Type::UByteTy); + return ConstRules::get(V1)->shr(&V1, &V2); +} + inline ConstantBool *operator<(const Constant &V1, const Constant &V2) { assert(V1.getType() == V2.getType() && "Constant types must be identical!"); @@ -219,4 +231,14 @@ inline Constant *ConstantFoldBinaryInstruction(unsigned Opcode, return 0; } +inline Constant *ConstantFoldShiftInstruction(unsigned Opcode, + const Constant *V1, + const Constant *V2) { + switch (Opcode) { + case Instruction::Shl: return *V1 << *V2; + case Instruction::Shr: return *V1 >> *V2; + default: return 0; + } +} + #endif diff --git a/lib/Transforms/Scalar/ConstantProp.cpp b/lib/Transforms/Scalar/ConstantProp.cpp index 77a959910fc..9e519e7cf77 100644 --- a/lib/Transforms/Scalar/ConstantProp.cpp +++ b/lib/Transforms/Scalar/ConstantProp.cpp @@ -97,6 +97,28 @@ ConstantFoldBinaryInst(BasicBlock *BB, BasicBlock::iterator &II, return true; } +inline static bool +ConstantFoldShiftInst(BasicBlock *BB, BasicBlock::iterator &II, + ShiftInst *Op, + Constant *D1, Constant *D2) { + Constant *ReplaceWith = ConstantFoldShiftInstruction(Op->getOpcode(), D1,D2); + if (!ReplaceWith) return false; // Nothing new to change... + + // Replaces all of the uses of a variable with uses of the constant. + Op->replaceAllUsesWith(ReplaceWith); + + // Remove the operator from the list of definitions... + Op->getParent()->getInstList().remove(II); + + // The new constant inherits the old name of the operator... + if (Op->hasName()) + ReplaceWith->setName(Op->getName(), BB->getParent()->getSymbolTableSure()); + + // Delete the operator now... + delete Op; + return true; +} + // ConstantFoldTerminator - If a terminator instruction is predicated on a // constant value, convert it into an unconditional branch to the constant // destination. @@ -157,12 +179,12 @@ bool ConstantFoldTerminator(BasicBlock *BB, BasicBlock::iterator &II, // bool doConstantPropogation(BasicBlock *BB, BasicBlock::iterator &II) { Instruction *Inst = *II; - if (isa(Inst)) { - Constant *D1 = dyn_cast(Inst->getOperand(0)); - Constant *D2 = dyn_cast(Inst->getOperand(1)); + if (BinaryOperator *BO = dyn_cast(Inst)) { + Constant *D1 = dyn_cast(BO->getOperand(0)); + Constant *D2 = dyn_cast(BO->getOperand(1)); if (D1 && D2) - return ConstantFoldBinaryInst(BB, II, cast(Inst), D1, D2); + return ConstantFoldBinaryInst(BB, II, BO, D1, D2); } else if (CastInst *CI = dyn_cast(Inst)) { Constant *D = dyn_cast(CI->getOperand(0)); @@ -188,7 +210,14 @@ bool doConstantPropogation(BasicBlock *BB, BasicBlock::iterator &II) { delete PN; // Finally, delete the node... return true; } + } else if (ShiftInst *SI = dyn_cast(Inst)) { + Constant *D1 = dyn_cast(SI->getOperand(0)); + Constant *D2 = dyn_cast(SI->getOperand(1)); + + if (D1 && D2) + return ConstantFoldShiftInst(BB, II, SI, D1, D2); } + return false; } diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp index 8d1547577b4..015c67a0d22 100644 --- a/lib/Transforms/Scalar/SCCP.cpp +++ b/lib/Transforms/Scalar/SCCP.cpp @@ -502,9 +502,15 @@ void SCCP::visitBinaryOperator(Instruction *I) { if (V1State.isOverdefined() || V2State.isOverdefined()) { markOverdefined(I); } else if (V1State.isConstant() && V2State.isConstant()) { - Constant *Result = ConstantFoldBinaryInstruction(I->getOpcode(), - V1State.getConstant(), - V2State.getConstant()); + Constant *Result = 0; + if (isa(I)) + Result = ConstantFoldBinaryInstruction(I->getOpcode(), + V1State.getConstant(), + V2State.getConstant()); + else if (isa(I)) + Result = ConstantFoldShiftInstruction(I->getOpcode(), + V1State.getConstant(), + V2State.getConstant()); if (Result) markConstant(I, Result); // This instruction constant folds! else diff --git a/lib/VMCore/ConstantFold.h b/lib/VMCore/ConstantFold.h index ef0a810b401..2203b9728d5 100644 --- a/lib/VMCore/ConstantFold.h +++ b/lib/VMCore/ConstantFold.h @@ -72,6 +72,8 @@ public: virtual Constant *mul(const Constant *V1, const Constant *V2) const = 0; virtual Constant *div(const Constant *V1, const Constant *V2) const = 0; virtual Constant *rem(const Constant *V1, const Constant *V2) const = 0; + virtual Constant *shl(const Constant *V1, const Constant *V2) const = 0; + virtual Constant *shr(const Constant *V1, const Constant *V2) const = 0; virtual ConstantBool *lessthan(const Constant *V1, const Constant *V2) const = 0; @@ -155,6 +157,16 @@ inline Constant *operator%(const Constant &V1, const Constant &V2) { return ConstRules::get(V1)->rem(&V1, &V2); } +inline Constant *operator<<(const Constant &V1, const Constant &V2) { + assert(V1.getType()->isIntegral() && V2.getType() == Type::UByteTy); + return ConstRules::get(V1)->shl(&V1, &V2); +} + +inline Constant *operator>>(const Constant &V1, const Constant &V2) { + assert(V1.getType()->isIntegral() && V2.getType() == Type::UByteTy); + return ConstRules::get(V1)->shr(&V1, &V2); +} + inline ConstantBool *operator<(const Constant &V1, const Constant &V2) { assert(V1.getType() == V2.getType() && "Constant types must be identical!"); @@ -219,4 +231,14 @@ inline Constant *ConstantFoldBinaryInstruction(unsigned Opcode, return 0; } +inline Constant *ConstantFoldShiftInstruction(unsigned Opcode, + const Constant *V1, + const Constant *V2) { + switch (Opcode) { + case Instruction::Shl: return *V1 << *V2; + case Instruction::Shr: return *V1 >> *V2; + default: return 0; + } +} + #endif diff --git a/lib/VMCore/ConstantFolding.h b/lib/VMCore/ConstantFolding.h index ef0a810b401..2203b9728d5 100644 --- a/lib/VMCore/ConstantFolding.h +++ b/lib/VMCore/ConstantFolding.h @@ -72,6 +72,8 @@ public: virtual Constant *mul(const Constant *V1, const Constant *V2) const = 0; virtual Constant *div(const Constant *V1, const Constant *V2) const = 0; virtual Constant *rem(const Constant *V1, const Constant *V2) const = 0; + virtual Constant *shl(const Constant *V1, const Constant *V2) const = 0; + virtual Constant *shr(const Constant *V1, const Constant *V2) const = 0; virtual ConstantBool *lessthan(const Constant *V1, const Constant *V2) const = 0; @@ -155,6 +157,16 @@ inline Constant *operator%(const Constant &V1, const Constant &V2) { return ConstRules::get(V1)->rem(&V1, &V2); } +inline Constant *operator<<(const Constant &V1, const Constant &V2) { + assert(V1.getType()->isIntegral() && V2.getType() == Type::UByteTy); + return ConstRules::get(V1)->shl(&V1, &V2); +} + +inline Constant *operator>>(const Constant &V1, const Constant &V2) { + assert(V1.getType()->isIntegral() && V2.getType() == Type::UByteTy); + return ConstRules::get(V1)->shr(&V1, &V2); +} + inline ConstantBool *operator<(const Constant &V1, const Constant &V2) { assert(V1.getType() == V2.getType() && "Constant types must be identical!"); @@ -219,4 +231,14 @@ inline Constant *ConstantFoldBinaryInstruction(unsigned Opcode, return 0; } +inline Constant *ConstantFoldShiftInstruction(unsigned Opcode, + const Constant *V1, + const Constant *V2) { + switch (Opcode) { + case Instruction::Shl: return *V1 << *V2; + case Instruction::Shr: return *V1 >> *V2; + default: return 0; + } +} + #endif