diff options
Diffstat (limited to 'lib/Transforms/InstCombine/InstCombineAndOrXor.cpp')
| -rw-r--r-- | lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 158 | 
1 files changed, 98 insertions, 60 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index fa7bb12ff218..5e47953d1ecc 100644 --- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -546,7 +546,7 @@ Instruction *InstCombiner::FoldAndOfICmps(Instruction &I,      std::swap(LHSCC, RHSCC);    } -  // At this point, we know we have have two icmp instructions +  // At this point, we know we have two icmp instructions    // comparing a value against two constants and and'ing the result    // together.  Because of the above check, we know that we only have    // icmp eq, icmp ne, icmp [su]lt, and icmp [SU]gt here. We also know  @@ -932,24 +932,49 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {      if (ICmpInst *LHS = dyn_cast<ICmpInst>(Op0))        if (Instruction *Res = FoldAndOfICmps(I, LHS, RHS))          return Res; - +   +  // If and'ing two fcmp, try combine them into one. +  if (FCmpInst *LHS = dyn_cast<FCmpInst>(I.getOperand(0))) +    if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand(1))) +      if (Instruction *Res = FoldAndOfFCmps(I, LHS, RHS)) +        return Res; +   +      // fold (and (cast A), (cast B)) -> (cast (and A, B))    if (CastInst *Op0C = dyn_cast<CastInst>(Op0)) -    if (CastInst *Op1C = dyn_cast<CastInst>(Op1)) -      if (Op0C->getOpcode() == Op1C->getOpcode()) { // same cast kind ? -        const Type *SrcTy = Op0C->getOperand(0)->getType(); -        if (SrcTy == Op1C->getOperand(0)->getType() && -            SrcTy->isIntOrIntVector() && -            // Only do this if the casts both really cause code to be generated. -            ValueRequiresCast(Op0C->getOpcode(), Op0C->getOperand(0), -                              I.getType()) && -            ValueRequiresCast(Op1C->getOpcode(), Op1C->getOperand(0),  -                              I.getType())) { -          Value *NewOp = Builder->CreateAnd(Op0C->getOperand(0), -                                            Op1C->getOperand(0), I.getName()); +    if (CastInst *Op1C = dyn_cast<CastInst>(Op1)) { +      const Type *SrcTy = Op0C->getOperand(0)->getType(); +      if (Op0C->getOpcode() == Op1C->getOpcode() && // same cast kind ? +          SrcTy == Op1C->getOperand(0)->getType() && +          SrcTy->isIntOrIntVectorTy()) { +        Value *Op0COp = Op0C->getOperand(0), *Op1COp = Op1C->getOperand(0); +         +        // Only do this if the casts both really cause code to be generated. +        if (ShouldOptimizeCast(Op0C->getOpcode(), Op0COp, I.getType()) && +            ShouldOptimizeCast(Op1C->getOpcode(), Op1COp, I.getType())) { +          Value *NewOp = Builder->CreateAnd(Op0COp, Op1COp, I.getName());            return CastInst::Create(Op0C->getOpcode(), NewOp, I.getType());          } +         +        // If this is and(cast(icmp), cast(icmp)), try to fold this even if the +        // cast is otherwise not optimizable.  This happens for vector sexts. +        if (ICmpInst *RHS = dyn_cast<ICmpInst>(Op1COp)) +          if (ICmpInst *LHS = dyn_cast<ICmpInst>(Op0COp)) +            if (Instruction *Res = FoldAndOfICmps(I, LHS, RHS)) { +              InsertNewInstBefore(Res, I); +              return CastInst::Create(Op0C->getOpcode(), Res, I.getType()); +            } +         +        // If this is and(cast(fcmp), cast(fcmp)), try to fold this even if the +        // cast is otherwise not optimizable.  This happens for vector sexts. +        if (FCmpInst *RHS = dyn_cast<FCmpInst>(Op1COp)) +          if (FCmpInst *LHS = dyn_cast<FCmpInst>(Op0COp)) +            if (Instruction *Res = FoldAndOfFCmps(I, LHS, RHS)) { +              InsertNewInstBefore(Res, I); +              return CastInst::Create(Op0C->getOpcode(), Res, I.getType()); +            }        } +    }    // (X >> Z) & (Y >> Z)  -> (X&Y) >> Z  for all shifts.    if (BinaryOperator *SI1 = dyn_cast<BinaryOperator>(Op1)) { @@ -965,13 +990,6 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {        }    } -  // If and'ing two fcmp, try combine them into one. -  if (FCmpInst *LHS = dyn_cast<FCmpInst>(I.getOperand(0))) { -    if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand(1))) -      if (Instruction *Res = FoldAndOfFCmps(I, LHS, RHS)) -        return Res; -  } -    return Changed ? &I : 0;  } @@ -1142,18 +1160,20 @@ static Instruction *MatchSelectFromAndOr(Value *A, Value *B,                                           Value *C, Value *D) {    // If A is not a select of -1/0, this cannot match.    Value *Cond = 0; -  if (!match(A, m_SelectCst<-1, 0>(m_Value(Cond)))) +  if (!match(A, m_SExt(m_Value(Cond))) || +      !Cond->getType()->isIntegerTy(1))      return 0;    // ((cond?-1:0)&C) | (B&(cond?0:-1)) -> cond ? C : B. -  if (match(D, m_SelectCst<0, -1>(m_Specific(Cond)))) +  if (match(D, m_Not(m_SExt(m_Specific(Cond)))))      return SelectInst::Create(Cond, C, B); -  if (match(D, m_Not(m_SelectCst<-1, 0>(m_Specific(Cond))))) +  if (match(D, m_SExt(m_Not(m_Specific(Cond)))))      return SelectInst::Create(Cond, C, B); +      // ((cond?-1:0)&C) | ((cond?0:-1)&D) -> cond ? C : D. -  if (match(B, m_SelectCst<0, -1>(m_Specific(Cond)))) +  if (match(B, m_Not(m_SExt(m_Specific(Cond)))))      return SelectInst::Create(Cond, C, D); -  if (match(B, m_Not(m_SelectCst<-1, 0>(m_Specific(Cond))))) +  if (match(B, m_SExt(m_Not(m_Specific(Cond)))))      return SelectInst::Create(Cond, C, D);    return 0;  } @@ -1224,7 +1244,7 @@ Instruction *InstCombiner::FoldOrOfICmps(Instruction &I,      std::swap(LHSCC, RHSCC);    } -  // At this point, we know we have have two icmp instructions +  // At this point, we know we have two icmp instructions    // comparing a value against two constants and or'ing the result    // together.  Because of the above check, we know that we only have    // ICMP_EQ, ICMP_NE, ICMP_LT, and ICMP_GT here. We also know (from the @@ -1595,15 +1615,19 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {        }      } -    // (A & (C0?-1:0)) | (B & ~(C0?-1:0)) ->  C0 ? A : B, and commuted variants -    if (Instruction *Match = MatchSelectFromAndOr(A, B, C, D)) -      return Match; -    if (Instruction *Match = MatchSelectFromAndOr(B, A, D, C)) -      return Match; -    if (Instruction *Match = MatchSelectFromAndOr(C, B, A, D)) -      return Match; -    if (Instruction *Match = MatchSelectFromAndOr(D, A, B, C)) -      return Match; +    // (A & (C0?-1:0)) | (B & ~(C0?-1:0)) ->  C0 ? A : B, and commuted variants. +    // Don't do this for vector select idioms, the code generator doesn't handle +    // them well yet. +    if (!isa<VectorType>(I.getType())) { +      if (Instruction *Match = MatchSelectFromAndOr(A, B, C, D)) +        return Match; +      if (Instruction *Match = MatchSelectFromAndOr(B, A, D, C)) +        return Match; +      if (Instruction *Match = MatchSelectFromAndOr(C, B, A, D)) +        return Match; +      if (Instruction *Match = MatchSelectFromAndOr(D, A, B, C)) +        return Match; +    }      // ((A&~B)|(~A&B)) -> A^B      if ((match(C, m_Not(m_Specific(D))) && @@ -1663,37 +1687,51 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {        if (Instruction *Res = FoldOrOfICmps(I, LHS, RHS))          return Res; +  // (fcmp uno x, c) | (fcmp uno y, c)  -> (fcmp uno x, y) +  if (FCmpInst *LHS = dyn_cast<FCmpInst>(I.getOperand(0))) +    if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand(1))) +      if (Instruction *Res = FoldOrOfFCmps(I, LHS, RHS)) +        return Res; +      // fold (or (cast A), (cast B)) -> (cast (or A, B))    if (CastInst *Op0C = dyn_cast<CastInst>(Op0)) {      if (CastInst *Op1C = dyn_cast<CastInst>(Op1))        if (Op0C->getOpcode() == Op1C->getOpcode()) {// same cast kind ? -        if (!isa<ICmpInst>(Op0C->getOperand(0)) || -            !isa<ICmpInst>(Op1C->getOperand(0))) { -          const Type *SrcTy = Op0C->getOperand(0)->getType(); -          if (SrcTy == Op1C->getOperand(0)->getType() && -              SrcTy->isIntOrIntVector() && +        const Type *SrcTy = Op0C->getOperand(0)->getType(); +        if (SrcTy == Op1C->getOperand(0)->getType() && +            SrcTy->isIntOrIntVectorTy()) { +          Value *Op0COp = Op0C->getOperand(0), *Op1COp = Op1C->getOperand(0); + +          if ((!isa<ICmpInst>(Op0COp) || !isa<ICmpInst>(Op1COp)) &&                // Only do this if the casts both really cause code to be                // generated. -              ValueRequiresCast(Op0C->getOpcode(), Op0C->getOperand(0),  -                                I.getType()) && -              ValueRequiresCast(Op1C->getOpcode(), Op1C->getOperand(0),  -                                I.getType())) { -            Value *NewOp = Builder->CreateOr(Op0C->getOperand(0), -                                             Op1C->getOperand(0), I.getName()); +              ShouldOptimizeCast(Op0C->getOpcode(), Op0COp, I.getType()) && +              ShouldOptimizeCast(Op1C->getOpcode(), Op1COp, I.getType())) { +            Value *NewOp = Builder->CreateOr(Op0COp, Op1COp, I.getName());              return CastInst::Create(Op0C->getOpcode(), NewOp, I.getType());            } +           +          // If this is or(cast(icmp), cast(icmp)), try to fold this even if the +          // cast is otherwise not optimizable.  This happens for vector sexts. +          if (ICmpInst *RHS = dyn_cast<ICmpInst>(Op1COp)) +            if (ICmpInst *LHS = dyn_cast<ICmpInst>(Op0COp)) +              if (Instruction *Res = FoldOrOfICmps(I, LHS, RHS)) { +                InsertNewInstBefore(Res, I); +                return CastInst::Create(Op0C->getOpcode(), Res, I.getType()); +              } +           +          // If this is or(cast(fcmp), cast(fcmp)), try to fold this even if the +          // cast is otherwise not optimizable.  This happens for vector sexts. +          if (FCmpInst *RHS = dyn_cast<FCmpInst>(Op1COp)) +            if (FCmpInst *LHS = dyn_cast<FCmpInst>(Op0COp)) +              if (Instruction *Res = FoldOrOfFCmps(I, LHS, RHS)) { +                InsertNewInstBefore(Res, I); +                return CastInst::Create(Op0C->getOpcode(), Res, I.getType()); +              }          }        }    } -     -  // (fcmp uno x, c) | (fcmp uno y, c)  -> (fcmp uno x, y) -  if (FCmpInst *LHS = dyn_cast<FCmpInst>(I.getOperand(0))) { -    if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand(1))) -      if (Instruction *Res = FoldOrOfFCmps(I, LHS, RHS)) -        return Res; -  } -    return Changed ? &I : 0;  } @@ -1978,12 +2016,12 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {      if (CastInst *Op1C = dyn_cast<CastInst>(Op1))        if (Op0C->getOpcode() == Op1C->getOpcode()) { // same cast kind?          const Type *SrcTy = Op0C->getOperand(0)->getType(); -        if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isInteger() && +        if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isIntegerTy() &&              // Only do this if the casts both really cause code to be generated. -            ValueRequiresCast(Op0C->getOpcode(), Op0C->getOperand(0),  -                              I.getType()) && -            ValueRequiresCast(Op1C->getOpcode(), Op1C->getOperand(0),  -                              I.getType())) { +            ShouldOptimizeCast(Op0C->getOpcode(), Op0C->getOperand(0),  +                               I.getType()) && +            ShouldOptimizeCast(Op1C->getOpcode(), Op1C->getOperand(0),  +                               I.getType())) {            Value *NewOp = Builder->CreateXor(Op0C->getOperand(0),                                              Op1C->getOperand(0), I.getName());            return CastInst::Create(Op0C->getOpcode(), NewOp, I.getType());  | 
