ConstantRange ConstantRange::binaryAnd(const ConstantRange &Other) const { if (isEmptySet() || Other.isEmptySet()) return ConstantRange(getBitWidth(), /*isFullSet=*/false); // TODO: replace this with something less conservative APInt umin = APIntOps::umin(Other.getUnsignedMax(), getUnsignedMax()); if (umin.isAllOnesValue()) return ConstantRange(getBitWidth(), /*isFullSet=*/true); return ConstantRange(APInt::getNullValue(getBitWidth()), umin + 1); }
Value *StraightLineStrengthReduce::emitBump(const Candidate &Basis, const Candidate &C, IRBuilder<> &Builder, const DataLayout *DL, bool &BumpWithUglyGEP) { APInt Idx = C.Index->getValue(), BasisIdx = Basis.Index->getValue(); unifyBitWidth(Idx, BasisIdx); APInt IndexOffset = Idx - BasisIdx; BumpWithUglyGEP = false; if (Basis.CandidateKind == Candidate::GEP) { APInt ElementSize( IndexOffset.getBitWidth(), DL->getTypeAllocSize( cast<GetElementPtrInst>(Basis.Ins)->getResultElementType())); APInt Q, R; APInt::sdivrem(IndexOffset, ElementSize, Q, R); if (R == 0) IndexOffset = Q; else BumpWithUglyGEP = true; } // Compute Bump = C - Basis = (i' - i) * S. // Common case 1: if (i' - i) is 1, Bump = S. if (IndexOffset == 1) return C.Stride; // Common case 2: if (i' - i) is -1, Bump = -S. if (IndexOffset.isAllOnesValue()) return Builder.CreateNeg(C.Stride); // Otherwise, Bump = (i' - i) * sext/trunc(S). Note that (i' - i) and S may // have different bit widths. IntegerType *DeltaType = IntegerType::get(Basis.Ins->getContext(), IndexOffset.getBitWidth()); Value *ExtendedStride = Builder.CreateSExtOrTrunc(C.Stride, DeltaType); if (IndexOffset.isPowerOf2()) { // If (i' - i) is a power of 2, Bump = sext/trunc(S) << log(i' - i). ConstantInt *Exponent = ConstantInt::get(DeltaType, IndexOffset.logBase2()); return Builder.CreateShl(ExtendedStride, Exponent); } if ((-IndexOffset).isPowerOf2()) { // If (i - i') is a power of 2, Bump = -sext/trunc(S) << log(i' - i). ConstantInt *Exponent = ConstantInt::get(DeltaType, (-IndexOffset).logBase2()); return Builder.CreateNeg(Builder.CreateShl(ExtendedStride, Exponent)); } Constant *Delta = ConstantInt::get(DeltaType, IndexOffset); return Builder.CreateMul(ExtendedStride, Delta); }
int ARMTTIImpl::getIntImmCost(unsigned Opcode, unsigned Idx, const APInt &Imm, Type *Ty) { // Division by a constant can be turned into multiplication, but only if we // know it's constant. So it's not so much that the immediate is cheap (it's // not), but that the alternative is worse. // FIXME: this is probably unneeded with GlobalISel. if ((Opcode == Instruction::SDiv || Opcode == Instruction::UDiv || Opcode == Instruction::SRem || Opcode == Instruction::URem) && Idx == 1) return 0; if (Opcode == Instruction::And) { // UXTB/UXTH if (Imm == 255 || Imm == 65535) return 0; // Conversion to BIC is free, and means we can use ~Imm instead. return std::min(getIntImmCost(Imm, Ty), getIntImmCost(~Imm, Ty)); } if (Opcode == Instruction::Add) // Conversion to SUB is free, and means we can use -Imm instead. return std::min(getIntImmCost(Imm, Ty), getIntImmCost(-Imm, Ty)); if (Opcode == Instruction::ICmp && Imm.isNegative() && Ty->getIntegerBitWidth() == 32) { int64_t NegImm = -Imm.getSExtValue(); if (ST->isThumb2() && NegImm < 1<<12) // icmp X, #-C -> cmn X, #C return 0; if (ST->isThumb() && NegImm < 1<<8) // icmp X, #-C -> adds X, #C return 0; } // xor a, -1 can always be folded to MVN if (Opcode == Instruction::Xor && Imm.isAllOnesValue()) return 0; return getIntImmCost(Imm, Ty); }
void EnumPayload::emitApplyAndMask(IRGenFunction &IGF, APInt mask) { // Early exit if the mask has no effect. if (mask.isAllOnesValue()) return; auto &DL = IGF.IGM.DataLayout; for (auto &pv : PayloadValues) { auto payloadTy = getPayloadType(pv); unsigned size = DL.getTypeSizeInBits(payloadTy); // Break off a chunk of the mask. auto maskPiece = mask.zextOrTrunc(size); mask = mask.lshr(size); // If this piece is all ones, it has no effect. if (maskPiece.isAllOnesValue()) continue; // If the payload value is vacant, the mask can't change it. if (pv.is<llvm::Type *>()) continue; // If this piece is zero, it wipes out the chunk entirely, and we can // drop it. if (maskPiece == 0) { pv = payloadTy; continue; } // Otherwise, apply the mask to the existing value. auto v = pv.get<llvm::Value*>(); auto payloadIntTy = llvm::IntegerType::get(IGF.IGM.getLLVMContext(), size); auto maskConstant = llvm::ConstantInt::get(payloadIntTy, maskPiece); v = IGF.Builder.CreateBitOrPointerCast(v, payloadIntTy); v = IGF.Builder.CreateAnd(v, maskConstant); v = IGF.Builder.CreateBitOrPointerCast(v, payloadTy); pv = v; } }
MyConstantRange binaryAnd(const ConstantRange &Other) const { if (isEmptySet() || Other.isEmptySet()) return MyConstantRange(getBitWidth(), /*isFullSet=*/false); if (!isWrappedSet() && !Other.isWrappedSet() && !isFullSet() && !Other.isFullSet()) { unsigned width1 = ((getUpper() - 1) ^ getLower()).logBase2() + 1; unsigned width2 = ((Other.getUpper() - 1) ^ Other.getLower()).logBase2() + 1; APInt res1 = getLower().lshr(width1) << width1; APInt res2 = Other.getLower().lshr(width2) << width2; APInt res_high1 = getLower(); APInt res_high2 = Other.getLower(); res_high1.setLowBits(width1); res_high2.setLowBits(width2); if ((res1 & res2).isNullValue() && (res_high1 & res_high2).isAllOnesValue()) { return MyConstantRange(getBitWidth(), /*isFullSet=*/true); } return MyConstantRange(res1 & res2, (res_high1 & res_high2) + 1); } APInt umin = APIntOps::umin(Other.getUnsignedMax(), getUnsignedMax()); if (umin.isAllOnesValue()) return MyConstantRange(getBitWidth(), /*isFullSet=*/true); return MyConstantRange(APInt::getNullValue(getBitWidth()), std::move(umin) + 1); }