[llvm] [llubi] Implement intrinsics for integer arithmetic/bit manipulation (PR #193702)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 23 02:58:47 PDT 2026
================
@@ -381,6 +472,171 @@ class InstExecutor : public InstVisitor<InstExecutor, void>,
}
return AnyValue();
}
+ case Intrinsic::ssa_copy:
+ case Intrinsic::expect:
+ case Intrinsic::expect_with_probability:
+ return getValue(CB.getArgOperand(0));
+ case Intrinsic::donothing:
+ return AnyValue();
+ case Intrinsic::vscale:
+ return APInt(RetTy->getScalarSizeInBits(), Ctx.getVScale());
+ case Intrinsic::abs: {
+ const bool IsIntMinPoison =
+ getBooleanNonPoison(getValue(CB.getArgOperand(1)).asBoolean());
+ return visitIntUnOpWithResult(CB, [&](const APInt &Operand) -> AnyValue {
+ if (IsIntMinPoison && Operand.isMinSignedValue())
+ return AnyValue::poison();
+ return Operand.abs();
+ });
+ }
+ case Intrinsic::smax: {
+ return visitIntBinOpWithResult(
+ CB, [](const APInt &LHS, const APInt &RHS) -> AnyValue {
+ return APIntOps::smax(LHS, RHS);
+ });
+ }
+ case Intrinsic::smin: {
+ return visitIntBinOpWithResult(
+ CB, [](const APInt &LHS, const APInt &RHS) -> AnyValue {
+ return APIntOps::smin(LHS, RHS);
+ });
+ }
+ case Intrinsic::umax: {
+ return visitIntBinOpWithResult(
+ CB, [](const APInt &LHS, const APInt &RHS) -> AnyValue {
+ return APIntOps::umax(LHS, RHS);
+ });
+ }
+ case Intrinsic::umin: {
+ return visitIntBinOpWithResult(
+ CB, [](const APInt &LHS, const APInt &RHS) -> AnyValue {
+ return APIntOps::umin(LHS, RHS);
+ });
+ }
+ case Intrinsic::scmp:
+ case Intrinsic::ucmp: {
+ std::uint32_t BitWidth = RetTy->getScalarSizeInBits();
+ return visitIntBinOpWithResult(
+ CB, [&](const APInt &LHS, const APInt &RHS) -> AnyValue {
+ if (LHS == RHS)
+ return APInt::getZero(BitWidth);
+ if (IID == Intrinsic::scmp)
+ return LHS.slt(RHS) ? APInt::getAllOnes(BitWidth)
+ : APInt(BitWidth, 1);
+ return LHS.ult(RHS) ? APInt::getAllOnes(BitWidth)
+ : APInt(BitWidth, 1);
+ });
+ }
+ case Intrinsic::bitreverse: {
+ return visitIntUnOpWithResult(CB, [](const APInt &Operand) -> AnyValue {
+ return Operand.reverseBits();
+ });
+ }
+ case Intrinsic::bswap: {
+ return visitIntUnOpWithResult(CB, [](const APInt &Operand) -> AnyValue {
+ return Operand.byteSwap();
+ });
+ }
+ case Intrinsic::ctpop: {
+ return visitIntUnOpWithResult(CB, [](const APInt &Operand) -> AnyValue {
+ return APInt(Operand.getBitWidth(), Operand.popcount());
+ });
+ }
+ case Intrinsic::ctlz:
+ case Intrinsic::cttz: {
+ const bool IsZeroPoison =
+ getBooleanNonPoison(getValue(CB.getArgOperand(1)).asBoolean());
+ return visitIntUnOpWithResult(CB, [&](const APInt &Operand) -> AnyValue {
+ if (IsZeroPoison && Operand.isZero())
+ return AnyValue::poison();
+ if (IID == Intrinsic::ctlz)
+ return APInt(Operand.getBitWidth(), Operand.countl_zero());
+ return APInt(Operand.getBitWidth(), Operand.countr_zero());
+ });
+ }
+ case Intrinsic::fshl:
+ case Intrinsic::fshr: {
+ return visitIntTriOpWithResult(
+ CB,
+ [IID](const APInt &Op1, const APInt &Op2,
+ const APInt &Op3) -> AnyValue {
+ const std::uint32_t BitWidth = Op1.getBitWidth();
+ const std::uint32_t ShiftAmount = Op3.urem(BitWidth);
+ const bool IsFShr = IID == Intrinsic::fshr;
+ const std::uint32_t LShrAmount =
+ IsFShr ? ShiftAmount : BitWidth - ShiftAmount;
+ const std::uint32_t ShlAmount =
+ !IsFShr ? ShiftAmount : BitWidth - ShiftAmount;
+ return Op1.shl(ShlAmount) | Op2.lshr(LShrAmount);
----------------
nikic wrote:
I think we'll get UB here if ShiftAmount is zero? Probably need to handle that explicitly.
https://github.com/llvm/llvm-project/pull/193702
More information about the llvm-commits
mailing list