aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Analysis/ConstantFolding.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Analysis/ConstantFolding.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Analysis/ConstantFolding.cpp189
1 files changed, 106 insertions, 83 deletions
diff --git a/contrib/llvm-project/llvm/lib/Analysis/ConstantFolding.cpp b/contrib/llvm-project/llvm/lib/Analysis/ConstantFolding.cpp
index 38cccb3ea3c2..90da3390eab3 100644
--- a/contrib/llvm-project/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/contrib/llvm-project/llvm/lib/Analysis/ConstantFolding.cpp
@@ -227,11 +227,16 @@ Constant *FoldBitCast(Constant *C, Type *DestTy, const DataLayout &DL) {
return ConstantExpr::getBitCast(C, DestTy);
// Zero extend the element to the right size.
- Src = ConstantExpr::getZExt(Src, Elt->getType());
+ Src = ConstantFoldCastOperand(Instruction::ZExt, Src, Elt->getType(),
+ DL);
+ assert(Src && "Constant folding cannot fail on plain integers");
// Shift it to the right place, depending on endianness.
- Src = ConstantExpr::getShl(Src,
- ConstantInt::get(Src->getType(), ShiftAmt));
+ Src = ConstantFoldBinaryOpOperands(
+ Instruction::Shl, Src, ConstantInt::get(Src->getType(), ShiftAmt),
+ DL);
+ assert(Src && "Constant folding cannot fail on plain integers");
+
ShiftAmt += isLittleEndian ? SrcBitSize : -SrcBitSize;
// Mix it in.
@@ -268,21 +273,11 @@ Constant *FoldBitCast(Constant *C, Type *DestTy, const DataLayout &DL) {
for (unsigned j = 0; j != Ratio; ++j) {
// Shift the piece of the value into the right place, depending on
// endianness.
- Constant *Elt = ConstantExpr::getLShr(Src,
- ConstantInt::get(Src->getType(), ShiftAmt));
+ APInt Elt = Src->getValue().lshr(ShiftAmt);
ShiftAmt += isLittleEndian ? DstBitSize : -DstBitSize;
- // Truncate the element to an integer with the same pointer size and
- // convert the element back to a pointer using a inttoptr.
- if (DstEltTy->isPointerTy()) {
- IntegerType *DstIntTy = Type::getIntNTy(C->getContext(), DstBitSize);
- Constant *CE = ConstantExpr::getTrunc(Elt, DstIntTy);
- Result.push_back(ConstantExpr::getIntToPtr(CE, DstEltTy));
- continue;
- }
-
// Truncate and remember this piece.
- Result.push_back(ConstantExpr::getTrunc(Elt, DstEltTy));
+ Result.push_back(ConstantInt::get(DstEltTy, Elt.trunc(DstBitSize)));
}
}
@@ -378,7 +373,7 @@ Constant *llvm::ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy,
Cast = Instruction::PtrToInt;
if (CastInst::castIsValid(Cast, C, DestTy))
- return ConstantExpr::getCast(Cast, C, DestTy);
+ return ConstantFoldCastOperand(Cast, C, DestTy, DL);
}
// If this isn't an aggregate type, there is nothing we can do to drill down
@@ -583,7 +578,7 @@ Constant *FoldReinterpretLoadFromConst(Constant *C, Type *LoadTy,
if (DL.isNonIntegralPointerType(LoadTy->getScalarType()))
// Be careful not to replace a load of an addrspace value with an inttoptr here
return nullptr;
- Res = ConstantExpr::getCast(Instruction::IntToPtr, Res, LoadTy);
+ Res = ConstantExpr::getIntToPtr(Res, LoadTy);
}
return Res;
}
@@ -841,14 +836,14 @@ Constant *CastGEPIndices(Type *SrcElemTy, ArrayRef<Constant *> Ops,
SrcElemTy, Ops.slice(1, i - 1)))) &&
Ops[i]->getType()->getScalarType() != IntIdxScalarTy) {
Any = true;
- Type *NewType = Ops[i]->getType()->isVectorTy()
- ? IntIdxTy
- : IntIdxScalarTy;
- NewIdxs.push_back(ConstantExpr::getCast(CastInst::getCastOpcode(Ops[i],
- true,
- NewType,
- true),
- Ops[i], NewType));
+ Type *NewType =
+ Ops[i]->getType()->isVectorTy() ? IntIdxTy : IntIdxScalarTy;
+ Constant *NewIdx = ConstantFoldCastOperand(
+ CastInst::getCastOpcode(Ops[i], true, NewType, true), Ops[i], NewType,
+ DL);
+ if (!NewIdx)
+ return nullptr;
+ NewIdxs.push_back(NewIdx);
} else
NewIdxs.push_back(Ops[i]);
}
@@ -861,20 +856,6 @@ Constant *CastGEPIndices(Type *SrcElemTy, ArrayRef<Constant *> Ops,
return ConstantFoldConstant(C, DL, TLI);
}
-/// Strip the pointer casts, but preserve the address space information.
-// TODO: This probably doesn't make sense with opaque pointers.
-static Constant *StripPtrCastKeepAS(Constant *Ptr) {
- assert(Ptr->getType()->isPointerTy() && "Not a pointer type");
- auto *OldPtrTy = cast<PointerType>(Ptr->getType());
- Ptr = cast<Constant>(Ptr->stripPointerCasts());
- auto *NewPtrTy = cast<PointerType>(Ptr->getType());
-
- // Preserve the address space number of the pointer.
- if (NewPtrTy->getAddressSpace() != OldPtrTy->getAddressSpace())
- Ptr = ConstantExpr::getPointerCast(Ptr, OldPtrTy);
- return Ptr;
-}
-
/// If we can symbolically evaluate the GEP constant expression, do so.
Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
ArrayRef<Constant *> Ops,
@@ -909,7 +890,6 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
BitWidth,
DL.getIndexedOffsetInType(
SrcElemTy, ArrayRef((Value *const *)Ops.data() + 1, Ops.size() - 1)));
- Ptr = StripPtrCastKeepAS(Ptr);
// If this is a GEP of a GEP, fold it all into a single GEP.
while (auto *GEP = dyn_cast<GEPOperator>(Ptr)) {
@@ -931,7 +911,6 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP,
Ptr = cast<Constant>(GEP->getOperand(0));
SrcElemTy = GEP->getSourceElementType();
Offset += APInt(BitWidth, DL.getIndexedOffsetInType(SrcElemTy, NestedOps));
- Ptr = StripPtrCastKeepAS(Ptr);
}
// If the base value for this address is a literal integer value, fold the
@@ -1228,10 +1207,11 @@ Constant *llvm::ConstantFoldCompareInstOperands(
Type *IntPtrTy = DL.getIntPtrType(CE0->getType());
// Convert the integer value to the right size to ensure we get the
// proper extension or truncation.
- Constant *C = ConstantExpr::getIntegerCast(CE0->getOperand(0),
- IntPtrTy, false);
- Constant *Null = Constant::getNullValue(C->getType());
- return ConstantFoldCompareInstOperands(Predicate, C, Null, DL, TLI);
+ if (Constant *C = ConstantFoldIntegerCast(CE0->getOperand(0), IntPtrTy,
+ /*IsSigned*/ false, DL)) {
+ Constant *Null = Constant::getNullValue(C->getType());
+ return ConstantFoldCompareInstOperands(Predicate, C, Null, DL, TLI);
+ }
}
// Only do this transformation if the int is intptrty in size, otherwise
@@ -1253,11 +1233,12 @@ Constant *llvm::ConstantFoldCompareInstOperands(
// Convert the integer value to the right size to ensure we get the
// proper extension or truncation.
- Constant *C0 = ConstantExpr::getIntegerCast(CE0->getOperand(0),
- IntPtrTy, false);
- Constant *C1 = ConstantExpr::getIntegerCast(CE1->getOperand(0),
- IntPtrTy, false);
- return ConstantFoldCompareInstOperands(Predicate, C0, C1, DL, TLI);
+ Constant *C0 = ConstantFoldIntegerCast(CE0->getOperand(0), IntPtrTy,
+ /*IsSigned*/ false, DL);
+ Constant *C1 = ConstantFoldIntegerCast(CE1->getOperand(0), IntPtrTy,
+ /*IsSigned*/ false, DL);
+ if (C0 && C1)
+ return ConstantFoldCompareInstOperands(Predicate, C0, C1, DL, TLI);
}
// Only do this transformation if the int is intptrty in size, otherwise
@@ -1273,19 +1254,6 @@ Constant *llvm::ConstantFoldCompareInstOperands(
}
}
- // icmp eq (or x, y), 0 -> (icmp eq x, 0) & (icmp eq y, 0)
- // icmp ne (or x, y), 0 -> (icmp ne x, 0) | (icmp ne y, 0)
- if ((Predicate == ICmpInst::ICMP_EQ || Predicate == ICmpInst::ICMP_NE) &&
- CE0->getOpcode() == Instruction::Or && Ops1->isNullValue()) {
- Constant *LHS = ConstantFoldCompareInstOperands(
- Predicate, CE0->getOperand(0), Ops1, DL, TLI);
- Constant *RHS = ConstantFoldCompareInstOperands(
- Predicate, CE0->getOperand(1), Ops1, DL, TLI);
- unsigned OpC =
- Predicate == ICmpInst::ICMP_EQ ? Instruction::And : Instruction::Or;
- return ConstantFoldBinaryOpOperands(OpC, LHS, RHS, DL);
- }
-
// Convert pointer comparison (base+offset1) pred (base+offset2) into
// offset1 pred offset2, for the case where the offset is inbounds. This
// only works for equality and unsigned comparison, as inbounds permits
@@ -1425,9 +1393,9 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C,
// the width of a pointer, so it can't be done in ConstantExpr::getCast.
if (CE->getOpcode() == Instruction::IntToPtr) {
// zext/trunc the inttoptr to pointer size.
- FoldedValue = ConstantExpr::getIntegerCast(
- CE->getOperand(0), DL.getIntPtrType(CE->getType()),
- /*IsSigned=*/false);
+ FoldedValue = ConstantFoldIntegerCast(CE->getOperand(0),
+ DL.getIntPtrType(CE->getType()),
+ /*IsSigned=*/false, DL);
} else if (auto *GEP = dyn_cast<GEPOperator>(CE)) {
// If we have GEP, we can perform the following folds:
// (ptrtoint (gep null, x)) -> x
@@ -1455,11 +1423,11 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C,
}
if (FoldedValue) {
// Do a zext or trunc to get to the ptrtoint dest size.
- return ConstantExpr::getIntegerCast(FoldedValue, DestTy,
- /*IsSigned=*/false);
+ return ConstantFoldIntegerCast(FoldedValue, DestTy, /*IsSigned=*/false,
+ DL);
}
}
- return ConstantExpr::getCast(Opcode, C, DestTy);
+ break;
case Instruction::IntToPtr:
// If the input is a ptrtoint, turn the pair into a ptr to ptr bitcast if
// the int size is >= the ptr size and the address spaces are the same.
@@ -1478,8 +1446,7 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C,
}
}
}
-
- return ConstantExpr::getCast(Opcode, C, DestTy);
+ break;
case Instruction::Trunc:
case Instruction::ZExt:
case Instruction::SExt:
@@ -1490,10 +1457,26 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C,
case Instruction::FPToUI:
case Instruction::FPToSI:
case Instruction::AddrSpaceCast:
- return ConstantExpr::getCast(Opcode, C, DestTy);
+ break;
case Instruction::BitCast:
return FoldBitCast(C, DestTy, DL);
}
+
+ if (ConstantExpr::isDesirableCastOp(Opcode))
+ return ConstantExpr::getCast(Opcode, C, DestTy);
+ return ConstantFoldCastInstruction(Opcode, C, DestTy);
+}
+
+Constant *llvm::ConstantFoldIntegerCast(Constant *C, Type *DestTy,
+ bool IsSigned, const DataLayout &DL) {
+ Type *SrcTy = C->getType();
+ if (SrcTy == DestTy)
+ return C;
+ if (SrcTy->getScalarSizeInBits() > DestTy->getScalarSizeInBits())
+ return ConstantFoldCastOperand(Instruction::Trunc, C, DestTy, DL);
+ if (IsSigned)
+ return ConstantFoldCastOperand(Instruction::SExt, C, DestTy, DL);
+ return ConstantFoldCastOperand(Instruction::ZExt, C, DestTy, DL);
}
//===----------------------------------------------------------------------===//
@@ -1548,6 +1531,11 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
case Intrinsic::vector_reduce_umax:
// Target intrinsics
case Intrinsic::amdgcn_perm:
+ case Intrinsic::amdgcn_wave_reduce_umin:
+ case Intrinsic::amdgcn_wave_reduce_umax:
+ case Intrinsic::amdgcn_s_wqm:
+ case Intrinsic::amdgcn_s_quadmask:
+ case Intrinsic::amdgcn_s_bitreplicate:
case Intrinsic::arm_mve_vctp8:
case Intrinsic::arm_mve_vctp16:
case Intrinsic::arm_mve_vctp32:
@@ -1569,11 +1557,13 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
case Intrinsic::log10:
case Intrinsic::exp:
case Intrinsic::exp2:
+ case Intrinsic::exp10:
case Intrinsic::sqrt:
case Intrinsic::sin:
case Intrinsic::cos:
case Intrinsic::pow:
case Intrinsic::powi:
+ case Intrinsic::ldexp:
case Intrinsic::fma:
case Intrinsic::fmuladd:
case Intrinsic::frexp:
@@ -1589,7 +1579,6 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
case Intrinsic::amdgcn_fmul_legacy:
case Intrinsic::amdgcn_fma_legacy:
case Intrinsic::amdgcn_fract:
- case Intrinsic::amdgcn_ldexp:
case Intrinsic::amdgcn_sin:
// The intrinsics below depend on rounding mode in MXCSR.
case Intrinsic::x86_sse_cvtss2si:
@@ -2227,6 +2216,9 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
case Intrinsic::exp2:
// Fold exp2(x) as pow(2, x), in case the host lacks a C99 library.
return ConstantFoldBinaryFP(pow, APFloat(2.0), APF, Ty);
+ case Intrinsic::exp10:
+ // Fold exp10(x) as pow(10, x), in case the host lacks a C99 library.
+ return ConstantFoldBinaryFP(pow, APFloat(10.0), APF, Ty);
case Intrinsic::sin:
return ConstantFoldFP(sin, APF, Ty);
case Intrinsic::cos:
@@ -2433,6 +2425,39 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
return ConstantFP::get(Ty->getContext(), Val);
}
+
+ case Intrinsic::amdgcn_s_wqm: {
+ uint64_t Val = Op->getZExtValue();
+ Val |= (Val & 0x5555555555555555ULL) << 1 |
+ ((Val >> 1) & 0x5555555555555555ULL);
+ Val |= (Val & 0x3333333333333333ULL) << 2 |
+ ((Val >> 2) & 0x3333333333333333ULL);
+ return ConstantInt::get(Ty, Val);
+ }
+
+ case Intrinsic::amdgcn_s_quadmask: {
+ uint64_t Val = Op->getZExtValue();
+ uint64_t QuadMask = 0;
+ for (unsigned I = 0; I < Op->getBitWidth() / 4; ++I, Val >>= 4) {
+ if (!(Val & 0xF))
+ continue;
+
+ QuadMask |= (1ULL << I);
+ }
+ return ConstantInt::get(Ty, QuadMask);
+ }
+
+ case Intrinsic::amdgcn_s_bitreplicate: {
+ uint64_t Val = Op->getZExtValue();
+ Val = (Val & 0x000000000000FFFFULL) | (Val & 0x00000000FFFF0000ULL) << 16;
+ Val = (Val & 0x000000FF000000FFULL) | (Val & 0x0000FF000000FF00ULL) << 8;
+ Val = (Val & 0x000F000F000F000FULL) | (Val & 0x00F000F000F000F0ULL) << 4;
+ Val = (Val & 0x0303030303030303ULL) | (Val & 0x0C0C0C0C0C0C0C0CULL) << 2;
+ Val = (Val & 0x1111111111111111ULL) | (Val & 0x2222222222222222ULL) << 1;
+ Val = Val | Val << 1;
+ return ConstantInt::get(Ty, Val);
+ }
+
default:
return nullptr;
}
@@ -2650,6 +2675,11 @@ static Constant *ConstantFoldScalarCall2(StringRef Name,
}
} else if (auto *Op2C = dyn_cast<ConstantInt>(Operands[1])) {
switch (IntrinsicID) {
+ case Intrinsic::ldexp: {
+ return ConstantFP::get(
+ Ty->getContext(),
+ scalbn(Op1V, Op2C->getSExtValue(), APFloat::rmNearestTiesToEven));
+ }
case Intrinsic::is_fpclass: {
FPClassTest Mask = static_cast<FPClassTest>(Op2C->getZExtValue());
bool Result =
@@ -2686,16 +2716,6 @@ static Constant *ConstantFoldScalarCall2(StringRef Name,
Ty->getContext(),
APFloat((double)std::pow(Op1V.convertToDouble(),
(int)Op2C->getZExtValue())));
-
- if (IntrinsicID == Intrinsic::amdgcn_ldexp) {
- // FIXME: Should flush denorms depending on FP mode, but that's ignored
- // everywhere else.
-
- // scalbn is equivalent to ldexp with float radix 2
- APFloat Result = scalbn(Op1->getValueAPF(), Op2C->getSExtValue(),
- APFloat::rmNearestTiesToEven);
- return ConstantFP::get(Ty->getContext(), Result);
- }
}
return nullptr;
}
@@ -2839,6 +2859,9 @@ static Constant *ConstantFoldScalarCall2(StringRef Name,
return Constant::getNullValue(Ty);
return ConstantInt::get(Ty, C0->abs());
+ case Intrinsic::amdgcn_wave_reduce_umin:
+ case Intrinsic::amdgcn_wave_reduce_umax:
+ return dyn_cast<Constant>(Operands[0]);
}
return nullptr;