Even more passes being LLVMContext'd.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74781 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Owen Anderson 2009-07-03 19:42:02 +00:00
parent 715029478c
commit fa5cbd6d0f
9 changed files with 235 additions and 181 deletions

View File

@ -178,7 +178,7 @@ public:
const std::vector<Constant*>& V); const std::vector<Constant*>& V);
Constant* getConstantVector(const std::vector<Constant*>& V); Constant* getConstantVector(const std::vector<Constant*>& V);
Constant* getConstantVector(Constant* const* Vals, unsigned NumVals); Constant* getConstantVector(Constant* const* Vals, unsigned NumVals);
ConstantVector* getConstantVectorAllOnes(const VectorType* Ty); ConstantVector* getConstantVectorAllOnesValue(const VectorType* Ty);
// MDNode accessors // MDNode accessors
MDNode* getMDNode(Value* const* Vals, unsigned NumVals); MDNode* getMDNode(Value* const* Vals, unsigned NumVals);

View File

@ -16,6 +16,7 @@
#include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar.h"
#include "llvm/IntrinsicInst.h" #include "llvm/IntrinsicInst.h"
#include "llvm/Instructions.h" #include "llvm/Instructions.h"
#include "llvm/LLVMContext.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/Dominators.h"
@ -35,7 +36,7 @@ STATISTIC(NumMemSetInfer, "Number of memsets inferred");
/// true for all i8 values obviously, but is also true for i32 0, i32 -1, /// true for all i8 values obviously, but is also true for i32 0, i32 -1,
/// i16 0xF0F0, double 0.0 etc. If the value can't be handled with a repeated /// i16 0xF0F0, double 0.0 etc. If the value can't be handled with a repeated
/// byte store (e.g. i16 0x1234), return null. /// byte store (e.g. i16 0x1234), return null.
static Value *isBytewiseValue(Value *V) { static Value *isBytewiseValue(Value *V, LLVMContext* Context) {
// All byte-wide stores are splatable, even of arbitrary variables. // All byte-wide stores are splatable, even of arbitrary variables.
if (V->getType() == Type::Int8Ty) return V; if (V->getType() == Type::Int8Ty) return V;
@ -43,9 +44,9 @@ static Value *isBytewiseValue(Value *V) {
// corresponding integer value is "byteable". An important case is 0.0. // corresponding integer value is "byteable". An important case is 0.0.
if (ConstantFP *CFP = dyn_cast<ConstantFP>(V)) { if (ConstantFP *CFP = dyn_cast<ConstantFP>(V)) {
if (CFP->getType() == Type::FloatTy) if (CFP->getType() == Type::FloatTy)
V = ConstantExpr::getBitCast(CFP, Type::Int32Ty); V = Context->getConstantExprBitCast(CFP, Type::Int32Ty);
if (CFP->getType() == Type::DoubleTy) if (CFP->getType() == Type::DoubleTy)
V = ConstantExpr::getBitCast(CFP, Type::Int64Ty); V = Context->getConstantExprBitCast(CFP, Type::Int64Ty);
// Don't handle long double formats, which have strange constraints. // Don't handle long double formats, which have strange constraints.
} }
@ -68,7 +69,7 @@ static Value *isBytewiseValue(Value *V) {
if (Val != Val2) if (Val != Val2)
return 0; return 0;
} }
return ConstantInt::get(Val); return Context->getConstantInt(Val);
} }
} }
@ -345,7 +346,7 @@ bool MemCpyOpt::processStore(StoreInst *SI, BasicBlock::iterator& BBI) {
// Ensure that the value being stored is something that can be memset'able a // Ensure that the value being stored is something that can be memset'able a
// byte at a time like "0" or "-1" or any width, as well as things like // byte at a time like "0" or "-1" or any width, as well as things like
// 0xA0A0A0A0 and 0.0. // 0xA0A0A0A0 and 0.0.
Value *ByteVal = isBytewiseValue(SI->getOperand(0)); Value *ByteVal = isBytewiseValue(SI->getOperand(0), Context);
if (!ByteVal) if (!ByteVal)
return false; return false;
@ -384,7 +385,7 @@ bool MemCpyOpt::processStore(StoreInst *SI, BasicBlock::iterator& BBI) {
if (NextStore->isVolatile()) break; if (NextStore->isVolatile()) break;
// Check to see if this stored value is of the same byte-splattable value. // Check to see if this stored value is of the same byte-splattable value.
if (ByteVal != isBytewiseValue(NextStore->getOperand(0))) if (ByteVal != isBytewiseValue(NextStore->getOperand(0), Context))
break; break;
// Check to see if this store is to a constant offset from the start ptr. // Check to see if this store is to a constant offset from the start ptr.
@ -438,15 +439,15 @@ bool MemCpyOpt::processStore(StoreInst *SI, BasicBlock::iterator& BBI) {
StartPtr = Range.StartPtr; StartPtr = Range.StartPtr;
// Cast the start ptr to be i8* as memset requires. // Cast the start ptr to be i8* as memset requires.
const Type *i8Ptr = PointerType::getUnqual(Type::Int8Ty); const Type *i8Ptr = Context->getPointerTypeUnqual(Type::Int8Ty);
if (StartPtr->getType() != i8Ptr) if (StartPtr->getType() != i8Ptr)
StartPtr = new BitCastInst(StartPtr, i8Ptr, StartPtr->getNameStart(), StartPtr = new BitCastInst(StartPtr, i8Ptr, StartPtr->getNameStart(),
InsertPt); InsertPt);
Value *Ops[] = { Value *Ops[] = {
StartPtr, ByteVal, // Start, value StartPtr, ByteVal, // Start, value
ConstantInt::get(Type::Int64Ty, Range.End-Range.Start), // size Context->getConstantInt(Type::Int64Ty, Range.End-Range.Start), // size
ConstantInt::get(Type::Int32Ty, Range.Alignment) // align Context->getConstantInt(Type::Int32Ty, Range.Alignment) // align
}; };
Value *C = CallInst::Create(MemSetF, Ops, Ops+4, "", InsertPt); Value *C = CallInst::Create(MemSetF, Ops, Ops+4, "", InsertPt);
DEBUG(cerr << "Replace stores:\n"; DEBUG(cerr << "Replace stores:\n";

View File

@ -27,6 +27,7 @@
#include "llvm/Function.h" #include "llvm/Function.h"
#include "llvm/Instructions.h" #include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h" #include "llvm/IntrinsicInst.h"
#include "llvm/LLVMContext.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Assembly/Writer.h" #include "llvm/Assembly/Writer.h"
#include "llvm/Support/CFG.h" #include "llvm/Support/CFG.h"
@ -198,8 +199,9 @@ static BinaryOperator *isReassociableOp(Value *V, unsigned Opcode) {
/// LowerNegateToMultiply - Replace 0-X with X*-1. /// LowerNegateToMultiply - Replace 0-X with X*-1.
/// ///
static Instruction *LowerNegateToMultiply(Instruction *Neg, static Instruction *LowerNegateToMultiply(Instruction *Neg,
std::map<AssertingVH<>, unsigned> &ValueRankMap) { std::map<AssertingVH<>, unsigned> &ValueRankMap,
Constant *Cst = ConstantInt::getAllOnesValue(Neg->getType()); LLVMContext* Context) {
Constant *Cst = Context->getConstantIntAllOnesValue(Neg->getType());
Instruction *Res = BinaryOperator::CreateMul(Neg->getOperand(1), Cst, "",Neg); Instruction *Res = BinaryOperator::CreateMul(Neg->getOperand(1), Cst, "",Neg);
ValueRankMap.erase(Neg); ValueRankMap.erase(Neg);
@ -263,11 +265,13 @@ void Reassociate::LinearizeExprTree(BinaryOperator *I,
// transform them into multiplies by -1 so they can be reassociated. // transform them into multiplies by -1 so they can be reassociated.
if (I->getOpcode() == Instruction::Mul) { if (I->getOpcode() == Instruction::Mul) {
if (!LHSBO && LHS->hasOneUse() && BinaryOperator::isNeg(LHS)) { if (!LHSBO && LHS->hasOneUse() && BinaryOperator::isNeg(LHS)) {
LHS = LowerNegateToMultiply(cast<Instruction>(LHS), ValueRankMap); LHS = LowerNegateToMultiply(cast<Instruction>(LHS),
ValueRankMap, Context);
LHSBO = isReassociableOp(LHS, Opcode); LHSBO = isReassociableOp(LHS, Opcode);
} }
if (!RHSBO && RHS->hasOneUse() && BinaryOperator::isNeg(RHS)) { if (!RHSBO && RHS->hasOneUse() && BinaryOperator::isNeg(RHS)) {
RHS = LowerNegateToMultiply(cast<Instruction>(RHS), ValueRankMap); RHS = LowerNegateToMultiply(cast<Instruction>(RHS),
ValueRankMap, Context);
RHSBO = isReassociableOp(RHS, Opcode); RHSBO = isReassociableOp(RHS, Opcode);
} }
} }
@ -280,8 +284,8 @@ void Reassociate::LinearizeExprTree(BinaryOperator *I,
Ops.push_back(ValueEntry(getRank(RHS), RHS)); Ops.push_back(ValueEntry(getRank(RHS), RHS));
// Clear the leaves out. // Clear the leaves out.
I->setOperand(0, UndefValue::get(I->getType())); I->setOperand(0, Context->getUndef(I->getType()));
I->setOperand(1, UndefValue::get(I->getType())); I->setOperand(1, Context->getUndef(I->getType()));
return; return;
} else { } else {
// Turn X+(Y+Z) -> (Y+Z)+X // Turn X+(Y+Z) -> (Y+Z)+X
@ -316,7 +320,7 @@ void Reassociate::LinearizeExprTree(BinaryOperator *I,
Ops.push_back(ValueEntry(getRank(RHS), RHS)); Ops.push_back(ValueEntry(getRank(RHS), RHS));
// Clear the RHS leaf out. // Clear the RHS leaf out.
I->setOperand(1, UndefValue::get(I->getType())); I->setOperand(1, Context->getUndef(I->getType()));
} }
// RewriteExprTree - Now that the operands for this expression tree are // RewriteExprTree - Now that the operands for this expression tree are
@ -453,15 +457,17 @@ static Instruction *BreakUpSubtract(Instruction *Sub,
/// by one, change this into a multiply by a constant to assist with further /// by one, change this into a multiply by a constant to assist with further
/// reassociation. /// reassociation.
static Instruction *ConvertShiftToMul(Instruction *Shl, static Instruction *ConvertShiftToMul(Instruction *Shl,
std::map<AssertingVH<>, unsigned> &ValueRankMap) { std::map<AssertingVH<>, unsigned> &ValueRankMap,
LLVMContext* Context) {
// If an operand of this shift is a reassociable multiply, or if the shift // If an operand of this shift is a reassociable multiply, or if the shift
// is used by a reassociable multiply or add, turn into a multiply. // is used by a reassociable multiply or add, turn into a multiply.
if (isReassociableOp(Shl->getOperand(0), Instruction::Mul) || if (isReassociableOp(Shl->getOperand(0), Instruction::Mul) ||
(Shl->hasOneUse() && (Shl->hasOneUse() &&
(isReassociableOp(Shl->use_back(), Instruction::Mul) || (isReassociableOp(Shl->use_back(), Instruction::Mul) ||
isReassociableOp(Shl->use_back(), Instruction::Add)))) { isReassociableOp(Shl->use_back(), Instruction::Add)))) {
Constant *MulCst = ConstantInt::get(Shl->getType(), 1); Constant *MulCst = Context->getConstantInt(Shl->getType(), 1);
MulCst = ConstantExpr::getShl(MulCst, cast<Constant>(Shl->getOperand(1))); MulCst =
Context->getConstantExprShl(MulCst, cast<Constant>(Shl->getOperand(1)));
Instruction *Mul = BinaryOperator::CreateMul(Shl->getOperand(0), MulCst, Instruction *Mul = BinaryOperator::CreateMul(Shl->getOperand(0), MulCst,
"", Shl); "", Shl);
@ -561,7 +567,7 @@ Value *Reassociate::OptimizeExpression(BinaryOperator *I,
if (Constant *V1 = dyn_cast<Constant>(Ops[Ops.size()-2].Op)) if (Constant *V1 = dyn_cast<Constant>(Ops[Ops.size()-2].Op))
if (Constant *V2 = dyn_cast<Constant>(Ops.back().Op)) { if (Constant *V2 = dyn_cast<Constant>(Ops.back().Op)) {
Ops.pop_back(); Ops.pop_back();
Ops.back().Op = ConstantExpr::get(Opcode, V1, V2); Ops.back().Op = Context->getConstantExpr(Opcode, V1, V2);
return OptimizeExpression(I, Ops); return OptimizeExpression(I, Ops);
} }
@ -617,10 +623,10 @@ Value *Reassociate::OptimizeExpression(BinaryOperator *I,
if (FoundX != i) { if (FoundX != i) {
if (Opcode == Instruction::And) { // ...&X&~X = 0 if (Opcode == Instruction::And) { // ...&X&~X = 0
++NumAnnihil; ++NumAnnihil;
return Constant::getNullValue(X->getType()); return Context->getNullValue(X->getType());
} else if (Opcode == Instruction::Or) { // ...|X|~X = -1 } else if (Opcode == Instruction::Or) { // ...|X|~X = -1
++NumAnnihil; ++NumAnnihil;
return ConstantInt::getAllOnesValue(X->getType()); return Context->getConstantIntAllOnesValue(X->getType());
} }
} }
} }
@ -639,7 +645,7 @@ Value *Reassociate::OptimizeExpression(BinaryOperator *I,
assert(Opcode == Instruction::Xor); assert(Opcode == Instruction::Xor);
if (e == 2) { if (e == 2) {
++NumAnnihil; ++NumAnnihil;
return Constant::getNullValue(Ops[0].Op->getType()); return Context->getNullValue(Ops[0].Op->getType());
} }
// ... X^X -> ... // ... X^X -> ...
Ops.erase(Ops.begin()+i, Ops.begin()+i+2); Ops.erase(Ops.begin()+i, Ops.begin()+i+2);
@ -664,7 +670,7 @@ Value *Reassociate::OptimizeExpression(BinaryOperator *I,
// Remove X and -X from the operand list. // Remove X and -X from the operand list.
if (Ops.size() == 2) { if (Ops.size() == 2) {
++NumAnnihil; ++NumAnnihil;
return Constant::getNullValue(X->getType()); return Context->getNullValue(X->getType());
} else { } else {
Ops.erase(Ops.begin()+i); Ops.erase(Ops.begin()+i);
if (i < FoundX) if (i < FoundX)
@ -779,7 +785,7 @@ void Reassociate::ReassociateBB(BasicBlock *BB) {
Instruction *BI = BBI++; Instruction *BI = BBI++;
if (BI->getOpcode() == Instruction::Shl && if (BI->getOpcode() == Instruction::Shl &&
isa<ConstantInt>(BI->getOperand(1))) isa<ConstantInt>(BI->getOperand(1)))
if (Instruction *NI = ConvertShiftToMul(BI, ValueRankMap)) { if (Instruction *NI = ConvertShiftToMul(BI, ValueRankMap, Context)) {
MadeChange = true; MadeChange = true;
BI = NI; BI = NI;
} }
@ -801,7 +807,7 @@ void Reassociate::ReassociateBB(BasicBlock *BB) {
if (isReassociableOp(BI->getOperand(1), Instruction::Mul) && if (isReassociableOp(BI->getOperand(1), Instruction::Mul) &&
(!BI->hasOneUse() || (!BI->hasOneUse() ||
!isReassociableOp(BI->use_back(), Instruction::Mul))) { !isReassociableOp(BI->use_back(), Instruction::Mul))) {
BI = LowerNegateToMultiply(BI, ValueRankMap); BI = LowerNegateToMultiply(BI, ValueRankMap, Context);
MadeChange = true; MadeChange = true;
} }
} }

View File

@ -21,6 +21,7 @@
#include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/Local.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Function.h" #include "llvm/Function.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h" #include "llvm/Module.h"
#include "llvm/BasicBlock.h" #include "llvm/BasicBlock.h"
#include "llvm/Instructions.h" #include "llvm/Instructions.h"
@ -68,7 +69,7 @@ namespace {
CastInst *AllocaInsertionPoint = CastInst *AllocaInsertionPoint =
CastInst::Create(Instruction::BitCast, CastInst::Create(Instruction::BitCast,
Constant::getNullValue(Type::Int32Ty), Type::Int32Ty, Context->getNullValue(Type::Int32Ty), Type::Int32Ty,
"reg2mem alloca point", I); "reg2mem alloca point", I);
// Find the escaped instructions. But don't create stack slots for // Find the escaped instructions. But don't create stack slots for

View File

@ -27,6 +27,7 @@
#include "llvm/Constants.h" #include "llvm/Constants.h"
#include "llvm/DerivedTypes.h" #include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h" #include "llvm/Instructions.h"
#include "llvm/LLVMContext.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/ValueTracking.h" #include "llvm/Analysis/ValueTracking.h"
@ -138,6 +139,7 @@ public:
/// Constant Propagation. /// Constant Propagation.
/// ///
class SCCPSolver : public InstVisitor<SCCPSolver> { class SCCPSolver : public InstVisitor<SCCPSolver> {
LLVMContext* Context;
DenseSet<BasicBlock*> BBExecutable;// The basic blocks that are executable DenseSet<BasicBlock*> BBExecutable;// The basic blocks that are executable
std::map<Value*, LatticeVal> ValueState; // The state each value is in. std::map<Value*, LatticeVal> ValueState; // The state each value is in.
@ -177,6 +179,7 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {
typedef std::pair<BasicBlock*, BasicBlock*> Edge; typedef std::pair<BasicBlock*, BasicBlock*> Edge;
DenseSet<Edge> KnownFeasibleEdges; DenseSet<Edge> KnownFeasibleEdges;
public: public:
void setContext(LLVMContext* C) { Context = C; }
/// MarkBlockExecutable - This method can be used by clients to mark all of /// MarkBlockExecutable - This method can be used by clients to mark all of
/// the blocks that are known to be intrinsically live in the processed unit. /// the blocks that are known to be intrinsically live in the processed unit.
@ -437,7 +440,7 @@ void SCCPSolver::getFeasibleSuccessors(TerminatorInst &TI,
Succs[0] = Succs[1] = true; Succs[0] = Succs[1] = true;
} else if (BCValue.isConstant()) { } else if (BCValue.isConstant()) {
// Constant condition variables mean the branch can only go a single way // Constant condition variables mean the branch can only go a single way
Succs[BCValue.getConstant() == ConstantInt::getFalse()] = true; Succs[BCValue.getConstant() == Context->getConstantIntFalse()] = true;
} }
} }
} else if (isa<InvokeInst>(&TI)) { } else if (isa<InvokeInst>(&TI)) {
@ -482,7 +485,7 @@ bool SCCPSolver::isEdgeFeasible(BasicBlock *From, BasicBlock *To) {
// Constant condition variables mean the branch can only go a single way // Constant condition variables mean the branch can only go a single way
return BI->getSuccessor(BCValue.getConstant() == return BI->getSuccessor(BCValue.getConstant() ==
ConstantInt::getFalse()) == To; Context->getConstantIntFalse()) == To;
} }
return false; return false;
} }
@ -663,7 +666,7 @@ void SCCPSolver::visitCastInst(CastInst &I) {
if (VState.isOverdefined()) // Inherit overdefinedness of operand if (VState.isOverdefined()) // Inherit overdefinedness of operand
markOverdefined(&I); markOverdefined(&I);
else if (VState.isConstant()) // Propagate constant value else if (VState.isConstant()) // Propagate constant value
markConstant(&I, ConstantExpr::getCast(I.getOpcode(), markConstant(&I, Context->getConstantExprCast(I.getOpcode(),
VState.getConstant(), I.getType())); VState.getConstant(), I.getType()));
} }
@ -806,11 +809,12 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) {
if (NonOverdefVal->isUndefined()) { if (NonOverdefVal->isUndefined()) {
// Could annihilate value. // Could annihilate value.
if (I.getOpcode() == Instruction::And) if (I.getOpcode() == Instruction::And)
markConstant(IV, &I, Constant::getNullValue(I.getType())); markConstant(IV, &I, Context->getNullValue(I.getType()));
else if (const VectorType *PT = dyn_cast<VectorType>(I.getType())) else if (const VectorType *PT = dyn_cast<VectorType>(I.getType()))
markConstant(IV, &I, ConstantVector::getAllOnesValue(PT)); markConstant(IV, &I, Context->getConstantVectorAllOnesValue(PT));
else else
markConstant(IV, &I, ConstantInt::getAllOnesValue(I.getType())); markConstant(IV, &I,
Context->getConstantIntAllOnesValue(I.getType()));
return; return;
} else { } else {
if (I.getOpcode() == Instruction::And) { if (I.getOpcode() == Instruction::And) {
@ -854,7 +858,8 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) {
Result.markOverdefined(); Result.markOverdefined();
break; // Cannot fold this operation over the PHI nodes! break; // Cannot fold this operation over the PHI nodes!
} else if (In1.isConstant() && In2.isConstant()) { } else if (In1.isConstant() && In2.isConstant()) {
Constant *V = ConstantExpr::get(I.getOpcode(), In1.getConstant(), Constant *V =
Context->getConstantExpr(I.getOpcode(), In1.getConstant(),
In2.getConstant()); In2.getConstant());
if (Result.isUndefined()) if (Result.isUndefined())
Result.markConstant(V); Result.markConstant(V);
@ -902,7 +907,8 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) {
markOverdefined(IV, &I); markOverdefined(IV, &I);
} else if (V1State.isConstant() && V2State.isConstant()) { } else if (V1State.isConstant() && V2State.isConstant()) {
markConstant(IV, &I, ConstantExpr::get(I.getOpcode(), V1State.getConstant(), markConstant(IV, &I,
Context->getConstantExpr(I.getOpcode(), V1State.getConstant(),
V2State.getConstant())); V2State.getConstant()));
} }
} }
@ -939,7 +945,7 @@ void SCCPSolver::visitCmpInst(CmpInst &I) {
Result.markOverdefined(); Result.markOverdefined();
break; // Cannot fold this operation over the PHI nodes! break; // Cannot fold this operation over the PHI nodes!
} else if (In1.isConstant() && In2.isConstant()) { } else if (In1.isConstant() && In2.isConstant()) {
Constant *V = ConstantExpr::getCompare(I.getPredicate(), Constant *V = Context->getConstantExprCompare(I.getPredicate(),
In1.getConstant(), In1.getConstant(),
In2.getConstant()); In2.getConstant());
if (Result.isUndefined()) if (Result.isUndefined())
@ -988,7 +994,7 @@ void SCCPSolver::visitCmpInst(CmpInst &I) {
markOverdefined(IV, &I); markOverdefined(IV, &I);
} else if (V1State.isConstant() && V2State.isConstant()) { } else if (V1State.isConstant() && V2State.isConstant()) {
markConstant(IV, &I, ConstantExpr::getCompare(I.getPredicate(), markConstant(IV, &I, Context->getConstantExprCompare(I.getPredicate(),
V1State.getConstant(), V1State.getConstant(),
V2State.getConstant())); V2State.getConstant()));
} }
@ -1090,7 +1096,7 @@ void SCCPSolver::visitGetElementPtrInst(GetElementPtrInst &I) {
Constant *Ptr = Operands[0]; Constant *Ptr = Operands[0];
Operands.erase(Operands.begin()); // Erase the pointer from idx list... Operands.erase(Operands.begin()); // Erase the pointer from idx list...
markConstant(IV, &I, ConstantExpr::getGetElementPtr(Ptr, &Operands[0], markConstant(IV, &I, Context->getConstantExprGetElementPtr(Ptr, &Operands[0],
Operands.size())); Operands.size()));
} }
@ -1124,7 +1130,7 @@ void SCCPSolver::visitLoadInst(LoadInst &I) {
if (isa<ConstantPointerNull>(Ptr) && if (isa<ConstantPointerNull>(Ptr) &&
cast<PointerType>(Ptr->getType())->getAddressSpace() == 0) { cast<PointerType>(Ptr->getType())->getAddressSpace() == 0) {
// load null -> null // load null -> null
markConstant(IV, &I, Constant::getNullValue(I.getType())); markConstant(IV, &I, Context->getNullValue(I.getType()));
return; return;
} }
@ -1365,21 +1371,22 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
// to be handled here, because we don't know whether the top part is 1's // to be handled here, because we don't know whether the top part is 1's
// or 0's. // or 0's.
assert(Op0LV.isUndefined()); assert(Op0LV.isUndefined());
markForcedConstant(LV, I, Constant::getNullValue(ITy)); markForcedConstant(LV, I, Context->getNullValue(ITy));
return true; return true;
case Instruction::Mul: case Instruction::Mul:
case Instruction::And: case Instruction::And:
// undef * X -> 0. X could be zero. // undef * X -> 0. X could be zero.
// undef & X -> 0. X could be zero. // undef & X -> 0. X could be zero.
markForcedConstant(LV, I, Constant::getNullValue(ITy)); markForcedConstant(LV, I, Context->getNullValue(ITy));
return true; return true;
case Instruction::Or: case Instruction::Or:
// undef | X -> -1. X could be -1. // undef | X -> -1. X could be -1.
if (const VectorType *PTy = dyn_cast<VectorType>(ITy)) if (const VectorType *PTy = dyn_cast<VectorType>(ITy))
markForcedConstant(LV, I, ConstantVector::getAllOnesValue(PTy)); markForcedConstant(LV, I,
Context->getConstantVectorAllOnesValue(PTy));
else else
markForcedConstant(LV, I, ConstantInt::getAllOnesValue(ITy)); markForcedConstant(LV, I, Context->getConstantIntAllOnesValue(ITy));
return true; return true;
case Instruction::SDiv: case Instruction::SDiv:
@ -1392,7 +1399,7 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
// undef / X -> 0. X could be maxint. // undef / X -> 0. X could be maxint.
// undef % X -> 0. X could be 1. // undef % X -> 0. X could be 1.
markForcedConstant(LV, I, Constant::getNullValue(ITy)); markForcedConstant(LV, I, Context->getNullValue(ITy));
return true; return true;
case Instruction::AShr: case Instruction::AShr:
@ -1413,7 +1420,7 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
// X >> undef -> 0. X could be 0. // X >> undef -> 0. X could be 0.
// X << undef -> 0. X could be 0. // X << undef -> 0. X could be 0.
markForcedConstant(LV, I, Constant::getNullValue(ITy)); markForcedConstant(LV, I, Context->getNullValue(ITy));
return true; return true;
case Instruction::Select: case Instruction::Select:
// undef ? X : Y -> X or Y. There could be commonality between X/Y. // undef ? X : Y -> X or Y. There could be commonality between X/Y.
@ -1476,7 +1483,7 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) {
// as undef, then further analysis could think the undef went another way // as undef, then further analysis could think the undef went another way
// leading to an inconsistent set of conclusions. // leading to an inconsistent set of conclusions.
if (BranchInst *BI = dyn_cast<BranchInst>(TI)) { if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
BI->setCondition(ConstantInt::getFalse()); BI->setCondition(Context->getConstantIntFalse());
} else { } else {
SwitchInst *SI = cast<SwitchInst>(TI); SwitchInst *SI = cast<SwitchInst>(TI);
SI->setCondition(SI->getCaseValue(1)); SI->setCondition(SI->getCaseValue(1));
@ -1526,6 +1533,7 @@ FunctionPass *llvm::createSCCPPass() {
bool SCCP::runOnFunction(Function &F) { bool SCCP::runOnFunction(Function &F) {
DOUT << "SCCP on function '" << F.getNameStart() << "'\n"; DOUT << "SCCP on function '" << F.getNameStart() << "'\n";
SCCPSolver Solver; SCCPSolver Solver;
Solver.setContext(Context);
// Mark the first block of the function as being executable. // Mark the first block of the function as being executable.
Solver.MarkBlockExecutable(F.begin()); Solver.MarkBlockExecutable(F.begin());
@ -1565,7 +1573,7 @@ bool SCCP::runOnFunction(Function &F) {
Instruction *I = Insts.back(); Instruction *I = Insts.back();
Insts.pop_back(); Insts.pop_back();
if (!I->use_empty()) if (!I->use_empty())
I->replaceAllUsesWith(UndefValue::get(I->getType())); I->replaceAllUsesWith(Context->getUndef(I->getType()));
BB->getInstList().erase(I); BB->getInstList().erase(I);
MadeChanges = true; MadeChanges = true;
++NumInstRemoved; ++NumInstRemoved;
@ -1585,7 +1593,7 @@ bool SCCP::runOnFunction(Function &F) {
continue; continue;
Constant *Const = IV.isConstant() Constant *Const = IV.isConstant()
? IV.getConstant() : UndefValue::get(Inst->getType()); ? IV.getConstant() : Context->getUndef(Inst->getType());
DOUT << " Constant: " << *Const << " = " << *Inst; DOUT << " Constant: " << *Const << " = " << *Inst;
// Replaces all of the uses of a variable with uses of the constant. // Replaces all of the uses of a variable with uses of the constant.
@ -1701,7 +1709,7 @@ bool IPSCCP::runOnModule(Module &M) {
LatticeVal &IV = Values[AI]; LatticeVal &IV = Values[AI];
if (IV.isConstant() || IV.isUndefined()) { if (IV.isConstant() || IV.isUndefined()) {
Constant *CST = IV.isConstant() ? Constant *CST = IV.isConstant() ?
IV.getConstant() : UndefValue::get(AI->getType()); IV.getConstant() : Context->getUndef(AI->getType());
DOUT << "*** Arg " << *AI << " = " << *CST <<"\n"; DOUT << "*** Arg " << *AI << " = " << *CST <<"\n";
// Replaces all of the uses of a variable with uses of the // Replaces all of the uses of a variable with uses of the
@ -1726,7 +1734,7 @@ bool IPSCCP::runOnModule(Module &M) {
Instruction *I = Insts.back(); Instruction *I = Insts.back();
Insts.pop_back(); Insts.pop_back();
if (!I->use_empty()) if (!I->use_empty())
I->replaceAllUsesWith(UndefValue::get(I->getType())); I->replaceAllUsesWith(Context->getUndef(I->getType()));
BB->getInstList().erase(I); BB->getInstList().erase(I);
MadeChanges = true; MadeChanges = true;
++IPNumInstRemoved; ++IPNumInstRemoved;
@ -1738,7 +1746,7 @@ bool IPSCCP::runOnModule(Module &M) {
TI->getSuccessor(i)->removePredecessor(BB); TI->getSuccessor(i)->removePredecessor(BB);
} }
if (!TI->use_empty()) if (!TI->use_empty())
TI->replaceAllUsesWith(UndefValue::get(TI->getType())); TI->replaceAllUsesWith(Context->getUndef(TI->getType()));
BB->getInstList().erase(TI); BB->getInstList().erase(TI);
if (&*BB != &F->front()) if (&*BB != &F->front())
@ -1757,7 +1765,7 @@ bool IPSCCP::runOnModule(Module &M) {
continue; continue;
Constant *Const = IV.isConstant() Constant *Const = IV.isConstant()
? IV.getConstant() : UndefValue::get(Inst->getType()); ? IV.getConstant() : Context->getUndef(Inst->getType());
DOUT << " Constant: " << *Const << " = " << *Inst; DOUT << " Constant: " << *Const << " = " << *Inst;
// Replaces all of the uses of a variable with uses of the // Replaces all of the uses of a variable with uses of the
@ -1831,7 +1839,7 @@ bool IPSCCP::runOnModule(Module &M) {
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator()))
if (!isa<UndefValue>(RI->getOperand(0))) if (!isa<UndefValue>(RI->getOperand(0)))
RI->setOperand(0, UndefValue::get(F->getReturnType())); RI->setOperand(0, Context->getUndef(F->getReturnType()));
} }
// If we infered constant or undef values for globals variables, we can delete // If we infered constant or undef values for globals variables, we can delete

View File

@ -27,6 +27,7 @@
#include "llvm/GlobalVariable.h" #include "llvm/GlobalVariable.h"
#include "llvm/Instructions.h" #include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h" #include "llvm/IntrinsicInst.h"
#include "llvm/LLVMContext.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/Dominators.h"
#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetData.h"
@ -240,7 +241,8 @@ bool SROA::performScalarRepl(Function &F) {
DOUT << "Found alloca equal to global: " << *AI; DOUT << "Found alloca equal to global: " << *AI;
DOUT << " memcpy = " << *TheCopy; DOUT << " memcpy = " << *TheCopy;
Constant *TheSrc = cast<Constant>(TheCopy->getOperand(2)); Constant *TheSrc = cast<Constant>(TheCopy->getOperand(2));
AI->replaceAllUsesWith(ConstantExpr::getBitCast(TheSrc, AI->getType())); AI->replaceAllUsesWith(
Context->getConstantExprBitCast(TheSrc, AI->getType()));
TheCopy->eraseFromParent(); // Don't mutate the global. TheCopy->eraseFromParent(); // Don't mutate the global.
AI->eraseFromParent(); AI->eraseFromParent();
++NumGlobals; ++NumGlobals;
@ -305,7 +307,7 @@ bool SROA::performScalarRepl(Function &F) {
DOUT << "CONVERT TO SCALAR INTEGER: " << *AI << "\n"; DOUT << "CONVERT TO SCALAR INTEGER: " << *AI << "\n";
// Create and insert the integer alloca. // Create and insert the integer alloca.
const Type *NewTy = IntegerType::get(AllocaSize*8); const Type *NewTy = Context->getIntegerType(AllocaSize*8);
NewAI = new AllocaInst(NewTy, 0, "", AI->getParent()->begin()); NewAI = new AllocaInst(NewTy, 0, "", AI->getParent()->begin());
ConvertUsesToScalar(AI, NewAI, 0); ConvertUsesToScalar(AI, NewAI, 0);
} }
@ -369,7 +371,7 @@ void SROA::DoScalarReplacement(AllocationInst *AI,
// %insert = insertvalue { i32, i32 } %insert.0, i32 %load.1, 1 // %insert = insertvalue { i32, i32 } %insert.0, i32 %load.1, 1
// (Also works for arrays instead of structs) // (Also works for arrays instead of structs)
if (LoadInst *LI = dyn_cast<LoadInst>(User)) { if (LoadInst *LI = dyn_cast<LoadInst>(User)) {
Value *Insert = UndefValue::get(LI->getType()); Value *Insert = Context->getUndef(LI->getType());
for (unsigned i = 0, e = ElementAllocas.size(); i != e; ++i) { for (unsigned i = 0, e = ElementAllocas.size(); i != e; ++i) {
Value *Load = new LoadInst(ElementAllocas[i], "load", LI); Value *Load = new LoadInst(ElementAllocas[i], "load", LI);
Insert = InsertValueInst::Create(Insert, Load, i, "insert", LI); Insert = InsertValueInst::Create(Insert, Load, i, "insert", LI);
@ -416,7 +418,7 @@ void SROA::DoScalarReplacement(AllocationInst *AI,
// expanded itself once the worklist is rerun. // expanded itself once the worklist is rerun.
// //
SmallVector<Value*, 8> NewArgs; SmallVector<Value*, 8> NewArgs;
NewArgs.push_back(Constant::getNullValue(Type::Int32Ty)); NewArgs.push_back(Context->getNullValue(Type::Int32Ty));
NewArgs.append(GEPI->op_begin()+3, GEPI->op_end()); NewArgs.append(GEPI->op_begin()+3, GEPI->op_end());
RepValue = GetElementPtrInst::Create(AllocaToUse, NewArgs.begin(), RepValue = GetElementPtrInst::Create(AllocaToUse, NewArgs.begin(),
NewArgs.end(), "", GEPI); NewArgs.end(), "", GEPI);
@ -529,7 +531,7 @@ void SROA::isSafeUseOfAllocation(Instruction *User, AllocationInst *AI,
// The GEP is not safe to transform if not of the form "GEP <ptr>, 0, <cst>". // The GEP is not safe to transform if not of the form "GEP <ptr>, 0, <cst>".
if (I == E || if (I == E ||
I.getOperand() != Constant::getNullValue(I.getOperand()->getType())) { I.getOperand() != Context->getNullValue(I.getOperand()->getType())) {
return MarkUnsafe(Info); return MarkUnsafe(Info);
} }
@ -762,7 +764,7 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *BCInst,
const Type *BytePtrTy = MI->getRawDest()->getType(); const Type *BytePtrTy = MI->getRawDest()->getType();
bool SROADest = MI->getRawDest() == BCInst; bool SROADest = MI->getRawDest() == BCInst;
Constant *Zero = Constant::getNullValue(Type::Int32Ty); Constant *Zero = Context->getNullValue(Type::Int32Ty);
for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { for (unsigned i = 0, e = NewElts.size(); i != e; ++i) {
// If this is a memcpy/memmove, emit a GEP of the other element address. // If this is a memcpy/memmove, emit a GEP of the other element address.
@ -770,7 +772,7 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *BCInst,
unsigned OtherEltAlign = MemAlignment; unsigned OtherEltAlign = MemAlignment;
if (OtherPtr) { if (OtherPtr) {
Value *Idx[2] = { Zero, ConstantInt::get(Type::Int32Ty, i) }; Value *Idx[2] = { Zero, Context->getConstantInt(Type::Int32Ty, i) };
OtherElt = GetElementPtrInst::Create(OtherPtr, Idx, Idx + 2, OtherElt = GetElementPtrInst::Create(OtherPtr, Idx, Idx + 2,
OtherPtr->getNameStr()+"."+utostr(i), OtherPtr->getNameStr()+"."+utostr(i),
MI); MI);
@ -817,7 +819,7 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *BCInst,
Constant *StoreVal; Constant *StoreVal;
if (ConstantInt *CI = dyn_cast<ConstantInt>(MI->getOperand(2))) { if (ConstantInt *CI = dyn_cast<ConstantInt>(MI->getOperand(2))) {
if (CI->isZero()) { if (CI->isZero()) {
StoreVal = Constant::getNullValue(EltTy); // 0.0, null, 0, <0,0> StoreVal = Context->getNullValue(EltTy); // 0.0, null, 0, <0,0>
} else { } else {
// If EltTy is a vector type, get the element type. // If EltTy is a vector type, get the element type.
const Type *ValTy = EltTy->getScalarType(); const Type *ValTy = EltTy->getScalarType();
@ -833,18 +835,18 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *BCInst,
} }
// Convert the integer value to the appropriate type. // Convert the integer value to the appropriate type.
StoreVal = ConstantInt::get(TotalVal); StoreVal = Context->getConstantInt(TotalVal);
if (isa<PointerType>(ValTy)) if (isa<PointerType>(ValTy))
StoreVal = ConstantExpr::getIntToPtr(StoreVal, ValTy); StoreVal = Context->getConstantExprIntToPtr(StoreVal, ValTy);
else if (ValTy->isFloatingPoint()) else if (ValTy->isFloatingPoint())
StoreVal = ConstantExpr::getBitCast(StoreVal, ValTy); StoreVal = Context->getConstantExprBitCast(StoreVal, ValTy);
assert(StoreVal->getType() == ValTy && "Type mismatch!"); assert(StoreVal->getType() == ValTy && "Type mismatch!");
// If the requested value was a vector constant, create it. // If the requested value was a vector constant, create it.
if (EltTy != ValTy) { if (EltTy != ValTy) {
unsigned NumElts = cast<VectorType>(ValTy)->getNumElements(); unsigned NumElts = cast<VectorType>(ValTy)->getNumElements();
SmallVector<Constant*, 16> Elts(NumElts, StoreVal); SmallVector<Constant*, 16> Elts(NumElts, StoreVal);
StoreVal = ConstantVector::get(&Elts[0], NumElts); StoreVal = Context->getConstantVector(&Elts[0], NumElts);
} }
} }
new StoreInst(StoreVal, EltPtr, MI); new StoreInst(StoreVal, EltPtr, MI);
@ -870,15 +872,15 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *BCInst,
Value *Ops[] = { Value *Ops[] = {
SROADest ? EltPtr : OtherElt, // Dest ptr SROADest ? EltPtr : OtherElt, // Dest ptr
SROADest ? OtherElt : EltPtr, // Src ptr SROADest ? OtherElt : EltPtr, // Src ptr
ConstantInt::get(MI->getOperand(3)->getType(), EltSize), // Size Context->getConstantInt(MI->getOperand(3)->getType(), EltSize), // Size
ConstantInt::get(Type::Int32Ty, OtherEltAlign) // Align Context->getConstantInt(Type::Int32Ty, OtherEltAlign) // Align
}; };
CallInst::Create(TheFn, Ops, Ops + 4, "", MI); CallInst::Create(TheFn, Ops, Ops + 4, "", MI);
} else { } else {
assert(isa<MemSetInst>(MI)); assert(isa<MemSetInst>(MI));
Value *Ops[] = { Value *Ops[] = {
EltPtr, MI->getOperand(2), // Dest, Value, EltPtr, MI->getOperand(2), // Dest, Value,
ConstantInt::get(MI->getOperand(3)->getType(), EltSize), // Size Context->getConstantInt(MI->getOperand(3)->getType(), EltSize), // Size
Zero // Align Zero // Align
}; };
CallInst::Create(TheFn, Ops, Ops + 4, "", MI); CallInst::Create(TheFn, Ops, Ops + 4, "", MI);
@ -907,7 +909,8 @@ void SROA::RewriteStoreUserOfWholeAlloca(StoreInst *SI,
return; return;
// Handle tail padding by extending the operand // Handle tail padding by extending the operand
if (TD->getTypeSizeInBits(SrcVal->getType()) != AllocaSizeBits) if (TD->getTypeSizeInBits(SrcVal->getType()) != AllocaSizeBits)
SrcVal = new ZExtInst(SrcVal, IntegerType::get(AllocaSizeBits), "", SI); SrcVal = new ZExtInst(SrcVal,
Context->getIntegerType(AllocaSizeBits), "", SI);
DOUT << "PROMOTING STORE TO WHOLE ALLOCA: " << *AI << *SI; DOUT << "PROMOTING STORE TO WHOLE ALLOCA: " << *AI << *SI;
@ -926,7 +929,7 @@ void SROA::RewriteStoreUserOfWholeAlloca(StoreInst *SI,
Value *EltVal = SrcVal; Value *EltVal = SrcVal;
if (Shift) { if (Shift) {
Value *ShiftVal = ConstantInt::get(EltVal->getType(), Shift); Value *ShiftVal = Context->getConstantInt(EltVal->getType(), Shift);
EltVal = BinaryOperator::CreateLShr(EltVal, ShiftVal, EltVal = BinaryOperator::CreateLShr(EltVal, ShiftVal,
"sroa.store.elt", SI); "sroa.store.elt", SI);
} }
@ -938,7 +941,8 @@ void SROA::RewriteStoreUserOfWholeAlloca(StoreInst *SI,
if (FieldSizeBits == 0) continue; if (FieldSizeBits == 0) continue;
if (FieldSizeBits != AllocaSizeBits) if (FieldSizeBits != AllocaSizeBits)
EltVal = new TruncInst(EltVal, IntegerType::get(FieldSizeBits), "", SI); EltVal = new TruncInst(EltVal,
Context->getIntegerType(FieldSizeBits), "", SI);
Value *DestField = NewElts[i]; Value *DestField = NewElts[i];
if (EltVal->getType() == FieldTy) { if (EltVal->getType() == FieldTy) {
// Storing to an integer field of this size, just do it. // Storing to an integer field of this size, just do it.
@ -948,7 +952,7 @@ void SROA::RewriteStoreUserOfWholeAlloca(StoreInst *SI,
} else { } else {
// Otherwise, bitcast the dest pointer (for aggregates). // Otherwise, bitcast the dest pointer (for aggregates).
DestField = new BitCastInst(DestField, DestField = new BitCastInst(DestField,
PointerType::getUnqual(EltVal->getType()), Context->getPointerTypeUnqual(EltVal->getType()),
"", SI); "", SI);
} }
new StoreInst(EltVal, DestField, SI); new StoreInst(EltVal, DestField, SI);
@ -973,14 +977,15 @@ void SROA::RewriteStoreUserOfWholeAlloca(StoreInst *SI,
Value *EltVal = SrcVal; Value *EltVal = SrcVal;
if (Shift) { if (Shift) {
Value *ShiftVal = ConstantInt::get(EltVal->getType(), Shift); Value *ShiftVal = Context->getConstantInt(EltVal->getType(), Shift);
EltVal = BinaryOperator::CreateLShr(EltVal, ShiftVal, EltVal = BinaryOperator::CreateLShr(EltVal, ShiftVal,
"sroa.store.elt", SI); "sroa.store.elt", SI);
} }
// Truncate down to an integer of the right size. // Truncate down to an integer of the right size.
if (ElementSizeBits != AllocaSizeBits) if (ElementSizeBits != AllocaSizeBits)
EltVal = new TruncInst(EltVal, IntegerType::get(ElementSizeBits),"",SI); EltVal = new TruncInst(EltVal,
Context->getIntegerType(ElementSizeBits),"",SI);
Value *DestField = NewElts[i]; Value *DestField = NewElts[i];
if (EltVal->getType() == ArrayEltTy) { if (EltVal->getType() == ArrayEltTy) {
// Storing to an integer field of this size, just do it. // Storing to an integer field of this size, just do it.
@ -990,7 +995,7 @@ void SROA::RewriteStoreUserOfWholeAlloca(StoreInst *SI,
} else { } else {
// Otherwise, bitcast the dest pointer (for aggregates). // Otherwise, bitcast the dest pointer (for aggregates).
DestField = new BitCastInst(DestField, DestField = new BitCastInst(DestField,
PointerType::getUnqual(EltVal->getType()), Context->getPointerTypeUnqual(EltVal->getType()),
"", SI); "", SI);
} }
new StoreInst(EltVal, DestField, SI); new StoreInst(EltVal, DestField, SI);
@ -1034,7 +1039,8 @@ void SROA::RewriteLoadUserOfWholeAlloca(LoadInst *LI, AllocationInst *AI,
ArrayEltBitOffset = TD->getTypeAllocSizeInBits(ArrayEltTy); ArrayEltBitOffset = TD->getTypeAllocSizeInBits(ArrayEltTy);
} }
Value *ResultVal = Constant::getNullValue(IntegerType::get(AllocaSizeBits)); Value *ResultVal =
Context->getNullValue(Context->getIntegerType(AllocaSizeBits));
for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { for (unsigned i = 0, e = NewElts.size(); i != e; ++i) {
// Load the value from the alloca. If the NewElt is an aggregate, cast // Load the value from the alloca. If the NewElt is an aggregate, cast
@ -1047,10 +1053,11 @@ void SROA::RewriteLoadUserOfWholeAlloca(LoadInst *LI, AllocationInst *AI,
// Ignore zero sized fields like {}, they obviously contain no data. // Ignore zero sized fields like {}, they obviously contain no data.
if (FieldSizeBits == 0) continue; if (FieldSizeBits == 0) continue;
const IntegerType *FieldIntTy = IntegerType::get(FieldSizeBits); const IntegerType *FieldIntTy = Context->getIntegerType(FieldSizeBits);
if (!isa<IntegerType>(FieldTy) && !FieldTy->isFloatingPoint() && if (!isa<IntegerType>(FieldTy) && !FieldTy->isFloatingPoint() &&
!isa<VectorType>(FieldTy)) !isa<VectorType>(FieldTy))
SrcField = new BitCastInst(SrcField, PointerType::getUnqual(FieldIntTy), SrcField = new BitCastInst(SrcField,
Context->getPointerTypeUnqual(FieldIntTy),
"", LI); "", LI);
SrcField = new LoadInst(SrcField, "sroa.load.elt", LI); SrcField = new LoadInst(SrcField, "sroa.load.elt", LI);
@ -1075,7 +1082,7 @@ void SROA::RewriteLoadUserOfWholeAlloca(LoadInst *LI, AllocationInst *AI,
Shift = AllocaSizeBits-Shift-FieldIntTy->getBitWidth(); Shift = AllocaSizeBits-Shift-FieldIntTy->getBitWidth();
if (Shift) { if (Shift) {
Value *ShiftVal = ConstantInt::get(SrcField->getType(), Shift); Value *ShiftVal = Context->getConstantInt(SrcField->getType(), Shift);
SrcField = BinaryOperator::CreateShl(SrcField, ShiftVal, "", LI); SrcField = BinaryOperator::CreateShl(SrcField, ShiftVal, "", LI);
} }
@ -1179,7 +1186,7 @@ void SROA::CleanupGEP(GetElementPtrInst *GEPI) {
return; return;
if (NumElements == 1) { if (NumElements == 1) {
GEPI->setOperand(2, Constant::getNullValue(Type::Int32Ty)); GEPI->setOperand(2, Context->getNullValue(Type::Int32Ty));
return; return;
} }
@ -1187,16 +1194,16 @@ void SROA::CleanupGEP(GetElementPtrInst *GEPI) {
// All users of the GEP must be loads. At each use of the GEP, insert // All users of the GEP must be loads. At each use of the GEP, insert
// two loads of the appropriate indexed GEP and select between them. // two loads of the appropriate indexed GEP and select between them.
Value *IsOne = new ICmpInst(ICmpInst::ICMP_NE, I.getOperand(), Value *IsOne = new ICmpInst(ICmpInst::ICMP_NE, I.getOperand(),
Constant::getNullValue(I.getOperand()->getType()), Context->getNullValue(I.getOperand()->getType()),
"isone", GEPI); "isone", GEPI);
// Insert the new GEP instructions, which are properly indexed. // Insert the new GEP instructions, which are properly indexed.
SmallVector<Value*, 8> Indices(GEPI->op_begin()+1, GEPI->op_end()); SmallVector<Value*, 8> Indices(GEPI->op_begin()+1, GEPI->op_end());
Indices[1] = Constant::getNullValue(Type::Int32Ty); Indices[1] = Context->getNullValue(Type::Int32Ty);
Value *ZeroIdx = GetElementPtrInst::Create(GEPI->getOperand(0), Value *ZeroIdx = GetElementPtrInst::Create(GEPI->getOperand(0),
Indices.begin(), Indices.begin(),
Indices.end(), Indices.end(),
GEPI->getName()+".0", GEPI); GEPI->getName()+".0", GEPI);
Indices[1] = ConstantInt::get(Type::Int32Ty, 1); Indices[1] = Context->getConstantInt(Type::Int32Ty, 1);
Value *OneIdx = GetElementPtrInst::Create(GEPI->getOperand(0), Value *OneIdx = GetElementPtrInst::Create(GEPI->getOperand(0),
Indices.begin(), Indices.begin(),
Indices.end(), Indices.end(),
@ -1253,7 +1260,8 @@ void SROA::CleanupAllocaUsers(AllocationInst *AI) {
/// large) integer type with extract and insert operations where the loads /// large) integer type with extract and insert operations where the loads
/// and stores would mutate the memory. /// and stores would mutate the memory.
static void MergeInType(const Type *In, uint64_t Offset, const Type *&VecTy, static void MergeInType(const Type *In, uint64_t Offset, const Type *&VecTy,
unsigned AllocaSize, const TargetData &TD) { unsigned AllocaSize, const TargetData &TD,
LLVMContext* Context) {
// If this could be contributing to a vector, analyze it. // If this could be contributing to a vector, analyze it.
if (VecTy != Type::VoidTy) { // either null or a vector type. if (VecTy != Type::VoidTy) { // either null or a vector type.
@ -1281,7 +1289,7 @@ static void MergeInType(const Type *In, uint64_t Offset, const Type *&VecTy,
cast<VectorType>(VecTy)->getElementType() cast<VectorType>(VecTy)->getElementType()
->getPrimitiveSizeInBits()/8 == EltSize)) { ->getPrimitiveSizeInBits()/8 == EltSize)) {
if (VecTy == 0) if (VecTy == 0)
VecTy = VectorType::get(In, AllocaSize/EltSize); VecTy = Context->getVectorType(In, AllocaSize/EltSize);
return; return;
} }
} }
@ -1312,7 +1320,7 @@ bool SROA::CanConvertToScalar(Value *V, bool &IsNotTrivial, const Type *&VecTy,
// Don't break volatile loads. // Don't break volatile loads.
if (LI->isVolatile()) if (LI->isVolatile())
return false; return false;
MergeInType(LI->getType(), Offset, VecTy, AllocaSize, *TD); MergeInType(LI->getType(), Offset, VecTy, AllocaSize, *TD, Context);
SawVec |= isa<VectorType>(LI->getType()); SawVec |= isa<VectorType>(LI->getType());
continue; continue;
} }
@ -1320,7 +1328,8 @@ bool SROA::CanConvertToScalar(Value *V, bool &IsNotTrivial, const Type *&VecTy,
if (StoreInst *SI = dyn_cast<StoreInst>(User)) { if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
// Storing the pointer, not into the value? // Storing the pointer, not into the value?
if (SI->getOperand(0) == V || SI->isVolatile()) return 0; if (SI->getOperand(0) == V || SI->isVolatile()) return 0;
MergeInType(SI->getOperand(0)->getType(), Offset, VecTy, AllocaSize, *TD); MergeInType(SI->getOperand(0)->getType(), Offset,
VecTy, AllocaSize, *TD, Context);
SawVec |= isa<VectorType>(SI->getOperand(0)->getType()); SawVec |= isa<VectorType>(SI->getOperand(0)->getType());
continue; continue;
} }
@ -1449,8 +1458,8 @@ void SROA::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, uint64_t Offset) {
APVal |= APVal << 8; APVal |= APVal << 8;
Value *Old = Builder.CreateLoad(NewAI, (NewAI->getName()+".in").c_str()); Value *Old = Builder.CreateLoad(NewAI, (NewAI->getName()+".in").c_str());
Value *New = ConvertScalar_InsertValue(ConstantInt::get(APVal), Old, Value *New = ConvertScalar_InsertValue(Context->getConstantInt(APVal),
Offset, Builder); Old, Offset, Builder);
Builder.CreateStore(New, NewAI); Builder.CreateStore(New, NewAI);
} }
MSI->eraseFromParent(); MSI->eraseFromParent();
@ -1537,7 +1546,7 @@ Value *SROA::ConvertScalar_ExtractValue(Value *FromVal, const Type *ToType,
} }
// Return the element extracted out of it. // Return the element extracted out of it.
Value *V = Builder.CreateExtractElement(FromVal, Value *V = Builder.CreateExtractElement(FromVal,
ConstantInt::get(Type::Int32Ty,Elt), Context->getConstantInt(Type::Int32Ty,Elt),
"tmp"); "tmp");
if (V->getType() != ToType) if (V->getType() != ToType)
V = Builder.CreateBitCast(V, ToType, "tmp"); V = Builder.CreateBitCast(V, ToType, "tmp");
@ -1548,7 +1557,7 @@ Value *SROA::ConvertScalar_ExtractValue(Value *FromVal, const Type *ToType,
// use insertvalue's to form the FCA. // use insertvalue's to form the FCA.
if (const StructType *ST = dyn_cast<StructType>(ToType)) { if (const StructType *ST = dyn_cast<StructType>(ToType)) {
const StructLayout &Layout = *TD->getStructLayout(ST); const StructLayout &Layout = *TD->getStructLayout(ST);
Value *Res = UndefValue::get(ST); Value *Res = Context->getUndef(ST);
for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) {
Value *Elt = ConvertScalar_ExtractValue(FromVal, ST->getElementType(i), Value *Elt = ConvertScalar_ExtractValue(FromVal, ST->getElementType(i),
Offset+Layout.getElementOffsetInBits(i), Offset+Layout.getElementOffsetInBits(i),
@ -1560,7 +1569,7 @@ Value *SROA::ConvertScalar_ExtractValue(Value *FromVal, const Type *ToType,
if (const ArrayType *AT = dyn_cast<ArrayType>(ToType)) { if (const ArrayType *AT = dyn_cast<ArrayType>(ToType)) {
uint64_t EltSize = TD->getTypeAllocSizeInBits(AT->getElementType()); uint64_t EltSize = TD->getTypeAllocSizeInBits(AT->getElementType());
Value *Res = UndefValue::get(AT); Value *Res = Context->getUndef(AT);
for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) { for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) {
Value *Elt = ConvertScalar_ExtractValue(FromVal, AT->getElementType(), Value *Elt = ConvertScalar_ExtractValue(FromVal, AT->getElementType(),
Offset+i*EltSize, Builder); Offset+i*EltSize, Builder);
@ -1589,18 +1598,22 @@ Value *SROA::ConvertScalar_ExtractValue(Value *FromVal, const Type *ToType,
// We do this to support (f.e.) loads off the end of a structure where // We do this to support (f.e.) loads off the end of a structure where
// only some bits are used. // only some bits are used.
if (ShAmt > 0 && (unsigned)ShAmt < NTy->getBitWidth()) if (ShAmt > 0 && (unsigned)ShAmt < NTy->getBitWidth())
FromVal = Builder.CreateLShr(FromVal, ConstantInt::get(FromVal->getType(), FromVal = Builder.CreateLShr(FromVal,
Context->getConstantInt(FromVal->getType(),
ShAmt), "tmp"); ShAmt), "tmp");
else if (ShAmt < 0 && (unsigned)-ShAmt < NTy->getBitWidth()) else if (ShAmt < 0 && (unsigned)-ShAmt < NTy->getBitWidth())
FromVal = Builder.CreateShl(FromVal, ConstantInt::get(FromVal->getType(), FromVal = Builder.CreateShl(FromVal,
Context->getConstantInt(FromVal->getType(),
-ShAmt), "tmp"); -ShAmt), "tmp");
// Finally, unconditionally truncate the integer to the right width. // Finally, unconditionally truncate the integer to the right width.
unsigned LIBitWidth = TD->getTypeSizeInBits(ToType); unsigned LIBitWidth = TD->getTypeSizeInBits(ToType);
if (LIBitWidth < NTy->getBitWidth()) if (LIBitWidth < NTy->getBitWidth())
FromVal = Builder.CreateTrunc(FromVal, IntegerType::get(LIBitWidth), "tmp"); FromVal =
Builder.CreateTrunc(FromVal, Context->getIntegerType(LIBitWidth), "tmp");
else if (LIBitWidth > NTy->getBitWidth()) else if (LIBitWidth > NTy->getBitWidth())
FromVal = Builder.CreateZExt(FromVal, IntegerType::get(LIBitWidth), "tmp"); FromVal =
Builder.CreateZExt(FromVal, Context->getIntegerType(LIBitWidth), "tmp");
// If the result is an integer, this is a trunc or bitcast. // If the result is an integer, this is a trunc or bitcast.
if (isa<IntegerType>(ToType)) { if (isa<IntegerType>(ToType)) {
@ -1651,7 +1664,7 @@ Value *SROA::ConvertScalar_InsertValue(Value *SV, Value *Old,
SV = Builder.CreateBitCast(SV, VTy->getElementType(), "tmp"); SV = Builder.CreateBitCast(SV, VTy->getElementType(), "tmp");
SV = Builder.CreateInsertElement(Old, SV, SV = Builder.CreateInsertElement(Old, SV,
ConstantInt::get(Type::Int32Ty, Elt), Context->getConstantInt(Type::Int32Ty, Elt),
"tmp"); "tmp");
return SV; return SV;
} }
@ -1684,7 +1697,7 @@ Value *SROA::ConvertScalar_InsertValue(Value *SV, Value *Old,
unsigned SrcStoreWidth = TD->getTypeStoreSizeInBits(SV->getType()); unsigned SrcStoreWidth = TD->getTypeStoreSizeInBits(SV->getType());
unsigned DestStoreWidth = TD->getTypeStoreSizeInBits(AllocaType); unsigned DestStoreWidth = TD->getTypeStoreSizeInBits(AllocaType);
if (SV->getType()->isFloatingPoint() || isa<VectorType>(SV->getType())) if (SV->getType()->isFloatingPoint() || isa<VectorType>(SV->getType()))
SV = Builder.CreateBitCast(SV, IntegerType::get(SrcWidth), "tmp"); SV = Builder.CreateBitCast(SV, Context->getIntegerType(SrcWidth), "tmp");
else if (isa<PointerType>(SV->getType())) else if (isa<PointerType>(SV->getType()))
SV = Builder.CreatePtrToInt(SV, TD->getIntPtrType(), "tmp"); SV = Builder.CreatePtrToInt(SV, TD->getIntPtrType(), "tmp");
@ -1719,10 +1732,12 @@ Value *SROA::ConvertScalar_InsertValue(Value *SV, Value *Old,
// only some bits in the structure are set. // only some bits in the structure are set.
APInt Mask(APInt::getLowBitsSet(DestWidth, SrcWidth)); APInt Mask(APInt::getLowBitsSet(DestWidth, SrcWidth));
if (ShAmt > 0 && (unsigned)ShAmt < DestWidth) { if (ShAmt > 0 && (unsigned)ShAmt < DestWidth) {
SV = Builder.CreateShl(SV, ConstantInt::get(SV->getType(), ShAmt), "tmp"); SV = Builder.CreateShl(SV, Context->getConstantInt(SV->getType(),
ShAmt), "tmp");
Mask <<= ShAmt; Mask <<= ShAmt;
} else if (ShAmt < 0 && (unsigned)-ShAmt < DestWidth) { } else if (ShAmt < 0 && (unsigned)-ShAmt < DestWidth) {
SV = Builder.CreateLShr(SV, ConstantInt::get(SV->getType(), -ShAmt), "tmp"); SV = Builder.CreateLShr(SV, Context->getConstantInt(SV->getType(),
-ShAmt), "tmp");
Mask = Mask.lshr(-ShAmt); Mask = Mask.lshr(-ShAmt);
} }
@ -1730,7 +1745,7 @@ Value *SROA::ConvertScalar_InsertValue(Value *SV, Value *Old,
// in the new bits. // in the new bits.
if (SrcWidth != DestWidth) { if (SrcWidth != DestWidth) {
assert(DestWidth > SrcWidth); assert(DestWidth > SrcWidth);
Old = Builder.CreateAnd(Old, ConstantInt::get(~Mask), "mask"); Old = Builder.CreateAnd(Old, Context->getConstantInt(~Mask), "mask");
SV = Builder.CreateOr(Old, SV, "ins"); SV = Builder.CreateOr(Old, SV, "ins");
} }
return SV; return SV;

View File

@ -26,6 +26,7 @@
#include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/Local.h"
#include "llvm/Constants.h" #include "llvm/Constants.h"
#include "llvm/Instructions.h" #include "llvm/Instructions.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h" #include "llvm/Module.h"
#include "llvm/Attributes.h" #include "llvm/Attributes.h"
#include "llvm/Support/CFG.h" #include "llvm/Support/CFG.h"
@ -57,7 +58,7 @@ FunctionPass *llvm::createCFGSimplificationPass() {
/// ChangeToUnreachable - Insert an unreachable instruction before the specified /// ChangeToUnreachable - Insert an unreachable instruction before the specified
/// instruction, making it and the rest of the code in the block dead. /// instruction, making it and the rest of the code in the block dead.
static void ChangeToUnreachable(Instruction *I) { static void ChangeToUnreachable(Instruction *I, LLVMContext* Context) {
BasicBlock *BB = I->getParent(); BasicBlock *BB = I->getParent();
// Loop over all of the successors, removing BB's entry from any PHI // Loop over all of the successors, removing BB's entry from any PHI
// nodes. // nodes.
@ -70,7 +71,7 @@ static void ChangeToUnreachable(Instruction *I) {
BasicBlock::iterator BBI = I, BBE = BB->end(); BasicBlock::iterator BBI = I, BBE = BB->end();
while (BBI != BBE) { while (BBI != BBE) {
if (!BBI->use_empty()) if (!BBI->use_empty())
BBI->replaceAllUsesWith(UndefValue::get(BBI->getType())); BBI->replaceAllUsesWith(Context->getUndef(BBI->getType()));
BB->getInstList().erase(BBI++); BB->getInstList().erase(BBI++);
} }
} }
@ -95,7 +96,8 @@ static void ChangeToCall(InvokeInst *II) {
} }
static bool MarkAliveBlocks(BasicBlock *BB, static bool MarkAliveBlocks(BasicBlock *BB,
SmallPtrSet<BasicBlock*, 128> &Reachable) { SmallPtrSet<BasicBlock*, 128> &Reachable,
LLVMContext* Context) {
SmallVector<BasicBlock*, 128> Worklist; SmallVector<BasicBlock*, 128> Worklist;
Worklist.push_back(BB); Worklist.push_back(BB);
@ -118,7 +120,7 @@ static bool MarkAliveBlocks(BasicBlock *BB,
// though. // though.
++BBI; ++BBI;
if (!isa<UnreachableInst>(BBI)) { if (!isa<UnreachableInst>(BBI)) {
ChangeToUnreachable(BBI); ChangeToUnreachable(BBI, Context);
Changed = true; Changed = true;
} }
break; break;
@ -131,7 +133,7 @@ static bool MarkAliveBlocks(BasicBlock *BB,
if (isa<UndefValue>(Ptr) || if (isa<UndefValue>(Ptr) ||
(isa<ConstantPointerNull>(Ptr) && (isa<ConstantPointerNull>(Ptr) &&
cast<PointerType>(Ptr->getType())->getAddressSpace() == 0)) { cast<PointerType>(Ptr->getType())->getAddressSpace() == 0)) {
ChangeToUnreachable(SI); ChangeToUnreachable(SI, Context);
Changed = true; Changed = true;
break; break;
} }
@ -157,7 +159,7 @@ static bool MarkAliveBlocks(BasicBlock *BB,
/// otherwise. /// otherwise.
static bool RemoveUnreachableBlocksFromFn(Function &F) { static bool RemoveUnreachableBlocksFromFn(Function &F) {
SmallPtrSet<BasicBlock*, 128> Reachable; SmallPtrSet<BasicBlock*, 128> Reachable;
bool Changed = MarkAliveBlocks(F.begin(), Reachable); bool Changed = MarkAliveBlocks(F.begin(), Reachable, F.getContext());
// If there are unreachable blocks in the CFG... // If there are unreachable blocks in the CFG...
if (Reachable.size() == F.size()) if (Reachable.size() == F.size())

View File

@ -20,6 +20,7 @@
#define DEBUG_TYPE "simplify-libcalls" #define DEBUG_TYPE "simplify-libcalls"
#include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar.h"
#include "llvm/Intrinsics.h" #include "llvm/Intrinsics.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h" #include "llvm/Module.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Support/IRBuilder.h" #include "llvm/Support/IRBuilder.h"
@ -47,6 +48,7 @@ class VISIBILITY_HIDDEN LibCallOptimization {
protected: protected:
Function *Caller; Function *Caller;
const TargetData *TD; const TargetData *TD;
LLVMContext* Context;
public: public:
LibCallOptimization() { } LibCallOptimization() { }
virtual ~LibCallOptimization() {} virtual ~LibCallOptimization() {}
@ -62,6 +64,8 @@ public:
Value *OptimizeCall(CallInst *CI, const TargetData &TD, IRBuilder<> &B) { Value *OptimizeCall(CallInst *CI, const TargetData &TD, IRBuilder<> &B) {
Caller = CI->getParent()->getParent(); Caller = CI->getParent()->getParent();
this->TD = &TD; this->TD = &TD;
if (CI->getCalledFunction())
Context = CI->getCalledFunction()->getContext();
return CallOptimizer(CI->getCalledFunction(), CI, B); return CallOptimizer(CI->getCalledFunction(), CI, B);
} }
@ -119,7 +123,8 @@ public:
/// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*. /// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*.
Value *LibCallOptimization::CastToCStr(Value *V, IRBuilder<> &B) { Value *LibCallOptimization::CastToCStr(Value *V, IRBuilder<> &B) {
return B.CreateBitCast(V, PointerType::getUnqual(Type::Int8Ty), "cstr"); return
B.CreateBitCast(V, Context->getPointerTypeUnqual(Type::Int8Ty), "cstr");
} }
/// EmitStrLen - Emit a call to the strlen function to the builder, for the /// EmitStrLen - Emit a call to the strlen function to the builder, for the
@ -133,7 +138,7 @@ Value *LibCallOptimization::EmitStrLen(Value *Ptr, IRBuilder<> &B) {
Constant *StrLen =M->getOrInsertFunction("strlen", AttrListPtr::get(AWI, 2), Constant *StrLen =M->getOrInsertFunction("strlen", AttrListPtr::get(AWI, 2),
TD->getIntPtrType(), TD->getIntPtrType(),
PointerType::getUnqual(Type::Int8Ty), Context->getPointerTypeUnqual(Type::Int8Ty),
NULL); NULL);
CallInst *CI = B.CreateCall(StrLen, CastToCStr(Ptr, B), "strlen"); CallInst *CI = B.CreateCall(StrLen, CastToCStr(Ptr, B), "strlen");
if (const Function *F = dyn_cast<Function>(StrLen->stripPointerCasts())) if (const Function *F = dyn_cast<Function>(StrLen->stripPointerCasts()))
@ -152,7 +157,7 @@ Value *LibCallOptimization::EmitMemCpy(Value *Dst, Value *Src, Value *Len,
Tys[0] = Len->getType(); Tys[0] = Len->getType();
Value *MemCpy = Intrinsic::getDeclaration(M, IID, Tys, 1); Value *MemCpy = Intrinsic::getDeclaration(M, IID, Tys, 1);
return B.CreateCall4(MemCpy, CastToCStr(Dst, B), CastToCStr(Src, B), Len, return B.CreateCall4(MemCpy, CastToCStr(Dst, B), CastToCStr(Src, B), Len,
ConstantInt::get(Type::Int32Ty, Align)); Context->getConstantInt(Type::Int32Ty, Align));
} }
/// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is /// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is
@ -164,8 +169,8 @@ Value *LibCallOptimization::EmitMemChr(Value *Ptr, Value *Val,
AWI = AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind); AWI = AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind);
Value *MemChr = M->getOrInsertFunction("memchr", AttrListPtr::get(&AWI, 1), Value *MemChr = M->getOrInsertFunction("memchr", AttrListPtr::get(&AWI, 1),
PointerType::getUnqual(Type::Int8Ty), Context->getPointerTypeUnqual(Type::Int8Ty),
PointerType::getUnqual(Type::Int8Ty), Context->getPointerTypeUnqual(Type::Int8Ty),
Type::Int32Ty, TD->getIntPtrType(), Type::Int32Ty, TD->getIntPtrType(),
NULL); NULL);
CallInst *CI = B.CreateCall3(MemChr, CastToCStr(Ptr, B), Val, Len, "memchr"); CallInst *CI = B.CreateCall3(MemChr, CastToCStr(Ptr, B), Val, Len, "memchr");
@ -188,8 +193,8 @@ Value *LibCallOptimization::EmitMemCmp(Value *Ptr1, Value *Ptr2,
Value *MemCmp = M->getOrInsertFunction("memcmp", AttrListPtr::get(AWI, 3), Value *MemCmp = M->getOrInsertFunction("memcmp", AttrListPtr::get(AWI, 3),
Type::Int32Ty, Type::Int32Ty,
PointerType::getUnqual(Type::Int8Ty), Context->getPointerTypeUnqual(Type::Int8Ty),
PointerType::getUnqual(Type::Int8Ty), Context->getPointerTypeUnqual(Type::Int8Ty),
TD->getIntPtrType(), NULL); TD->getIntPtrType(), NULL);
CallInst *CI = B.CreateCall3(MemCmp, CastToCStr(Ptr1, B), CastToCStr(Ptr2, B), CallInst *CI = B.CreateCall3(MemCmp, CastToCStr(Ptr1, B), CastToCStr(Ptr2, B),
Len, "memcmp"); Len, "memcmp");
@ -208,7 +213,7 @@ Value *LibCallOptimization::EmitMemSet(Value *Dst, Value *Val,
const Type *Tys[1]; const Type *Tys[1];
Tys[0] = Len->getType(); Tys[0] = Len->getType();
Value *MemSet = Intrinsic::getDeclaration(M, IID, Tys, 1); Value *MemSet = Intrinsic::getDeclaration(M, IID, Tys, 1);
Value *Align = ConstantInt::get(Type::Int32Ty, 1); Value *Align = Context->getConstantInt(Type::Int32Ty, 1);
return B.CreateCall4(MemSet, CastToCStr(Dst, B), Val, Len, Align); return B.CreateCall4(MemSet, CastToCStr(Dst, B), Val, Len, Align);
} }
@ -267,7 +272,7 @@ void LibCallOptimization::EmitPutS(Value *Str, IRBuilder<> &B) {
Value *PutS = M->getOrInsertFunction("puts", AttrListPtr::get(AWI, 2), Value *PutS = M->getOrInsertFunction("puts", AttrListPtr::get(AWI, 2),
Type::Int32Ty, Type::Int32Ty,
PointerType::getUnqual(Type::Int8Ty), Context->getPointerTypeUnqual(Type::Int8Ty),
NULL); NULL);
CallInst *CI = B.CreateCall(PutS, CastToCStr(Str, B), "puts"); CallInst *CI = B.CreateCall(PutS, CastToCStr(Str, B), "puts");
if (const Function *F = dyn_cast<Function>(PutS->stripPointerCasts())) if (const Function *F = dyn_cast<Function>(PutS->stripPointerCasts()))
@ -307,11 +312,11 @@ void LibCallOptimization::EmitFPutS(Value *Str, Value *File, IRBuilder<> &B) {
Constant *F; Constant *F;
if (isa<PointerType>(File->getType())) if (isa<PointerType>(File->getType()))
F = M->getOrInsertFunction("fputs", AttrListPtr::get(AWI, 3), Type::Int32Ty, F = M->getOrInsertFunction("fputs", AttrListPtr::get(AWI, 3), Type::Int32Ty,
PointerType::getUnqual(Type::Int8Ty), Context->getPointerTypeUnqual(Type::Int8Ty),
File->getType(), NULL); File->getType(), NULL);
else else
F = M->getOrInsertFunction("fputs", Type::Int32Ty, F = M->getOrInsertFunction("fputs", Type::Int32Ty,
PointerType::getUnqual(Type::Int8Ty), Context->getPointerTypeUnqual(Type::Int8Ty),
File->getType(), NULL); File->getType(), NULL);
CallInst *CI = B.CreateCall2(F, CastToCStr(Str, B), File, "fputs"); CallInst *CI = B.CreateCall2(F, CastToCStr(Str, B), File, "fputs");
@ -332,16 +337,16 @@ void LibCallOptimization::EmitFWrite(Value *Ptr, Value *Size, Value *File,
if (isa<PointerType>(File->getType())) if (isa<PointerType>(File->getType()))
F = M->getOrInsertFunction("fwrite", AttrListPtr::get(AWI, 3), F = M->getOrInsertFunction("fwrite", AttrListPtr::get(AWI, 3),
TD->getIntPtrType(), TD->getIntPtrType(),
PointerType::getUnqual(Type::Int8Ty), Context->getPointerTypeUnqual(Type::Int8Ty),
TD->getIntPtrType(), TD->getIntPtrType(), TD->getIntPtrType(), TD->getIntPtrType(),
File->getType(), NULL); File->getType(), NULL);
else else
F = M->getOrInsertFunction("fwrite", TD->getIntPtrType(), F = M->getOrInsertFunction("fwrite", TD->getIntPtrType(),
PointerType::getUnqual(Type::Int8Ty), Context->getPointerTypeUnqual(Type::Int8Ty),
TD->getIntPtrType(), TD->getIntPtrType(), TD->getIntPtrType(), TD->getIntPtrType(),
File->getType(), NULL); File->getType(), NULL);
CallInst *CI = B.CreateCall4(F, CastToCStr(Ptr, B), Size, CallInst *CI = B.CreateCall4(F, CastToCStr(Ptr, B), Size,
ConstantInt::get(TD->getIntPtrType(), 1), File); Context->getConstantInt(TD->getIntPtrType(), 1), File);
if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts())) if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
CI->setCallingConv(Fn->getCallingConv()); CI->setCallingConv(Fn->getCallingConv());
@ -540,7 +545,7 @@ struct VISIBILITY_HIDDEN StrCatOpt : public LibCallOptimization {
// Verify the "strcat" function prototype. // Verify the "strcat" function prototype.
const FunctionType *FT = Callee->getFunctionType(); const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 || if (FT->getNumParams() != 2 ||
FT->getReturnType() != PointerType::getUnqual(Type::Int8Ty) || FT->getReturnType() != Context->getPointerTypeUnqual(Type::Int8Ty) ||
FT->getParamType(0) != FT->getReturnType() || FT->getParamType(0) != FT->getReturnType() ||
FT->getParamType(1) != FT->getReturnType()) FT->getParamType(1) != FT->getReturnType())
return 0; return 0;
@ -574,7 +579,8 @@ struct VISIBILITY_HIDDEN StrCatOpt : public LibCallOptimization {
// We have enough information to now generate the memcpy call to do the // We have enough information to now generate the memcpy call to do the
// concatenation for us. Make a memcpy to copy the nul byte with align = 1. // concatenation for us. Make a memcpy to copy the nul byte with align = 1.
EmitMemCpy(CpyDst, Src, ConstantInt::get(TD->getIntPtrType(), Len+1), 1, B); EmitMemCpy(CpyDst, Src,
Context->getConstantInt(TD->getIntPtrType(), Len+1), 1, B);
} }
}; };
@ -586,7 +592,7 @@ struct VISIBILITY_HIDDEN StrNCatOpt : public StrCatOpt {
// Verify the "strncat" function prototype. // Verify the "strncat" function prototype.
const FunctionType *FT = Callee->getFunctionType(); const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 || if (FT->getNumParams() != 3 ||
FT->getReturnType() != PointerType::getUnqual(Type::Int8Ty) || FT->getReturnType() != Context->getPointerTypeUnqual(Type::Int8Ty) ||
FT->getParamType(0) != FT->getReturnType() || FT->getParamType(0) != FT->getReturnType() ||
FT->getParamType(1) != FT->getReturnType() || FT->getParamType(1) != FT->getReturnType() ||
!isa<IntegerType>(FT->getParamType(2))) !isa<IntegerType>(FT->getParamType(2)))
@ -631,7 +637,7 @@ struct VISIBILITY_HIDDEN StrChrOpt : public LibCallOptimization {
// Verify the "strchr" function prototype. // Verify the "strchr" function prototype.
const FunctionType *FT = Callee->getFunctionType(); const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 || if (FT->getNumParams() != 2 ||
FT->getReturnType() != PointerType::getUnqual(Type::Int8Ty) || FT->getReturnType() != Context->getPointerTypeUnqual(Type::Int8Ty) ||
FT->getParamType(0) != FT->getReturnType()) FT->getParamType(0) != FT->getReturnType())
return 0; return 0;
@ -646,7 +652,7 @@ struct VISIBILITY_HIDDEN StrChrOpt : public LibCallOptimization {
return 0; return 0;
return EmitMemChr(SrcStr, CI->getOperand(2), // include nul. return EmitMemChr(SrcStr, CI->getOperand(2), // include nul.
ConstantInt::get(TD->getIntPtrType(), Len), B); Context->getConstantInt(TD->getIntPtrType(), Len), B);
} }
// Otherwise, the character is a constant, see if the first argument is // Otherwise, the character is a constant, see if the first argument is
@ -663,7 +669,7 @@ struct VISIBILITY_HIDDEN StrChrOpt : public LibCallOptimization {
uint64_t i = 0; uint64_t i = 0;
while (1) { while (1) {
if (i == Str.size()) // Didn't find the char. strchr returns null. if (i == Str.size()) // Didn't find the char. strchr returns null.
return Constant::getNullValue(CI->getType()); return Context->getNullValue(CI->getType());
// Did we find our match? // Did we find our match?
if (Str[i] == CharValue) if (Str[i] == CharValue)
break; break;
@ -671,7 +677,7 @@ struct VISIBILITY_HIDDEN StrChrOpt : public LibCallOptimization {
} }
// strchr(s+n,c) -> gep(s+n+i,c) // strchr(s+n,c) -> gep(s+n+i,c)
Value *Idx = ConstantInt::get(Type::Int64Ty, i); Value *Idx = Context->getConstantInt(Type::Int64Ty, i);
return B.CreateGEP(SrcStr, Idx, "strchr"); return B.CreateGEP(SrcStr, Idx, "strchr");
} }
}; };
@ -685,12 +691,12 @@ struct VISIBILITY_HIDDEN StrCmpOpt : public LibCallOptimization {
const FunctionType *FT = Callee->getFunctionType(); const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 || FT->getReturnType() != Type::Int32Ty || if (FT->getNumParams() != 2 || FT->getReturnType() != Type::Int32Ty ||
FT->getParamType(0) != FT->getParamType(1) || FT->getParamType(0) != FT->getParamType(1) ||
FT->getParamType(0) != PointerType::getUnqual(Type::Int8Ty)) FT->getParamType(0) != Context->getPointerTypeUnqual(Type::Int8Ty))
return 0; return 0;
Value *Str1P = CI->getOperand(1), *Str2P = CI->getOperand(2); Value *Str1P = CI->getOperand(1), *Str2P = CI->getOperand(2);
if (Str1P == Str2P) // strcmp(x,x) -> 0 if (Str1P == Str2P) // strcmp(x,x) -> 0
return ConstantInt::get(CI->getType(), 0); return Context->getConstantInt(CI->getType(), 0);
std::string Str1, Str2; std::string Str1, Str2;
bool HasStr1 = GetConstantStringInfo(Str1P, Str1); bool HasStr1 = GetConstantStringInfo(Str1P, Str1);
@ -704,14 +710,15 @@ struct VISIBILITY_HIDDEN StrCmpOpt : public LibCallOptimization {
// strcmp(x, y) -> cnst (if both x and y are constant strings) // strcmp(x, y) -> cnst (if both x and y are constant strings)
if (HasStr1 && HasStr2) if (HasStr1 && HasStr2)
return ConstantInt::get(CI->getType(), strcmp(Str1.c_str(),Str2.c_str())); return Context->getConstantInt(CI->getType(),
strcmp(Str1.c_str(),Str2.c_str()));
// strcmp(P, "x") -> memcmp(P, "x", 2) // strcmp(P, "x") -> memcmp(P, "x", 2)
uint64_t Len1 = GetStringLength(Str1P); uint64_t Len1 = GetStringLength(Str1P);
uint64_t Len2 = GetStringLength(Str2P); uint64_t Len2 = GetStringLength(Str2P);
if (Len1 && Len2) { if (Len1 && Len2) {
return EmitMemCmp(Str1P, Str2P, return EmitMemCmp(Str1P, Str2P,
ConstantInt::get(TD->getIntPtrType(), Context->getConstantInt(TD->getIntPtrType(),
std::min(Len1, Len2)), B); std::min(Len1, Len2)), B);
} }
@ -728,13 +735,13 @@ struct VISIBILITY_HIDDEN StrNCmpOpt : public LibCallOptimization {
const FunctionType *FT = Callee->getFunctionType(); const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 || FT->getReturnType() != Type::Int32Ty || if (FT->getNumParams() != 3 || FT->getReturnType() != Type::Int32Ty ||
FT->getParamType(0) != FT->getParamType(1) || FT->getParamType(0) != FT->getParamType(1) ||
FT->getParamType(0) != PointerType::getUnqual(Type::Int8Ty) || FT->getParamType(0) != Context->getPointerTypeUnqual(Type::Int8Ty) ||
!isa<IntegerType>(FT->getParamType(2))) !isa<IntegerType>(FT->getParamType(2)))
return 0; return 0;
Value *Str1P = CI->getOperand(1), *Str2P = CI->getOperand(2); Value *Str1P = CI->getOperand(1), *Str2P = CI->getOperand(2);
if (Str1P == Str2P) // strncmp(x,x,n) -> 0 if (Str1P == Str2P) // strncmp(x,x,n) -> 0
return ConstantInt::get(CI->getType(), 0); return Context->getConstantInt(CI->getType(), 0);
// Get the length argument if it is constant. // Get the length argument if it is constant.
uint64_t Length; uint64_t Length;
@ -744,7 +751,7 @@ struct VISIBILITY_HIDDEN StrNCmpOpt : public LibCallOptimization {
return 0; return 0;
if (Length == 0) // strncmp(x,y,0) -> 0 if (Length == 0) // strncmp(x,y,0) -> 0
return ConstantInt::get(CI->getType(), 0); return Context->getConstantInt(CI->getType(), 0);
std::string Str1, Str2; std::string Str1, Str2;
bool HasStr1 = GetConstantStringInfo(Str1P, Str1); bool HasStr1 = GetConstantStringInfo(Str1P, Str1);
@ -758,7 +765,7 @@ struct VISIBILITY_HIDDEN StrNCmpOpt : public LibCallOptimization {
// strncmp(x, y) -> cnst (if both x and y are constant strings) // strncmp(x, y) -> cnst (if both x and y are constant strings)
if (HasStr1 && HasStr2) if (HasStr1 && HasStr2)
return ConstantInt::get(CI->getType(), return Context->getConstantInt(CI->getType(),
strncmp(Str1.c_str(), Str2.c_str(), Length)); strncmp(Str1.c_str(), Str2.c_str(), Length));
return 0; return 0;
} }
@ -774,7 +781,7 @@ struct VISIBILITY_HIDDEN StrCpyOpt : public LibCallOptimization {
const FunctionType *FT = Callee->getFunctionType(); const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 2 || FT->getReturnType() != FT->getParamType(0) || if (FT->getNumParams() != 2 || FT->getReturnType() != FT->getParamType(0) ||
FT->getParamType(0) != FT->getParamType(1) || FT->getParamType(0) != FT->getParamType(1) ||
FT->getParamType(0) != PointerType::getUnqual(Type::Int8Ty)) FT->getParamType(0) != Context->getPointerTypeUnqual(Type::Int8Ty))
return 0; return 0;
Value *Dst = CI->getOperand(1), *Src = CI->getOperand(2); Value *Dst = CI->getOperand(1), *Src = CI->getOperand(2);
@ -787,7 +794,8 @@ struct VISIBILITY_HIDDEN StrCpyOpt : public LibCallOptimization {
// We have enough information to now generate the memcpy call to do the // We have enough information to now generate the memcpy call to do the
// concatenation for us. Make a memcpy to copy the nul byte with align = 1. // concatenation for us. Make a memcpy to copy the nul byte with align = 1.
EmitMemCpy(Dst, Src, ConstantInt::get(TD->getIntPtrType(), Len), 1, B); EmitMemCpy(Dst, Src,
Context->getConstantInt(TD->getIntPtrType(), Len), 1, B);
return Dst; return Dst;
} }
}; };
@ -800,7 +808,7 @@ struct VISIBILITY_HIDDEN StrNCpyOpt : public LibCallOptimization {
const FunctionType *FT = Callee->getFunctionType(); const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) || if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) ||
FT->getParamType(0) != FT->getParamType(1) || FT->getParamType(0) != FT->getParamType(1) ||
FT->getParamType(0) != PointerType::getUnqual(Type::Int8Ty) || FT->getParamType(0) != Context->getPointerTypeUnqual(Type::Int8Ty) ||
!isa<IntegerType>(FT->getParamType(2))) !isa<IntegerType>(FT->getParamType(2)))
return 0; return 0;
@ -815,7 +823,7 @@ struct VISIBILITY_HIDDEN StrNCpyOpt : public LibCallOptimization {
if (SrcLen == 0) { if (SrcLen == 0) {
// strncpy(x, "", y) -> memset(x, '\0', y, 1) // strncpy(x, "", y) -> memset(x, '\0', y, 1)
EmitMemSet(Dst, ConstantInt::get(Type::Int8Ty, '\0'), LenOp, B); EmitMemSet(Dst, Context->getConstantInt(Type::Int8Ty, '\0'), LenOp, B);
return Dst; return Dst;
} }
@ -831,7 +839,8 @@ struct VISIBILITY_HIDDEN StrNCpyOpt : public LibCallOptimization {
if (Len > SrcLen+1) return 0; if (Len > SrcLen+1) return 0;
// strncpy(x, s, c) -> memcpy(x, s, c, 1) [s and c are constant] // strncpy(x, s, c) -> memcpy(x, s, c, 1) [s and c are constant]
EmitMemCpy(Dst, Src, ConstantInt::get(TD->getIntPtrType(), Len), 1, B); EmitMemCpy(Dst, Src,
Context->getConstantInt(TD->getIntPtrType(), Len), 1, B);
return Dst; return Dst;
} }
@ -844,7 +853,7 @@ struct VISIBILITY_HIDDEN StrLenOpt : public LibCallOptimization {
virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
const FunctionType *FT = Callee->getFunctionType(); const FunctionType *FT = Callee->getFunctionType();
if (FT->getNumParams() != 1 || if (FT->getNumParams() != 1 ||
FT->getParamType(0) != PointerType::getUnqual(Type::Int8Ty) || FT->getParamType(0) != Context->getPointerTypeUnqual(Type::Int8Ty) ||
!isa<IntegerType>(FT->getReturnType())) !isa<IntegerType>(FT->getReturnType()))
return 0; return 0;
@ -852,7 +861,7 @@ struct VISIBILITY_HIDDEN StrLenOpt : public LibCallOptimization {
// Constant folding: strlen("xyz") -> 3 // Constant folding: strlen("xyz") -> 3
if (uint64_t Len = GetStringLength(Src)) if (uint64_t Len = GetStringLength(Src))
return ConstantInt::get(CI->getType(), Len-1); return Context->getConstantInt(CI->getType(), Len-1);
// Handle strlen(p) != 0. // Handle strlen(p) != 0.
if (!IsOnlyUsedInZeroEqualityComparison(CI)) return 0; if (!IsOnlyUsedInZeroEqualityComparison(CI)) return 0;
@ -899,7 +908,7 @@ struct VISIBILITY_HIDDEN MemCmpOpt : public LibCallOptimization {
Value *LHS = CI->getOperand(1), *RHS = CI->getOperand(2); Value *LHS = CI->getOperand(1), *RHS = CI->getOperand(2);
if (LHS == RHS) // memcmp(s,s,x) -> 0 if (LHS == RHS) // memcmp(s,s,x) -> 0
return Constant::getNullValue(CI->getType()); return Context->getNullValue(CI->getType());
// Make sure we have a constant length. // Make sure we have a constant length.
ConstantInt *LenC = dyn_cast<ConstantInt>(CI->getOperand(3)); ConstantInt *LenC = dyn_cast<ConstantInt>(CI->getOperand(3));
@ -907,7 +916,7 @@ struct VISIBILITY_HIDDEN MemCmpOpt : public LibCallOptimization {
uint64_t Len = LenC->getZExtValue(); uint64_t Len = LenC->getZExtValue();
if (Len == 0) // memcmp(s1,s2,0) -> 0 if (Len == 0) // memcmp(s1,s2,0) -> 0
return Constant::getNullValue(CI->getType()); return Context->getNullValue(CI->getType());
if (Len == 1) { // memcmp(S1,S2,1) -> *LHS - *RHS if (Len == 1) { // memcmp(S1,S2,1) -> *LHS - *RHS
Value *LHSV = B.CreateLoad(CastToCStr(LHS, B), "lhsv"); Value *LHSV = B.CreateLoad(CastToCStr(LHS, B), "lhsv");
@ -918,7 +927,7 @@ struct VISIBILITY_HIDDEN MemCmpOpt : public LibCallOptimization {
// memcmp(S1,S2,2) != 0 -> (*(short*)LHS ^ *(short*)RHS) != 0 // memcmp(S1,S2,2) != 0 -> (*(short*)LHS ^ *(short*)RHS) != 0
// memcmp(S1,S2,4) != 0 -> (*(int*)LHS ^ *(int*)RHS) != 0 // memcmp(S1,S2,4) != 0 -> (*(int*)LHS ^ *(int*)RHS) != 0
if ((Len == 2 || Len == 4) && IsOnlyUsedInZeroEqualityComparison(CI)) { if ((Len == 2 || Len == 4) && IsOnlyUsedInZeroEqualityComparison(CI)) {
const Type *PTy = PointerType::getUnqual(Len == 2 ? const Type *PTy = Context->getPointerTypeUnqual(Len == 2 ?
Type::Int16Ty : Type::Int32Ty); Type::Int16Ty : Type::Int32Ty);
LHS = B.CreateBitCast(LHS, PTy, "tmp"); LHS = B.CreateBitCast(LHS, PTy, "tmp");
RHS = B.CreateBitCast(RHS, PTy, "tmp"); RHS = B.CreateBitCast(RHS, PTy, "tmp");
@ -971,7 +980,7 @@ struct VISIBILITY_HIDDEN MemMoveOpt : public LibCallOptimization {
Value *Dst = CastToCStr(CI->getOperand(1), B); Value *Dst = CastToCStr(CI->getOperand(1), B);
Value *Src = CastToCStr(CI->getOperand(2), B); Value *Src = CastToCStr(CI->getOperand(2), B);
Value *Size = CI->getOperand(3); Value *Size = CI->getOperand(3);
Value *Align = ConstantInt::get(Type::Int32Ty, 1); Value *Align = Context->getConstantInt(Type::Int32Ty, 1);
B.CreateCall4(MemMove, Dst, Src, Size, Align); B.CreateCall4(MemMove, Dst, Src, Size, Align);
return CI->getOperand(1); return CI->getOperand(1);
} }
@ -1025,7 +1034,7 @@ struct VISIBILITY_HIDDEN PowOpt : public LibCallOptimization {
if (Op2C == 0) return 0; if (Op2C == 0) return 0;
if (Op2C->getValueAPF().isZero()) // pow(x, 0.0) -> 1.0 if (Op2C->getValueAPF().isZero()) // pow(x, 0.0) -> 1.0
return ConstantFP::get(CI->getType(), 1.0); return Context->getConstantFP(CI->getType(), 1.0);
if (Op2C->isExactlyValue(0.5)) { if (Op2C->isExactlyValue(0.5)) {
// FIXME: This is not safe for -0.0 and -inf. This can only be done when // FIXME: This is not safe for -0.0 and -inf. This can only be done when
@ -1045,7 +1054,8 @@ struct VISIBILITY_HIDDEN PowOpt : public LibCallOptimization {
if (Op2C->isExactlyValue(2.0)) // pow(x, 2.0) -> x*x if (Op2C->isExactlyValue(2.0)) // pow(x, 2.0) -> x*x
return B.CreateFMul(Op1, Op1, "pow2"); return B.CreateFMul(Op1, Op1, "pow2");
if (Op2C->isExactlyValue(-1.0)) // pow(x, -1.0) -> 1.0/x if (Op2C->isExactlyValue(-1.0)) // pow(x, -1.0) -> 1.0/x
return B.CreateFDiv(ConstantFP::get(CI->getType(), 1.0), Op1, "powrecip"); return B.CreateFDiv(Context->getConstantFP(CI->getType(), 1.0),
Op1, "powrecip");
return 0; return 0;
} }
}; };
@ -1083,9 +1093,9 @@ struct VISIBILITY_HIDDEN Exp2Opt : public LibCallOptimization {
else else
Name = "ldexpl"; Name = "ldexpl";
Constant *One = ConstantFP::get(APFloat(1.0f)); Constant *One = Context->getConstantFP(APFloat(1.0f));
if (Op->getType() != Type::FloatTy) if (Op->getType() != Type::FloatTy)
One = ConstantExpr::getFPExtend(One, Op->getType()); One = Context->getConstantExprFPExtend(One, Op->getType());
Module *M = Caller->getParent(); Module *M = Caller->getParent();
Value *Callee = M->getOrInsertFunction(Name, Op->getType(), Value *Callee = M->getOrInsertFunction(Name, Op->getType(),
@ -1143,8 +1153,8 @@ struct VISIBILITY_HIDDEN FFSOpt : public LibCallOptimization {
// Constant fold. // Constant fold.
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op)) { if (ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
if (CI->getValue() == 0) // ffs(0) -> 0. if (CI->getValue() == 0) // ffs(0) -> 0.
return Constant::getNullValue(CI->getType()); return Context->getNullValue(CI->getType());
return ConstantInt::get(Type::Int32Ty, // ffs(c) -> cttz(c)+1 return Context->getConstantInt(Type::Int32Ty, // ffs(c) -> cttz(c)+1
CI->getValue().countTrailingZeros()+1); CI->getValue().countTrailingZeros()+1);
} }
@ -1153,11 +1163,11 @@ struct VISIBILITY_HIDDEN FFSOpt : public LibCallOptimization {
Value *F = Intrinsic::getDeclaration(Callee->getParent(), Value *F = Intrinsic::getDeclaration(Callee->getParent(),
Intrinsic::cttz, &ArgType, 1); Intrinsic::cttz, &ArgType, 1);
Value *V = B.CreateCall(F, Op, "cttz"); Value *V = B.CreateCall(F, Op, "cttz");
V = B.CreateAdd(V, ConstantInt::get(V->getType(), 1), "tmp"); V = B.CreateAdd(V, Context->getConstantInt(V->getType(), 1), "tmp");
V = B.CreateIntCast(V, Type::Int32Ty, false, "tmp"); V = B.CreateIntCast(V, Type::Int32Ty, false, "tmp");
Value *Cond = B.CreateICmpNE(Op, Constant::getNullValue(ArgType), "tmp"); Value *Cond = B.CreateICmpNE(Op, Context->getNullValue(ArgType), "tmp");
return B.CreateSelect(Cond, V, ConstantInt::get(Type::Int32Ty, 0)); return B.CreateSelect(Cond, V, Context->getConstantInt(Type::Int32Ty, 0));
} }
}; };
@ -1174,8 +1184,10 @@ struct VISIBILITY_HIDDEN IsDigitOpt : public LibCallOptimization {
// isdigit(c) -> (c-'0') <u 10 // isdigit(c) -> (c-'0') <u 10
Value *Op = CI->getOperand(1); Value *Op = CI->getOperand(1);
Op = B.CreateSub(Op, ConstantInt::get(Type::Int32Ty, '0'), "isdigittmp"); Op = B.CreateSub(Op, Context->getConstantInt(Type::Int32Ty, '0'),
Op = B.CreateICmpULT(Op, ConstantInt::get(Type::Int32Ty, 10), "isdigit"); "isdigittmp");
Op = B.CreateICmpULT(Op, Context->getConstantInt(Type::Int32Ty, 10),
"isdigit");
return B.CreateZExt(Op, CI->getType()); return B.CreateZExt(Op, CI->getType());
} }
}; };
@ -1193,7 +1205,8 @@ struct VISIBILITY_HIDDEN IsAsciiOpt : public LibCallOptimization {
// isascii(c) -> c <u 128 // isascii(c) -> c <u 128
Value *Op = CI->getOperand(1); Value *Op = CI->getOperand(1);
Op = B.CreateICmpULT(Op, ConstantInt::get(Type::Int32Ty, 128), "isascii"); Op = B.CreateICmpULT(Op, Context->getConstantInt(Type::Int32Ty, 128),
"isascii");
return B.CreateZExt(Op, CI->getType()); return B.CreateZExt(Op, CI->getType());
} }
}; };
@ -1211,7 +1224,8 @@ struct VISIBILITY_HIDDEN AbsOpt : public LibCallOptimization {
// abs(x) -> x >s -1 ? x : -x // abs(x) -> x >s -1 ? x : -x
Value *Op = CI->getOperand(1); Value *Op = CI->getOperand(1);
Value *Pos = B.CreateICmpSGT(Op,ConstantInt::getAllOnesValue(Op->getType()), Value *Pos = B.CreateICmpSGT(Op,
Context->getConstantIntAllOnesValue(Op->getType()),
"ispos"); "ispos");
Value *Neg = B.CreateNeg(Op, "neg"); Value *Neg = B.CreateNeg(Op, "neg");
return B.CreateSelect(Pos, Op, Neg); return B.CreateSelect(Pos, Op, Neg);
@ -1231,7 +1245,8 @@ struct VISIBILITY_HIDDEN ToAsciiOpt : public LibCallOptimization {
return 0; return 0;
// isascii(c) -> c & 0x7f // isascii(c) -> c & 0x7f
return B.CreateAnd(CI->getOperand(1), ConstantInt::get(CI->getType(),0x7F)); return B.CreateAnd(CI->getOperand(1),
Context->getConstantInt(CI->getType(),0x7F));
} }
}; };
@ -1258,12 +1273,14 @@ struct VISIBILITY_HIDDEN PrintFOpt : public LibCallOptimization {
// Empty format string -> noop. // Empty format string -> noop.
if (FormatStr.empty()) // Tolerate printf's declared void. if (FormatStr.empty()) // Tolerate printf's declared void.
return CI->use_empty() ? (Value*)CI : ConstantInt::get(CI->getType(), 0); return CI->use_empty() ? (Value*)CI :
Context->getConstantInt(CI->getType(), 0);
// printf("x") -> putchar('x'), even for '%'. // printf("x") -> putchar('x'), even for '%'.
if (FormatStr.size() == 1) { if (FormatStr.size() == 1) {
EmitPutChar(ConstantInt::get(Type::Int32Ty, FormatStr[0]), B); EmitPutChar(Context->getConstantInt(Type::Int32Ty, FormatStr[0]), B);
return CI->use_empty() ? (Value*)CI : ConstantInt::get(CI->getType(), 1); return CI->use_empty() ? (Value*)CI :
Context->getConstantInt(CI->getType(), 1);
} }
// printf("foo\n") --> puts("foo") // printf("foo\n") --> puts("foo")
@ -1272,12 +1289,12 @@ struct VISIBILITY_HIDDEN PrintFOpt : public LibCallOptimization {
// Create a string literal with no \n on it. We expect the constant merge // Create a string literal with no \n on it. We expect the constant merge
// pass to be run after this pass, to merge duplicate strings. // pass to be run after this pass, to merge duplicate strings.
FormatStr.erase(FormatStr.end()-1); FormatStr.erase(FormatStr.end()-1);
Constant *C = ConstantArray::get(FormatStr, true); Constant *C = Context->getConstantArray(FormatStr, true);
C = new GlobalVariable(C->getType(), true,GlobalVariable::InternalLinkage, C = new GlobalVariable(C->getType(), true,GlobalVariable::InternalLinkage,
C, "str", Callee->getParent()); C, "str", Callee->getParent());
EmitPutS(C, B); EmitPutS(C, B);
return CI->use_empty() ? (Value*)CI : return CI->use_empty() ? (Value*)CI :
ConstantInt::get(CI->getType(), FormatStr.size()+1); Context->getConstantInt(CI->getType(), FormatStr.size()+1);
} }
// Optimize specific format strings. // Optimize specific format strings.
@ -1285,7 +1302,8 @@ struct VISIBILITY_HIDDEN PrintFOpt : public LibCallOptimization {
if (FormatStr == "%c" && CI->getNumOperands() > 2 && if (FormatStr == "%c" && CI->getNumOperands() > 2 &&
isa<IntegerType>(CI->getOperand(2)->getType())) { isa<IntegerType>(CI->getOperand(2)->getType())) {
EmitPutChar(CI->getOperand(2), B); EmitPutChar(CI->getOperand(2), B);
return CI->use_empty() ? (Value*)CI : ConstantInt::get(CI->getType(), 1); return CI->use_empty() ? (Value*)CI :
Context->getConstantInt(CI->getType(), 1);
} }
// printf("%s\n", str) --> puts(str) // printf("%s\n", str) --> puts(str)
@ -1326,8 +1344,8 @@ struct VISIBILITY_HIDDEN SPrintFOpt : public LibCallOptimization {
// sprintf(str, fmt) -> llvm.memcpy(str, fmt, strlen(fmt)+1, 1) // sprintf(str, fmt) -> llvm.memcpy(str, fmt, strlen(fmt)+1, 1)
EmitMemCpy(CI->getOperand(1), CI->getOperand(2), // Copy the nul byte. EmitMemCpy(CI->getOperand(1), CI->getOperand(2), // Copy the nul byte.
ConstantInt::get(TD->getIntPtrType(), FormatStr.size()+1),1,B); Context->getConstantInt(TD->getIntPtrType(), FormatStr.size()+1),1,B);
return ConstantInt::get(CI->getType(), FormatStr.size()); return Context->getConstantInt(CI->getType(), FormatStr.size());
} }
// The remaining optimizations require the format string to be "%s" or "%c" // The remaining optimizations require the format string to be "%s" or "%c"
@ -1342,10 +1360,10 @@ struct VISIBILITY_HIDDEN SPrintFOpt : public LibCallOptimization {
Value *V = B.CreateTrunc(CI->getOperand(3), Type::Int8Ty, "char"); Value *V = B.CreateTrunc(CI->getOperand(3), Type::Int8Ty, "char");
Value *Ptr = CastToCStr(CI->getOperand(1), B); Value *Ptr = CastToCStr(CI->getOperand(1), B);
B.CreateStore(V, Ptr); B.CreateStore(V, Ptr);
Ptr = B.CreateGEP(Ptr, ConstantInt::get(Type::Int32Ty, 1), "nul"); Ptr = B.CreateGEP(Ptr, Context->getConstantInt(Type::Int32Ty, 1), "nul");
B.CreateStore(Constant::getNullValue(Type::Int8Ty), Ptr); B.CreateStore(Context->getNullValue(Type::Int8Ty), Ptr);
return ConstantInt::get(CI->getType(), 1); return Context->getConstantInt(CI->getType(), 1);
} }
if (FormatStr[1] == 's') { if (FormatStr[1] == 's') {
@ -1353,7 +1371,8 @@ struct VISIBILITY_HIDDEN SPrintFOpt : public LibCallOptimization {
if (!isa<PointerType>(CI->getOperand(3)->getType())) return 0; if (!isa<PointerType>(CI->getOperand(3)->getType())) return 0;
Value *Len = EmitStrLen(CI->getOperand(3), B); Value *Len = EmitStrLen(CI->getOperand(3), B);
Value *IncLen = B.CreateAdd(Len, ConstantInt::get(Len->getType(), 1), Value *IncLen = B.CreateAdd(Len,
Context->getConstantInt(Len->getType(), 1),
"leninc"); "leninc");
EmitMemCpy(CI->getOperand(1), CI->getOperand(3), IncLen, 1, B); EmitMemCpy(CI->getOperand(1), CI->getOperand(3), IncLen, 1, B);
@ -1386,13 +1405,13 @@ struct VISIBILITY_HIDDEN FWriteOpt : public LibCallOptimization {
// If this is writing zero records, remove the call (it's a noop). // If this is writing zero records, remove the call (it's a noop).
if (Bytes == 0) if (Bytes == 0)
return ConstantInt::get(CI->getType(), 0); return Context->getConstantInt(CI->getType(), 0);
// If this is writing one byte, turn it into fputc. // If this is writing one byte, turn it into fputc.
if (Bytes == 1) { // fwrite(S,1,1,F) -> fputc(S[0],F) if (Bytes == 1) { // fwrite(S,1,1,F) -> fputc(S[0],F)
Value *Char = B.CreateLoad(CastToCStr(CI->getOperand(1), B), "char"); Value *Char = B.CreateLoad(CastToCStr(CI->getOperand(1), B), "char");
EmitFPutC(Char, CI->getOperand(4), B); EmitFPutC(Char, CI->getOperand(4), B);
return ConstantInt::get(CI->getType(), 1); return Context->getConstantInt(CI->getType(), 1);
} }
return 0; return 0;
@ -1414,7 +1433,8 @@ struct VISIBILITY_HIDDEN FPutsOpt : public LibCallOptimization {
// fputs(s,F) --> fwrite(s,1,strlen(s),F) // fputs(s,F) --> fwrite(s,1,strlen(s),F)
uint64_t Len = GetStringLength(CI->getOperand(1)); uint64_t Len = GetStringLength(CI->getOperand(1));
if (!Len) return 0; if (!Len) return 0;
EmitFWrite(CI->getOperand(1), ConstantInt::get(TD->getIntPtrType(), Len-1), EmitFWrite(CI->getOperand(1),
Context->getConstantInt(TD->getIntPtrType(), Len-1),
CI->getOperand(2), B); CI->getOperand(2), B);
return CI; // Known to have no uses (see above). return CI; // Known to have no uses (see above).
} }
@ -1443,10 +1463,10 @@ struct VISIBILITY_HIDDEN FPrintFOpt : public LibCallOptimization {
if (FormatStr[i] == '%') // Could handle %% -> % if we cared. if (FormatStr[i] == '%') // Could handle %% -> % if we cared.
return 0; // We found a format specifier. return 0; // We found a format specifier.
EmitFWrite(CI->getOperand(2), ConstantInt::get(TD->getIntPtrType(), EmitFWrite(CI->getOperand(2), Context->getConstantInt(TD->getIntPtrType(),
FormatStr.size()), FormatStr.size()),
CI->getOperand(1), B); CI->getOperand(1), B);
return ConstantInt::get(CI->getType(), FormatStr.size()); return Context->getConstantInt(CI->getType(), FormatStr.size());
} }
// The remaining optimizations require the format string to be "%s" or "%c" // The remaining optimizations require the format string to be "%s" or "%c"
@ -1459,7 +1479,7 @@ struct VISIBILITY_HIDDEN FPrintFOpt : public LibCallOptimization {
// fprintf(F, "%c", chr) --> *(i8*)dst = chr // fprintf(F, "%c", chr) --> *(i8*)dst = chr
if (!isa<IntegerType>(CI->getOperand(3)->getType())) return 0; if (!isa<IntegerType>(CI->getOperand(3)->getType())) return 0;
EmitFPutC(CI->getOperand(3), CI->getOperand(1), B); EmitFPutC(CI->getOperand(3), CI->getOperand(1), B);
return ConstantInt::get(CI->getType(), 1); return Context->getConstantInt(CI->getType(), 1);
} }
if (FormatStr[1] == 's') { if (FormatStr[1] == 's') {

View File

@ -408,7 +408,8 @@ Constant* LLVMContext::getConstantVector(Constant* const* Vals,
return ConstantVector::get(Vals, NumVals); return ConstantVector::get(Vals, NumVals);
} }
ConstantVector* LLVMContext::getConstantVectorAllOnes(const VectorType* Ty) { ConstantVector* LLVMContext::getConstantVectorAllOnesValue(
const VectorType* Ty) {
return ConstantVector::getAllOnesValue(Ty); return ConstantVector::getAllOnesValue(Ty);
} }