diff options
| author | Chris Lattner <sabre@nondot.org> | 2005-01-13 22:25:21 +0000 | 
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2005-01-13 22:25:21 +0000 | 
| commit | 81e8417614d48441fbaaf05cd39b78384e613e9d (patch) | |
| tree | 0f1d4ce12d1fd86376e55f1e3bb364faa754ce3b /llvm/lib/Transforms | |
| parent | e727af06c83d0880b62e410524dad7c44534926b (diff) | |
| download | bcm5719-llvm-81e8417614d48441fbaaf05cd39b78384e613e9d.tar.gz bcm5719-llvm-81e8417614d48441fbaaf05cd39b78384e613e9d.zip | |
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            ; <int> [#uses=1]
        %tmp.3.idx1 = shl int %Y, ubyte 2               ; <int> [#uses=1]
        %tmp.3.offs2 = sub int 0, %tmp.3.idx            ; <int> [#uses=1]
        %tmp.7 = seteq int %tmp.3.idx1, %tmp.3.offs2            ; <bool> [#uses=1]
        ret bool %tmp.7
}
generate this:
bool %test2(int %X, int %Y) {
        seteq int %X, 0         ; <bool>:0 [#uses=1]
        seteq int %Y, 0         ; <bool>:1 [#uses=1]
        %tmp.7 = and bool %0, %1                ; <bool> [#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                ; <bool> [#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              ; <int*> [#uses=1]
        %tmp.8 = seteq int* %inc5, getelementptr ([100 x [40 x int]]* %arr, int 0, int 100, int 0)              ; <bool> [#uses=1]
        %indvar.next = add uint %indvar, 1              ; <uint> [#uses=1]
        br bool %tmp.8, label %return, label %no_exit
llvm-svn: 19536
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/Scalar/InstructionCombining.cpp | 64 | 
1 files changed, 63 insertions, 1 deletions
| diff --git a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp index 9f6e712e254..bb235ca868a 100644 --- a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/llvm/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<CastInst>(RHS)) +    if (isa<PointerType>(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<Constant>(GEPLHS->getOperand(i))) { +          if (isa<UndefValue>(C))  // undef index -> undef. +            return ReplaceInstUsesWith(I, UndefValue::get(I.getType())); +          if (C->isNullValue()) +            EmitIt = false; +          else if (isa<ConstantInt>(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<Constant>(GEPLHS->getOperand(i)) || +          !cast<Constant>(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<Constant>(GEPRHS->getOperand(i)) || +          !cast<Constant>(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<ConstantExpr>(GEPLHS) || GEPLHS->hasOneUse()) && | 

