ConstantRange ConstantRange::binaryOr(const ConstantRange &Other) const { if (isEmptySet() || Other.isEmptySet()) return ConstantRange(getBitWidth(), /*isFullSet=*/false); // TODO: replace this with something less conservative APInt umax = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin()); if (umax.isNullValue()) return ConstantRange(getBitWidth(), /*isFullSet=*/true); return ConstantRange(std::move(umax), APInt::getNullValue(getBitWidth())); }
/// Emit a diagnostic for `poundAssert` builtins whose condition is /// false or whose condition cannot be evaluated. static void diagnosePoundAssert(const SILInstruction *I, SILModule &M, ConstExprEvaluator &constantEvaluator) { auto *builtinInst = dyn_cast<BuiltinInst>(I); if (!builtinInst || builtinInst->getBuiltinKind() != BuiltinValueKind::PoundAssert) return; SmallVector<SymbolicValue, 1> values; constantEvaluator.computeConstantValues({builtinInst->getArguments()[0]}, values); SymbolicValue value = values[0]; if (!value.isConstant()) { diagnose(M.getASTContext(), I->getLoc().getSourceLoc(), diag::pound_assert_condition_not_constant); // If we have more specific information about what went wrong, emit // notes. if (value.getKind() == SymbolicValue::Unknown) value.emitUnknownDiagnosticNotes(builtinInst->getLoc()); return; } assert(value.getKind() == SymbolicValue::Integer && "sema prevents non-integer #assert condition"); APInt intValue = value.getIntegerValue(); assert(intValue.getBitWidth() == 1 && "sema prevents non-int1 #assert condition"); if (intValue.isNullValue()) { auto *message = cast<StringLiteralInst>(builtinInst->getArguments()[1]); StringRef messageValue = message->getValue(); if (messageValue.empty()) messageValue = "assertion failed"; diagnose(M.getASTContext(), I->getLoc().getSourceLoc(), diag::pound_assert_failure, messageValue); return; } }
MyConstantRange binaryOr(const MyConstantRange &Other) const { if (isEmptySet() || Other.isEmptySet()) return MyConstantRange(getBitWidth(), /*isFullSet=*/false); if (!isWrappedSet() && !Other.isWrappedSet() && !isFullSet() && !Other.isFullSet()) { unsigned width1 = ((getUpper() - 1) ^ getLower()).getActiveBits(); unsigned width2 = ((Other.getUpper() - 1) ^ Other.getLower()).getActiveBits(); 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 umax = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin()); if (umax.isNullValue()) return MyConstantRange(getBitWidth(), /*isFullSet=*/true); return MyConstantRange(std::move(umax), APInt::getNullValue(getBitWidth())); }
ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const { assert(getBitWidth() == CR.getBitWidth() && "ConstantRange types don't agree!"); if ( isFullSet() || CR.isEmptySet()) return *this; if (CR.isFullSet() || isEmptySet()) return CR; if (!isWrappedSet() && CR.isWrappedSet()) return CR.unionWith(*this); if (!isWrappedSet() && !CR.isWrappedSet()) { if (CR.Upper.ult(Lower) || Upper.ult(CR.Lower)) { // If the two ranges are disjoint, find the smaller gap and bridge it. APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper; if (d1.ult(d2)) return ConstantRange(Lower, CR.Upper); return ConstantRange(CR.Lower, Upper); } APInt L = CR.Lower.ult(Lower) ? CR.Lower : Lower; APInt U = (CR.Upper - 1).ugt(Upper - 1) ? CR.Upper : Upper; if (L.isNullValue() && U.isNullValue()) return ConstantRange(getBitWidth()); return ConstantRange(std::move(L), std::move(U)); } if (!CR.isWrappedSet()) { // ------U L----- and ------U L----- : this // L--U L--U : CR if (CR.Upper.ule(Upper) || CR.Lower.uge(Lower)) return *this; // ------U L----- : this // L---------U : CR if (CR.Lower.ule(Upper) && Lower.ule(CR.Upper)) return ConstantRange(getBitWidth()); // ----U L---- : this // L---U : CR // <d1> <d2> if (Upper.ule(CR.Lower) && CR.Upper.ule(Lower)) { APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper; if (d1.ult(d2)) return ConstantRange(Lower, CR.Upper); return ConstantRange(CR.Lower, Upper); } // ----U L----- : this // L----U : CR if (Upper.ult(CR.Lower) && Lower.ult(CR.Upper)) return ConstantRange(CR.Lower, Upper); // ------U L---- : this // L-----U : CR assert(CR.Lower.ult(Upper) && CR.Upper.ult(Lower) && "ConstantRange::unionWith missed a case with one range wrapped"); return ConstantRange(Lower, CR.Upper); } // ------U L---- and ------U L---- : this // -U L----------- and ------------U L : CR if (CR.Lower.ule(Upper) || Lower.ule(CR.Upper)) return ConstantRange(getBitWidth()); APInt L = CR.Lower.ult(Lower) ? CR.Lower : Lower; APInt U = CR.Upper.ugt(Upper) ? CR.Upper : Upper; return ConstantRange(std::move(L), std::move(U)); }