From 574da9ba0bfa8d5975b675b36eaa7d80e132ec01 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 13 Jan 2005 20:14:25 +0000 Subject: [PATCH] Fix a crash compiling 129.compress git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19533 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/InstructionCombining.cpp | 115 +++++++++++++++++- 1 file changed, 109 insertions(+), 6 deletions(-) diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 3ab7be5f85a..d21ec762152 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -116,6 +116,8 @@ namespace { Instruction *visitSetCondInstWithCastAndConstant(BinaryOperator&I, CastInst*LHSI, ConstantInt* CI); + Instruction *FoldGEPSetCC(User *GEPLHS, Value *RHS, + Instruction::BinaryOps Cond, Instruction &I); Instruction *visitShiftInst(ShiftInst &I); Instruction *visitCastInst(CastInst &CI); Instruction *visitSelectInst(SelectInst &CI); @@ -347,6 +349,16 @@ static inline Value *dyn_castFoldableMul(Value *V, ConstantInt *&CST) { return 0; } +/// dyn_castGetElementPtr - If this is a getelementptr instruction or constant +/// expression, return it. +static User *dyn_castGetElementPtr(Value *V) { + if (isa(V)) return cast(V); + if (ConstantExpr *CE = dyn_cast(V)) + if (CE->getOpcode() == Instruction::GetElementPtr) + return cast(V); + return false; +} + // Log2 - Calculate the log base 2 for the specified value if it is exactly a // power of 2. static unsigned Log2(uint64_t Val) { @@ -2078,6 +2090,91 @@ static bool AddWithOverflow(ConstantInt *&Result, ConstantInt *In1, cast(In1)->getValue(); } +/// EmitGEPOffset - Given a getelementptr instruction/constantexpr, emit the +/// code necessary to compute the offset from the base pointer (without adding +/// in the base pointer). Return the result as a signed integer of intptr size. +static Value *EmitGEPOffset(User *GEP, Instruction &I, InstCombiner &IC) { + TargetData &TD = IC.getTargetData(); + gep_type_iterator GTI = gep_type_begin(GEP); + const Type *UIntPtrTy = TD.getIntPtrType(); + const Type *SIntPtrTy = UIntPtrTy->getSignedVersion(); + Value *Result = Constant::getNullValue(SIntPtrTy); + + // Build a mask for high order bits. + uint64_t PtrSizeMask = ~0ULL; + PtrSizeMask >>= 64-(TD.getPointerSize()*8); + + ++GTI; // Measure type stepping over. + for (unsigned i = 1, e = GEP->getNumOperands(); i != e; ++i, ++GTI) { + Value *Op = GEP->getOperand(i); + uint64_t Size = TD.getTypeSize(*GTI) & PtrSizeMask; + Constant *Scale = ConstantExpr::getCast(ConstantUInt::get(UIntPtrTy, Size), + SIntPtrTy); + if (Constant *OpC = dyn_cast(Op)) { + if (!OpC->isNullValue()) { + Scale = ConstantExpr::getMul(OpC, Scale); + if (Constant *RC = dyn_cast(Result)) + Result = ConstantExpr::getAdd(RC, Scale); + else { + // Emit an add instruction. + Result = IC.InsertNewInstBefore( + BinaryOperator::createAdd(Result, Scale, + GEP->getName()+".offs"), I); + } + } + } else { + // We'll let instcombine(mul) convert this to a shl if possible. + Value *Offs = + IC.InsertNewInstBefore(BinaryOperator::createMul(Op, Scale, + GEP->getName()+".idx"), I); + + // Emit an add instruction. + Result = IC.InsertNewInstBefore(BinaryOperator::createAdd(Offs, Result, + GEP->getName()+".offs"), I); + } + } + return Result; +} + +/// FoldGEPSetCC - Fold comparisons between a GEP instruction and something +/// else. At this point we know that the GEP is on the LHS of the comparison. +Instruction *InstCombiner::FoldGEPSetCC(User *GEPLHS, Value *RHS, + Instruction::BinaryOps Cond, + Instruction &I) { + assert(dyn_castGetElementPtr(GEPLHS) && "LHS is not a getelementptr!"); + + Value *PtrBase = GEPLHS->getOperand(0); + if (PtrBase == RHS) { + // As an optimization, we don't actually have to compute the actual value of + // OFFSET if this is a seteq or setne comparison, just return whether each + // index is zero or not. + + // Only lower this if the setcc is the only user of the GEP or if we expect + // the result to fold to a constant! + if (isa(GEPLHS) || GEPLHS->hasOneUse()) { + // ((gep Ptr, OFFSET) cmp Ptr) ---> (OFFSET cmp 0). + Value *Offset = EmitGEPOffset(GEPLHS, I, *this); + return new SetCondInst(Cond, Offset, + Constant::getNullValue(Offset->getType())); + } + } else if (User *GEPRHS = dyn_castGetElementPtr(RHS)) { + if (PtrBase != GEPRHS->getOperand(0)) + return 0; + + // Only lower this if the setcc is the only user of the GEP or if we expect + // the result to fold to a constant! + if ((isa(GEPLHS) || GEPLHS->hasOneUse()) && + (isa(GEPRHS) || GEPRHS->hasOneUse())) { + // ((gep Ptr, OFFSET1) cmp (gep Ptr, OFFSET2) ---> (OFFSET1 cmp OFFSET2) + Value *L = EmitGEPOffset(GEPLHS, I, *this); + Value *R = EmitGEPOffset(GEPRHS, I, *this); + return new SetCondInst(Cond, L, R); + } + } + return 0; +} + + Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) { bool Changed = SimplifyCommutative(I); Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); @@ -2625,6 +2722,15 @@ Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) { } } + // If we can optimize a 'setcc GEP, P' or 'setcc P, GEP', do so now. + if (User *GEP = dyn_castGetElementPtr(Op0)) + if (Instruction *NI = FoldGEPSetCC(GEP, Op1, I.getOpcode(), I)) + return NI; + if (User *GEP = dyn_castGetElementPtr(Op1)) + if (Instruction *NI = FoldGEPSetCC(GEP, Op0, + SetCondInst::getSwappedCondition(I.getOpcode()), I)) + return NI; + // Test to see if the operands of the setcc are casted versions of other // values. If the cast can be stripped off both arguments, we do so now. if (CastInst *CI = dyn_cast(Op0)) { @@ -3951,12 +4057,8 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { // getelementptr instructions into a single instruction. // std::vector SrcGEPOperands; - if (GetElementPtrInst *Src = dyn_cast(PtrOp)) { + if (User *Src = dyn_castGetElementPtr(PtrOp)) SrcGEPOperands.assign(Src->op_begin(), Src->op_end()); - } else if (ConstantExpr *CE = dyn_cast(PtrOp)) { - if (CE->getOpcode() == Instruction::GetElementPtr) - SrcGEPOperands.assign(CE->op_begin(), CE->op_end()); - } if (!SrcGEPOperands.empty()) { // Note that if our source is a gep chain itself that we wait for that @@ -4079,7 +4181,8 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { GEP.setOperand(0, X); return &GEP; } - } else if (GEP.getNumOperands() == 2) { + } else if (GEP.getNumOperands() == 2 && + isa(CE->getOperand(0)->getType())) { // Transform things like: // %t = getelementptr ubyte* cast ([2 x sbyte]* %str to ubyte*), uint %V // into: %t1 = getelementptr [2 x sbyte*]* %str, int 0, uint %V; cast -- 2.34.1