Details
Details
Diff Detail
Diff Detail
- Repository
- rL LLVM
Event Timeline
Comment Actions
I think the patch is correct, but it's hard to keep all of the values straight (because there are a lot!). What do you think about rearranging it a bit like this and using m_c_And():
/// We want to turn: /// (select (icmp eq (and X, Y), 0), (and (lshr X, Z), 1), 1) /// into: /// zext (icmp ne i32 (and X, (or Y, (shl 1, Z))), 0) /// Note: /// Z may be 0 if lshr is missing. /// Worst-case scenario is that we will replace 5 instructions with 5 different /// instructions, but we got rid of select. static Instruction *foldSelectICmpAndAnd(Type *SelType, const ICmpInst *Cmp, Value *TVal, Value *FVal, InstCombiner::BuilderTy &Builder) { if (!Cmp->hasOneUse() || !Cmp->getOperand(0)->hasOneUse() || Cmp->getPredicate() != ICmpInst::ICMP_EQ || !match(Cmp->getOperand(1), m_Zero()) || !match(FVal, m_One())) return nullptr; // The TrueVal has general form of: // and %B, 1 // where %B may be optionally shifted: lshr %X, %Z. Value *B; if (!match(TVal, m_OneUse(m_And(m_Value(B), m_One())))) return nullptr; Value *X, *Y, *Z; bool HasShift = match(B, m_OneUse(m_LShr(m_Value(X), m_Value(Z)))); if (!HasShift) X = B; if (!match(Cmp->getOperand(0), m_c_And(m_Specific(X), m_Value(Y)))) return nullptr; // ((X & Y) == 0) ? ((X >> Z) & 1) : 1 --> (X & (Y | (1 << Z))) != 0 // ((X & Y) == 0) ? (X & 1) : 1 --> (X & (Y | 1)) != 0 Constant *One = ConstantInt::get(SelType, 1); Value *MaskB = HasShift ? Builder.CreateShl(One, Z) : One; Value *FullMask = Builder.CreateOr(Y, MaskB); Value *MaskedX = Builder.CreateAnd(X, FullMask); Value *ICmpNeZero = Builder.CreateIsNotNull(MaskedX); return new ZExtInst(ICmpNeZero, SelType); }