From e9d782b7bea2578ac20a96be2233df4f1fce4ca3 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 13 Jan 2005 22:25:21 +0000 Subject: [PATCH] Implement an optimization for == and != comparisons like this: _Bool test2(int X, int Y) { return &arr[X][Y] == arr; } instead of generating this: bool %test2(int %X, int %Y) { %tmp.3.idx = mul int %X, 160 ; [#uses=1] %tmp.3.idx1 = shl int %Y, ubyte 2 ; [#uses=1] %tmp.3.offs2 = sub int 0, %tmp.3.idx ; [#uses=1] %tmp.7 = seteq int %tmp.3.idx1, %tmp.3.offs2 ; [#uses=1] ret bool %tmp.7 } generate this: bool %test2(int %X, int %Y) { seteq int %X, 0 ; :0 [#uses=1] seteq int %Y, 0 ; :1 [#uses=1] %tmp.7 = and bool %0, %1 ; [#uses=1] ret bool %tmp.7 } This idiom occurs in C++ programs when iterating from begin() to end(), in a vector or array. For example, we now compile this: void test(int X, int Y) { for (int *i = arr; i != arr+100; ++i) foo(*i); } to this: no_exit: ; preds = %entry, %no_exit ... %exitcond = seteq uint %indvar.next, 100 ; [#uses=1] br bool %exitcond, label %return, label %no_exit instead of this: no_exit: ; preds = %entry, %no_exit ... %inc5 = getelementptr [100 x [40 x int]]* %arr, int 0, int 0, int %inc.rec ; [#uses=1] %tmp.8 = seteq int* %inc5, getelementptr ([100 x [40 x int]]* %arr, int 0, int 100, int 0) ; [#uses=1] %indvar.next = add uint %indvar, 1 ; [#uses=1] br bool %tmp.8, label %return, label %no_exit git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19536 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/InstructionCombining.cpp | 64 ++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 9f6e712e254..bb235ca868a 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -2149,12 +2149,53 @@ Instruction *InstCombiner::FoldGEPSetCC(User *GEPLHS, Value *RHS, Instruction::BinaryOps Cond, Instruction &I) { assert(dyn_castGetElementPtr(GEPLHS) && "LHS is not a getelementptr!"); - + + if (CastInst *CI = dyn_cast(RHS)) + if (isa(CI->getOperand(0)->getType())) + RHS = CI->getOperand(0); + 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. + if (Cond == Instruction::SetEQ || Cond == Instruction::SetNE) { + Instruction *InVal = 0; + for (unsigned i = 1, e = GEPLHS->getNumOperands(); i != e; ++i) { + bool EmitIt = true; + if (Constant *C = dyn_cast(GEPLHS->getOperand(i))) { + if (isa(C)) // undef index -> undef. + return ReplaceInstUsesWith(I, UndefValue::get(I.getType())); + if (C->isNullValue()) + EmitIt = false; + else if (isa(C)) + return ReplaceInstUsesWith(I, // No comparison is needed here. + ConstantBool::get(Cond == Instruction::SetNE)); + } + + if (EmitIt) { + Instruction *Comp = + new SetCondInst(Cond, GEPLHS->getOperand(i), + Constant::getNullValue(GEPLHS->getOperand(i)->getType())); + if (InVal == 0) + InVal = Comp; + else { + InVal = InsertNewInstBefore(InVal, I); + InsertNewInstBefore(Comp, I); + if (Cond == Instruction::SetNE) // True if any are unequal + InVal = BinaryOperator::createOr(InVal, Comp); + else // True if all are equal + InVal = BinaryOperator::createAnd(InVal, Comp); + } + } + } + + if (InVal) + return InVal; + else + ReplaceInstUsesWith(I, // No comparison is needed here, all indexes = 0 + ConstantBool::get(Cond == Instruction::SetEQ)); + } // Only lower this if the setcc is the only user of the GEP or if we expect // the result to fold to a constant! @@ -2168,6 +2209,27 @@ Instruction *InstCombiner::FoldGEPSetCC(User *GEPLHS, Value *RHS, if (PtrBase != GEPRHS->getOperand(0)) return 0; + // If one of the GEPs has all zero indices, recurse. + bool AllZeros = true; + for (unsigned i = 1, e = GEPLHS->getNumOperands(); i != e; ++i) + if (!isa(GEPLHS->getOperand(i)) || + !cast(GEPLHS->getOperand(i))->isNullValue()) { + AllZeros = false; + break; + } + if (AllZeros) + return FoldGEPSetCC(GEPRHS, GEPLHS->getOperand(0), + SetCondInst::getSwappedCondition(Cond), I); + AllZeros = true; + for (unsigned i = 1, e = GEPRHS->getNumOperands(); i != e; ++i) + if (!isa(GEPRHS->getOperand(i)) || + !cast(GEPRHS->getOperand(i))->isNullValue()) { + AllZeros = false; + break; + } + if (AllZeros) + return FoldGEPSetCC(GEPLHS, GEPRHS->getOperand(0), Cond, I); + // 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()) &&