diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Analysis/ConstantFolding.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/Analysis/ConstantFolding.cpp | 189 |
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; |
