10b57cec5SDimitry Andric //===-- ConstantFolding.cpp - Fold instructions into constants ------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file defines routines for folding instructions into constants. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric // Also, to supplement the basic IR ConstantExpr simplifications, 120b57cec5SDimitry Andric // this file defines some additional folding routines that can make use of 130b57cec5SDimitry Andric // DataLayout information. These functions cannot go in IR due to library 140b57cec5SDimitry Andric // dependency issues. 150b57cec5SDimitry Andric // 160b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric #include "llvm/Analysis/ConstantFolding.h" 190b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h" 200b57cec5SDimitry Andric #include "llvm/ADT/APInt.h" 21e8d8bef9SDimitry Andric #include "llvm/ADT/APSInt.h" 220b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 230b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 240b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 250b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 260b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 275ffd83dbSDimitry Andric #include "llvm/Analysis/TargetFolder.h" 280b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h" 290b57cec5SDimitry Andric #include "llvm/Analysis/ValueTracking.h" 300b57cec5SDimitry Andric #include "llvm/Analysis/VectorUtils.h" 310b57cec5SDimitry Andric #include "llvm/Config/config.h" 320b57cec5SDimitry Andric #include "llvm/IR/Constant.h" 33753f127fSDimitry Andric #include "llvm/IR/ConstantFold.h" 340b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 350b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 360b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 370b57cec5SDimitry Andric #include "llvm/IR/Function.h" 380b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h" 390b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h" 400b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h" 410b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 420b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 435ffd83dbSDimitry Andric #include "llvm/IR/IntrinsicInst.h" 44480093f4SDimitry Andric #include "llvm/IR/Intrinsics.h" 45fe6060f1SDimitry Andric #include "llvm/IR/IntrinsicsAArch64.h" 465ffd83dbSDimitry Andric #include "llvm/IR/IntrinsicsAMDGPU.h" 47e8d8bef9SDimitry Andric #include "llvm/IR/IntrinsicsARM.h" 48e8d8bef9SDimitry Andric #include "llvm/IR/IntrinsicsWebAssembly.h" 49480093f4SDimitry Andric #include "llvm/IR/IntrinsicsX86.h" 500b57cec5SDimitry Andric #include "llvm/IR/Operator.h" 510b57cec5SDimitry Andric #include "llvm/IR/Type.h" 520b57cec5SDimitry Andric #include "llvm/IR/Value.h" 530b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 540b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 550b57cec5SDimitry Andric #include "llvm/Support/KnownBits.h" 560b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 570b57cec5SDimitry Andric #include <cassert> 580b57cec5SDimitry Andric #include <cerrno> 590b57cec5SDimitry Andric #include <cfenv> 600b57cec5SDimitry Andric #include <cmath> 610b57cec5SDimitry Andric #include <cstdint> 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric using namespace llvm; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric namespace { 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 680b57cec5SDimitry Andric // Constant Folding internal helper functions 690b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric static Constant *foldConstVectorToAPInt(APInt &Result, Type *DestTy, 720b57cec5SDimitry Andric Constant *C, Type *SrcEltTy, 730b57cec5SDimitry Andric unsigned NumSrcElts, 740b57cec5SDimitry Andric const DataLayout &DL) { 750b57cec5SDimitry Andric // Now that we know that the input value is a vector of integers, just shift 760b57cec5SDimitry Andric // and insert them into our result. 770b57cec5SDimitry Andric unsigned BitShift = DL.getTypeSizeInBits(SrcEltTy); 780b57cec5SDimitry Andric for (unsigned i = 0; i != NumSrcElts; ++i) { 790b57cec5SDimitry Andric Constant *Element; 800b57cec5SDimitry Andric if (DL.isLittleEndian()) 810b57cec5SDimitry Andric Element = C->getAggregateElement(NumSrcElts - i - 1); 820b57cec5SDimitry Andric else 830b57cec5SDimitry Andric Element = C->getAggregateElement(i); 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric if (Element && isa<UndefValue>(Element)) { 860b57cec5SDimitry Andric Result <<= BitShift; 870b57cec5SDimitry Andric continue; 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric auto *ElementCI = dyn_cast_or_null<ConstantInt>(Element); 910b57cec5SDimitry Andric if (!ElementCI) 920b57cec5SDimitry Andric return ConstantExpr::getBitCast(C, DestTy); 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric Result <<= BitShift; 9581ad6265SDimitry Andric Result |= ElementCI->getValue().zext(Result.getBitWidth()); 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric return nullptr; 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric /// Constant fold bitcast, symbolically evaluating it with DataLayout. 1020b57cec5SDimitry Andric /// This always returns a non-null constant, but it may be a 1030b57cec5SDimitry Andric /// ConstantExpr if unfoldable. 1040b57cec5SDimitry Andric Constant *FoldBitCast(Constant *C, Type *DestTy, const DataLayout &DL) { 1058bcb0991SDimitry Andric assert(CastInst::castIsValid(Instruction::BitCast, C, DestTy) && 1068bcb0991SDimitry Andric "Invalid constantexpr bitcast!"); 1078bcb0991SDimitry Andric 1080b57cec5SDimitry Andric // Catch the obvious splat cases. 1090fca6ea1SDimitry Andric if (Constant *Res = ConstantFoldLoadFromUniformValue(C, DestTy, DL)) 11004eeddc0SDimitry Andric return Res; 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric if (auto *VTy = dyn_cast<VectorType>(C->getType())) { 1130b57cec5SDimitry Andric // Handle a vector->scalar integer/fp cast. 1140b57cec5SDimitry Andric if (isa<IntegerType>(DestTy) || DestTy->isFloatingPointTy()) { 115e8d8bef9SDimitry Andric unsigned NumSrcElts = cast<FixedVectorType>(VTy)->getNumElements(); 1160b57cec5SDimitry Andric Type *SrcEltTy = VTy->getElementType(); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric // If the vector is a vector of floating point, convert it to vector of int 1190b57cec5SDimitry Andric // to simplify things. 1200b57cec5SDimitry Andric if (SrcEltTy->isFloatingPointTy()) { 1210b57cec5SDimitry Andric unsigned FPWidth = SrcEltTy->getPrimitiveSizeInBits(); 1225ffd83dbSDimitry Andric auto *SrcIVTy = FixedVectorType::get( 1235ffd83dbSDimitry Andric IntegerType::get(C->getContext(), FPWidth), NumSrcElts); 1240b57cec5SDimitry Andric // Ask IR to do the conversion now that #elts line up. 1250b57cec5SDimitry Andric C = ConstantExpr::getBitCast(C, SrcIVTy); 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric APInt Result(DL.getTypeSizeInBits(DestTy), 0); 1290b57cec5SDimitry Andric if (Constant *CE = foldConstVectorToAPInt(Result, DestTy, C, 1300b57cec5SDimitry Andric SrcEltTy, NumSrcElts, DL)) 1310b57cec5SDimitry Andric return CE; 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric if (isa<IntegerType>(DestTy)) 1340b57cec5SDimitry Andric return ConstantInt::get(DestTy, Result); 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric APFloat FP(DestTy->getFltSemantics(), Result); 1370b57cec5SDimitry Andric return ConstantFP::get(DestTy->getContext(), FP); 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric // The code below only handles casts to vectors currently. 1420b57cec5SDimitry Andric auto *DestVTy = dyn_cast<VectorType>(DestTy); 1430b57cec5SDimitry Andric if (!DestVTy) 1440b57cec5SDimitry Andric return ConstantExpr::getBitCast(C, DestTy); 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric // If this is a scalar -> vector cast, convert the input into a <1 x scalar> 1470b57cec5SDimitry Andric // vector so the code below can handle it uniformly. 1480b57cec5SDimitry Andric if (isa<ConstantFP>(C) || isa<ConstantInt>(C)) { 1490b57cec5SDimitry Andric Constant *Ops = C; // don't take the address of C! 1500b57cec5SDimitry Andric return FoldBitCast(ConstantVector::get(Ops), DestTy, DL); 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric // If this is a bitcast from constant vector -> vector, fold it. 1540b57cec5SDimitry Andric if (!isa<ConstantDataVector>(C) && !isa<ConstantVector>(C)) 1550b57cec5SDimitry Andric return ConstantExpr::getBitCast(C, DestTy); 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric // If the element types match, IR can fold it. 158e8d8bef9SDimitry Andric unsigned NumDstElt = cast<FixedVectorType>(DestVTy)->getNumElements(); 159e8d8bef9SDimitry Andric unsigned NumSrcElt = cast<FixedVectorType>(C->getType())->getNumElements(); 1600b57cec5SDimitry Andric if (NumDstElt == NumSrcElt) 1610b57cec5SDimitry Andric return ConstantExpr::getBitCast(C, DestTy); 1620b57cec5SDimitry Andric 1635ffd83dbSDimitry Andric Type *SrcEltTy = cast<VectorType>(C->getType())->getElementType(); 1640b57cec5SDimitry Andric Type *DstEltTy = DestVTy->getElementType(); 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric // Otherwise, we're changing the number of elements in a vector, which 1670b57cec5SDimitry Andric // requires endianness information to do the right thing. For example, 1680b57cec5SDimitry Andric // bitcast (<2 x i64> <i64 0, i64 1> to <4 x i32>) 1690b57cec5SDimitry Andric // folds to (little endian): 1700b57cec5SDimitry Andric // <4 x i32> <i32 0, i32 0, i32 1, i32 0> 1710b57cec5SDimitry Andric // and to (big endian): 1720b57cec5SDimitry Andric // <4 x i32> <i32 0, i32 0, i32 0, i32 1> 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric // First thing is first. We only want to think about integer here, so if 1750b57cec5SDimitry Andric // we have something in FP form, recast it as integer. 1760b57cec5SDimitry Andric if (DstEltTy->isFloatingPointTy()) { 1770b57cec5SDimitry Andric // Fold to an vector of integers with same size as our FP type. 1780b57cec5SDimitry Andric unsigned FPWidth = DstEltTy->getPrimitiveSizeInBits(); 1795ffd83dbSDimitry Andric auto *DestIVTy = FixedVectorType::get( 1805ffd83dbSDimitry Andric IntegerType::get(C->getContext(), FPWidth), NumDstElt); 1810b57cec5SDimitry Andric // Recursively handle this integer conversion, if possible. 1820b57cec5SDimitry Andric C = FoldBitCast(C, DestIVTy, DL); 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric // Finally, IR can handle this now that #elts line up. 1850b57cec5SDimitry Andric return ConstantExpr::getBitCast(C, DestTy); 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric // Okay, we know the destination is integer, if the input is FP, convert 1890b57cec5SDimitry Andric // it to integer first. 1900b57cec5SDimitry Andric if (SrcEltTy->isFloatingPointTy()) { 1910b57cec5SDimitry Andric unsigned FPWidth = SrcEltTy->getPrimitiveSizeInBits(); 1925ffd83dbSDimitry Andric auto *SrcIVTy = FixedVectorType::get( 1935ffd83dbSDimitry Andric IntegerType::get(C->getContext(), FPWidth), NumSrcElt); 1940b57cec5SDimitry Andric // Ask IR to do the conversion now that #elts line up. 1950b57cec5SDimitry Andric C = ConstantExpr::getBitCast(C, SrcIVTy); 1960b57cec5SDimitry Andric // If IR wasn't able to fold it, bail out. 1970b57cec5SDimitry Andric if (!isa<ConstantVector>(C) && // FIXME: Remove ConstantVector. 1980b57cec5SDimitry Andric !isa<ConstantDataVector>(C)) 1990b57cec5SDimitry Andric return C; 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric // Now we know that the input and output vectors are both integer vectors 2030b57cec5SDimitry Andric // of the same size, and that their #elements is not the same. Do the 2040b57cec5SDimitry Andric // conversion here, which depends on whether the input or output has 2050b57cec5SDimitry Andric // more elements. 2060b57cec5SDimitry Andric bool isLittleEndian = DL.isLittleEndian(); 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric SmallVector<Constant*, 32> Result; 2090b57cec5SDimitry Andric if (NumDstElt < NumSrcElt) { 2100b57cec5SDimitry Andric // Handle: bitcast (<4 x i32> <i32 0, i32 1, i32 2, i32 3> to <2 x i64>) 2110b57cec5SDimitry Andric Constant *Zero = Constant::getNullValue(DstEltTy); 2120b57cec5SDimitry Andric unsigned Ratio = NumSrcElt/NumDstElt; 2130b57cec5SDimitry Andric unsigned SrcBitSize = SrcEltTy->getPrimitiveSizeInBits(); 2140b57cec5SDimitry Andric unsigned SrcElt = 0; 2150b57cec5SDimitry Andric for (unsigned i = 0; i != NumDstElt; ++i) { 2160b57cec5SDimitry Andric // Build each element of the result. 2170b57cec5SDimitry Andric Constant *Elt = Zero; 2180b57cec5SDimitry Andric unsigned ShiftAmt = isLittleEndian ? 0 : SrcBitSize*(Ratio-1); 2190b57cec5SDimitry Andric for (unsigned j = 0; j != Ratio; ++j) { 2200b57cec5SDimitry Andric Constant *Src = C->getAggregateElement(SrcElt++); 2210b57cec5SDimitry Andric if (Src && isa<UndefValue>(Src)) 2225ffd83dbSDimitry Andric Src = Constant::getNullValue( 2235ffd83dbSDimitry Andric cast<VectorType>(C->getType())->getElementType()); 2240b57cec5SDimitry Andric else 2250b57cec5SDimitry Andric Src = dyn_cast_or_null<ConstantInt>(Src); 2260b57cec5SDimitry Andric if (!Src) // Reject constantexpr elements. 2270b57cec5SDimitry Andric return ConstantExpr::getBitCast(C, DestTy); 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric // Zero extend the element to the right size. 2305f757f3fSDimitry Andric Src = ConstantFoldCastOperand(Instruction::ZExt, Src, Elt->getType(), 2315f757f3fSDimitry Andric DL); 2325f757f3fSDimitry Andric assert(Src && "Constant folding cannot fail on plain integers"); 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric // Shift it to the right place, depending on endianness. 2355f757f3fSDimitry Andric Src = ConstantFoldBinaryOpOperands( 2365f757f3fSDimitry Andric Instruction::Shl, Src, ConstantInt::get(Src->getType(), ShiftAmt), 2375f757f3fSDimitry Andric DL); 2385f757f3fSDimitry Andric assert(Src && "Constant folding cannot fail on plain integers"); 2395f757f3fSDimitry Andric 2400b57cec5SDimitry Andric ShiftAmt += isLittleEndian ? SrcBitSize : -SrcBitSize; 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric // Mix it in. 24306c3fb27SDimitry Andric Elt = ConstantFoldBinaryOpOperands(Instruction::Or, Elt, Src, DL); 24406c3fb27SDimitry Andric assert(Elt && "Constant folding cannot fail on plain integers"); 2450b57cec5SDimitry Andric } 2460b57cec5SDimitry Andric Result.push_back(Elt); 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric return ConstantVector::get(Result); 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric // Handle: bitcast (<2 x i64> <i64 0, i64 1> to <4 x i32>) 2520b57cec5SDimitry Andric unsigned Ratio = NumDstElt/NumSrcElt; 2530b57cec5SDimitry Andric unsigned DstBitSize = DL.getTypeSizeInBits(DstEltTy); 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric // Loop over each source value, expanding into multiple results. 2560b57cec5SDimitry Andric for (unsigned i = 0; i != NumSrcElt; ++i) { 2570b57cec5SDimitry Andric auto *Element = C->getAggregateElement(i); 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric if (!Element) // Reject constantexpr elements. 2600b57cec5SDimitry Andric return ConstantExpr::getBitCast(C, DestTy); 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric if (isa<UndefValue>(Element)) { 2630b57cec5SDimitry Andric // Correctly Propagate undef values. 2640b57cec5SDimitry Andric Result.append(Ratio, UndefValue::get(DstEltTy)); 2650b57cec5SDimitry Andric continue; 2660b57cec5SDimitry Andric } 2670b57cec5SDimitry Andric 2680b57cec5SDimitry Andric auto *Src = dyn_cast<ConstantInt>(Element); 2690b57cec5SDimitry Andric if (!Src) 2700b57cec5SDimitry Andric return ConstantExpr::getBitCast(C, DestTy); 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric unsigned ShiftAmt = isLittleEndian ? 0 : DstBitSize*(Ratio-1); 2730b57cec5SDimitry Andric for (unsigned j = 0; j != Ratio; ++j) { 2740b57cec5SDimitry Andric // Shift the piece of the value into the right place, depending on 2750b57cec5SDimitry Andric // endianness. 2765f757f3fSDimitry Andric APInt Elt = Src->getValue().lshr(ShiftAmt); 2770b57cec5SDimitry Andric ShiftAmt += isLittleEndian ? DstBitSize : -DstBitSize; 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric // Truncate and remember this piece. 2805f757f3fSDimitry Andric Result.push_back(ConstantInt::get(DstEltTy, Elt.trunc(DstBitSize))); 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric return ConstantVector::get(Result); 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric } // end anonymous namespace 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric /// If this constant is a constant offset from a global, return the global and 2900b57cec5SDimitry Andric /// the constant. Because of constantexprs, this function is recursive. 2910b57cec5SDimitry Andric bool llvm::IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV, 292e8d8bef9SDimitry Andric APInt &Offset, const DataLayout &DL, 293e8d8bef9SDimitry Andric DSOLocalEquivalent **DSOEquiv) { 294e8d8bef9SDimitry Andric if (DSOEquiv) 295e8d8bef9SDimitry Andric *DSOEquiv = nullptr; 296e8d8bef9SDimitry Andric 2970b57cec5SDimitry Andric // Trivial case, constant is the global. 2980b57cec5SDimitry Andric if ((GV = dyn_cast<GlobalValue>(C))) { 2990b57cec5SDimitry Andric unsigned BitWidth = DL.getIndexTypeSizeInBits(GV->getType()); 3000b57cec5SDimitry Andric Offset = APInt(BitWidth, 0); 3010b57cec5SDimitry Andric return true; 3020b57cec5SDimitry Andric } 3030b57cec5SDimitry Andric 304e8d8bef9SDimitry Andric if (auto *FoundDSOEquiv = dyn_cast<DSOLocalEquivalent>(C)) { 305e8d8bef9SDimitry Andric if (DSOEquiv) 306e8d8bef9SDimitry Andric *DSOEquiv = FoundDSOEquiv; 307e8d8bef9SDimitry Andric GV = FoundDSOEquiv->getGlobalValue(); 308e8d8bef9SDimitry Andric unsigned BitWidth = DL.getIndexTypeSizeInBits(GV->getType()); 309e8d8bef9SDimitry Andric Offset = APInt(BitWidth, 0); 310e8d8bef9SDimitry Andric return true; 311e8d8bef9SDimitry Andric } 312e8d8bef9SDimitry Andric 3130b57cec5SDimitry Andric // Otherwise, if this isn't a constant expr, bail out. 3140b57cec5SDimitry Andric auto *CE = dyn_cast<ConstantExpr>(C); 3150b57cec5SDimitry Andric if (!CE) return false; 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric // Look through ptr->int and ptr->ptr casts. 3180b57cec5SDimitry Andric if (CE->getOpcode() == Instruction::PtrToInt || 3190b57cec5SDimitry Andric CE->getOpcode() == Instruction::BitCast) 320e8d8bef9SDimitry Andric return IsConstantOffsetFromGlobal(CE->getOperand(0), GV, Offset, DL, 321e8d8bef9SDimitry Andric DSOEquiv); 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric // i32* getelementptr ([5 x i32]* @a, i32 0, i32 5) 3240b57cec5SDimitry Andric auto *GEP = dyn_cast<GEPOperator>(CE); 3250b57cec5SDimitry Andric if (!GEP) 3260b57cec5SDimitry Andric return false; 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric unsigned BitWidth = DL.getIndexTypeSizeInBits(GEP->getType()); 3290b57cec5SDimitry Andric APInt TmpOffset(BitWidth, 0); 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric // If the base isn't a global+constant, we aren't either. 332e8d8bef9SDimitry Andric if (!IsConstantOffsetFromGlobal(CE->getOperand(0), GV, TmpOffset, DL, 333e8d8bef9SDimitry Andric DSOEquiv)) 3340b57cec5SDimitry Andric return false; 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric // Otherwise, add any offset that our operands provide. 3370b57cec5SDimitry Andric if (!GEP->accumulateConstantOffset(DL, TmpOffset)) 3380b57cec5SDimitry Andric return false; 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric Offset = TmpOffset; 3410b57cec5SDimitry Andric return true; 3420b57cec5SDimitry Andric } 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric Constant *llvm::ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy, 3450b57cec5SDimitry Andric const DataLayout &DL) { 3460b57cec5SDimitry Andric do { 3470b57cec5SDimitry Andric Type *SrcTy = C->getType(); 3480eae32dcSDimitry Andric if (SrcTy == DestTy) 3490eae32dcSDimitry Andric return C; 3500eae32dcSDimitry Andric 351349cc55cSDimitry Andric TypeSize DestSize = DL.getTypeSizeInBits(DestTy); 352349cc55cSDimitry Andric TypeSize SrcSize = DL.getTypeSizeInBits(SrcTy); 353349cc55cSDimitry Andric if (!TypeSize::isKnownGE(SrcSize, DestSize)) 3545ffd83dbSDimitry Andric return nullptr; 3555ffd83dbSDimitry Andric 3565ffd83dbSDimitry Andric // Catch the obvious splat cases (since all-zeros can coerce non-integral 3575ffd83dbSDimitry Andric // pointers legally). 3580fca6ea1SDimitry Andric if (Constant *Res = ConstantFoldLoadFromUniformValue(C, DestTy, DL)) 35904eeddc0SDimitry Andric return Res; 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric // If the type sizes are the same and a cast is legal, just directly 3620b57cec5SDimitry Andric // cast the constant. 3635ffd83dbSDimitry Andric // But be careful not to coerce non-integral pointers illegally. 3645ffd83dbSDimitry Andric if (SrcSize == DestSize && 3655ffd83dbSDimitry Andric DL.isNonIntegralPointerType(SrcTy->getScalarType()) == 3665ffd83dbSDimitry Andric DL.isNonIntegralPointerType(DestTy->getScalarType())) { 3670b57cec5SDimitry Andric Instruction::CastOps Cast = Instruction::BitCast; 3680b57cec5SDimitry Andric // If we are going from a pointer to int or vice versa, we spell the cast 3690b57cec5SDimitry Andric // differently. 3700b57cec5SDimitry Andric if (SrcTy->isIntegerTy() && DestTy->isPointerTy()) 3710b57cec5SDimitry Andric Cast = Instruction::IntToPtr; 3720b57cec5SDimitry Andric else if (SrcTy->isPointerTy() && DestTy->isIntegerTy()) 3730b57cec5SDimitry Andric Cast = Instruction::PtrToInt; 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric if (CastInst::castIsValid(Cast, C, DestTy)) 3765f757f3fSDimitry Andric return ConstantFoldCastOperand(Cast, C, DestTy, DL); 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric // If this isn't an aggregate type, there is nothing we can do to drill down 3800b57cec5SDimitry Andric // and find a bitcastable constant. 381fe6060f1SDimitry Andric if (!SrcTy->isAggregateType() && !SrcTy->isVectorTy()) 3820b57cec5SDimitry Andric return nullptr; 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric // We're simulating a load through a pointer that was bitcast to point to 3850b57cec5SDimitry Andric // a different type, so we can try to walk down through the initial 3860b57cec5SDimitry Andric // elements of an aggregate to see if some part of the aggregate is 3870b57cec5SDimitry Andric // castable to implement the "load" semantic model. 3880b57cec5SDimitry Andric if (SrcTy->isStructTy()) { 3890b57cec5SDimitry Andric // Struct types might have leading zero-length elements like [0 x i32], 3900b57cec5SDimitry Andric // which are certainly not what we are looking for, so skip them. 3910b57cec5SDimitry Andric unsigned Elem = 0; 3920b57cec5SDimitry Andric Constant *ElemC; 3930b57cec5SDimitry Andric do { 3940b57cec5SDimitry Andric ElemC = C->getAggregateElement(Elem++); 3955ffd83dbSDimitry Andric } while (ElemC && DL.getTypeSizeInBits(ElemC->getType()).isZero()); 3960b57cec5SDimitry Andric C = ElemC; 3970b57cec5SDimitry Andric } else { 39804eeddc0SDimitry Andric // For non-byte-sized vector elements, the first element is not 39904eeddc0SDimitry Andric // necessarily located at the vector base address. 40004eeddc0SDimitry Andric if (auto *VT = dyn_cast<VectorType>(SrcTy)) 40104eeddc0SDimitry Andric if (!DL.typeSizeEqualsStoreSize(VT->getElementType())) 40204eeddc0SDimitry Andric return nullptr; 40304eeddc0SDimitry Andric 4040b57cec5SDimitry Andric C = C->getAggregateElement(0u); 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric } while (C); 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric return nullptr; 4090b57cec5SDimitry Andric } 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric namespace { 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric /// Recursive helper to read bits out of global. C is the constant being copied 4140b57cec5SDimitry Andric /// out of. ByteOffset is an offset into C. CurPtr is the pointer to copy 4150b57cec5SDimitry Andric /// results into and BytesLeft is the number of bytes left in 4160b57cec5SDimitry Andric /// the CurPtr buffer. DL is the DataLayout. 4170b57cec5SDimitry Andric bool ReadDataFromGlobal(Constant *C, uint64_t ByteOffset, unsigned char *CurPtr, 4180b57cec5SDimitry Andric unsigned BytesLeft, const DataLayout &DL) { 4190b57cec5SDimitry Andric assert(ByteOffset <= DL.getTypeAllocSize(C->getType()) && 4200b57cec5SDimitry Andric "Out of range access"); 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric // If this element is zero or undefined, we can just return since *CurPtr is 4230b57cec5SDimitry Andric // zero initialized. 4240b57cec5SDimitry Andric if (isa<ConstantAggregateZero>(C) || isa<UndefValue>(C)) 4250b57cec5SDimitry Andric return true; 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric if (auto *CI = dyn_cast<ConstantInt>(C)) { 42806c3fb27SDimitry Andric if ((CI->getBitWidth() & 7) != 0) 4290b57cec5SDimitry Andric return false; 43006c3fb27SDimitry Andric const APInt &Val = CI->getValue(); 4310b57cec5SDimitry Andric unsigned IntBytes = unsigned(CI->getBitWidth()/8); 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric for (unsigned i = 0; i != BytesLeft && ByteOffset != IntBytes; ++i) { 43406c3fb27SDimitry Andric unsigned n = ByteOffset; 4350b57cec5SDimitry Andric if (!DL.isLittleEndian()) 4360b57cec5SDimitry Andric n = IntBytes - n - 1; 43706c3fb27SDimitry Andric CurPtr[i] = Val.extractBits(8, n * 8).getZExtValue(); 4380b57cec5SDimitry Andric ++ByteOffset; 4390b57cec5SDimitry Andric } 4400b57cec5SDimitry Andric return true; 4410b57cec5SDimitry Andric } 4420b57cec5SDimitry Andric 4430b57cec5SDimitry Andric if (auto *CFP = dyn_cast<ConstantFP>(C)) { 4440b57cec5SDimitry Andric if (CFP->getType()->isDoubleTy()) { 4450b57cec5SDimitry Andric C = FoldBitCast(C, Type::getInt64Ty(C->getContext()), DL); 4460b57cec5SDimitry Andric return ReadDataFromGlobal(C, ByteOffset, CurPtr, BytesLeft, DL); 4470b57cec5SDimitry Andric } 4480b57cec5SDimitry Andric if (CFP->getType()->isFloatTy()){ 4490b57cec5SDimitry Andric C = FoldBitCast(C, Type::getInt32Ty(C->getContext()), DL); 4500b57cec5SDimitry Andric return ReadDataFromGlobal(C, ByteOffset, CurPtr, BytesLeft, DL); 4510b57cec5SDimitry Andric } 4520b57cec5SDimitry Andric if (CFP->getType()->isHalfTy()){ 4530b57cec5SDimitry Andric C = FoldBitCast(C, Type::getInt16Ty(C->getContext()), DL); 4540b57cec5SDimitry Andric return ReadDataFromGlobal(C, ByteOffset, CurPtr, BytesLeft, DL); 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric return false; 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric if (auto *CS = dyn_cast<ConstantStruct>(C)) { 4600b57cec5SDimitry Andric const StructLayout *SL = DL.getStructLayout(CS->getType()); 4610b57cec5SDimitry Andric unsigned Index = SL->getElementContainingOffset(ByteOffset); 4620b57cec5SDimitry Andric uint64_t CurEltOffset = SL->getElementOffset(Index); 4630b57cec5SDimitry Andric ByteOffset -= CurEltOffset; 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric while (true) { 4660b57cec5SDimitry Andric // If the element access is to the element itself and not to tail padding, 4670b57cec5SDimitry Andric // read the bytes from the element. 4680b57cec5SDimitry Andric uint64_t EltSize = DL.getTypeAllocSize(CS->getOperand(Index)->getType()); 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andric if (ByteOffset < EltSize && 4710b57cec5SDimitry Andric !ReadDataFromGlobal(CS->getOperand(Index), ByteOffset, CurPtr, 4720b57cec5SDimitry Andric BytesLeft, DL)) 4730b57cec5SDimitry Andric return false; 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric ++Index; 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric // Check to see if we read from the last struct element, if so we're done. 4780b57cec5SDimitry Andric if (Index == CS->getType()->getNumElements()) 4790b57cec5SDimitry Andric return true; 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric // If we read all of the bytes we needed from this element we're done. 4820b57cec5SDimitry Andric uint64_t NextEltOffset = SL->getElementOffset(Index); 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric if (BytesLeft <= NextEltOffset - CurEltOffset - ByteOffset) 4850b57cec5SDimitry Andric return true; 4860b57cec5SDimitry Andric 4870b57cec5SDimitry Andric // Move to the next element of the struct. 4880b57cec5SDimitry Andric CurPtr += NextEltOffset - CurEltOffset - ByteOffset; 4890b57cec5SDimitry Andric BytesLeft -= NextEltOffset - CurEltOffset - ByteOffset; 4900b57cec5SDimitry Andric ByteOffset = 0; 4910b57cec5SDimitry Andric CurEltOffset = NextEltOffset; 4920b57cec5SDimitry Andric } 4930b57cec5SDimitry Andric // not reached. 4940b57cec5SDimitry Andric } 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric if (isa<ConstantArray>(C) || isa<ConstantVector>(C) || 4970b57cec5SDimitry Andric isa<ConstantDataSequential>(C)) { 49806c3fb27SDimitry Andric uint64_t NumElts, EltSize; 4995ffd83dbSDimitry Andric Type *EltTy; 5005ffd83dbSDimitry Andric if (auto *AT = dyn_cast<ArrayType>(C->getType())) { 5015ffd83dbSDimitry Andric NumElts = AT->getNumElements(); 5025ffd83dbSDimitry Andric EltTy = AT->getElementType(); 50306c3fb27SDimitry Andric EltSize = DL.getTypeAllocSize(EltTy); 5045ffd83dbSDimitry Andric } else { 505e8d8bef9SDimitry Andric NumElts = cast<FixedVectorType>(C->getType())->getNumElements(); 506e8d8bef9SDimitry Andric EltTy = cast<FixedVectorType>(C->getType())->getElementType(); 50706c3fb27SDimitry Andric // TODO: For non-byte-sized vectors, current implementation assumes there is 50806c3fb27SDimitry Andric // padding to the next byte boundary between elements. 50906c3fb27SDimitry Andric if (!DL.typeSizeEqualsStoreSize(EltTy)) 51006c3fb27SDimitry Andric return false; 51106c3fb27SDimitry Andric 51206c3fb27SDimitry Andric EltSize = DL.getTypeStoreSize(EltTy); 5135ffd83dbSDimitry Andric } 5140b57cec5SDimitry Andric uint64_t Index = ByteOffset / EltSize; 5150b57cec5SDimitry Andric uint64_t Offset = ByteOffset - Index * EltSize; 5160b57cec5SDimitry Andric 5170b57cec5SDimitry Andric for (; Index != NumElts; ++Index) { 5180b57cec5SDimitry Andric if (!ReadDataFromGlobal(C->getAggregateElement(Index), Offset, CurPtr, 5190b57cec5SDimitry Andric BytesLeft, DL)) 5200b57cec5SDimitry Andric return false; 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric uint64_t BytesWritten = EltSize - Offset; 5230b57cec5SDimitry Andric assert(BytesWritten <= EltSize && "Not indexing into this element?"); 5240b57cec5SDimitry Andric if (BytesWritten >= BytesLeft) 5250b57cec5SDimitry Andric return true; 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric Offset = 0; 5280b57cec5SDimitry Andric BytesLeft -= BytesWritten; 5290b57cec5SDimitry Andric CurPtr += BytesWritten; 5300b57cec5SDimitry Andric } 5310b57cec5SDimitry Andric return true; 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric if (auto *CE = dyn_cast<ConstantExpr>(C)) { 5350b57cec5SDimitry Andric if (CE->getOpcode() == Instruction::IntToPtr && 5360b57cec5SDimitry Andric CE->getOperand(0)->getType() == DL.getIntPtrType(CE->getType())) { 5370b57cec5SDimitry Andric return ReadDataFromGlobal(CE->getOperand(0), ByteOffset, CurPtr, 5380b57cec5SDimitry Andric BytesLeft, DL); 5390b57cec5SDimitry Andric } 5400b57cec5SDimitry Andric } 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric // Otherwise, unknown initializer type. 5430b57cec5SDimitry Andric return false; 5440b57cec5SDimitry Andric } 5450b57cec5SDimitry Andric 546349cc55cSDimitry Andric Constant *FoldReinterpretLoadFromConst(Constant *C, Type *LoadTy, 547349cc55cSDimitry Andric int64_t Offset, const DataLayout &DL) { 5485ffd83dbSDimitry Andric // Bail out early. Not expect to load from scalable global variable. 5495ffd83dbSDimitry Andric if (isa<ScalableVectorType>(LoadTy)) 5505ffd83dbSDimitry Andric return nullptr; 5515ffd83dbSDimitry Andric 5520b57cec5SDimitry Andric auto *IntType = dyn_cast<IntegerType>(LoadTy); 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric // If this isn't an integer load we can't fold it directly. 5550b57cec5SDimitry Andric if (!IntType) { 55604eeddc0SDimitry Andric // If this is a non-integer load, we can try folding it as an int load and 55704eeddc0SDimitry Andric // then bitcast the result. This can be useful for union cases. Note 5580b57cec5SDimitry Andric // that address spaces don't matter here since we're not going to result in 5590b57cec5SDimitry Andric // an actual new load. 56004eeddc0SDimitry Andric if (!LoadTy->isFloatingPointTy() && !LoadTy->isPointerTy() && 56104eeddc0SDimitry Andric !LoadTy->isVectorTy()) 5620b57cec5SDimitry Andric return nullptr; 5630b57cec5SDimitry Andric 564bdd1243dSDimitry Andric Type *MapTy = Type::getIntNTy(C->getContext(), 565bdd1243dSDimitry Andric DL.getTypeSizeInBits(LoadTy).getFixedValue()); 566349cc55cSDimitry Andric if (Constant *Res = FoldReinterpretLoadFromConst(C, MapTy, Offset, DL)) { 567e8d8bef9SDimitry Andric if (Res->isNullValue() && !LoadTy->isX86_MMXTy() && 568e8d8bef9SDimitry Andric !LoadTy->isX86_AMXTy()) 5698bcb0991SDimitry Andric // Materializing a zero can be done trivially without a bitcast 5708bcb0991SDimitry Andric return Constant::getNullValue(LoadTy); 5718bcb0991SDimitry Andric Type *CastTy = LoadTy->isPtrOrPtrVectorTy() ? DL.getIntPtrType(LoadTy) : LoadTy; 5728bcb0991SDimitry Andric Res = FoldBitCast(Res, CastTy, DL); 5738bcb0991SDimitry Andric if (LoadTy->isPtrOrPtrVectorTy()) { 5748bcb0991SDimitry Andric // For vector of pointer, we needed to first convert to a vector of integer, then do vector inttoptr 575e8d8bef9SDimitry Andric if (Res->isNullValue() && !LoadTy->isX86_MMXTy() && 576e8d8bef9SDimitry Andric !LoadTy->isX86_AMXTy()) 5778bcb0991SDimitry Andric return Constant::getNullValue(LoadTy); 5788bcb0991SDimitry Andric if (DL.isNonIntegralPointerType(LoadTy->getScalarType())) 5798bcb0991SDimitry Andric // Be careful not to replace a load of an addrspace value with an inttoptr here 5808bcb0991SDimitry Andric return nullptr; 5815f757f3fSDimitry Andric Res = ConstantExpr::getIntToPtr(Res, LoadTy); 5828bcb0991SDimitry Andric } 5838bcb0991SDimitry Andric return Res; 5848bcb0991SDimitry Andric } 5850b57cec5SDimitry Andric return nullptr; 5860b57cec5SDimitry Andric } 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric unsigned BytesLoaded = (IntType->getBitWidth() + 7) / 8; 5890b57cec5SDimitry Andric if (BytesLoaded > 32 || BytesLoaded == 0) 5900b57cec5SDimitry Andric return nullptr; 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric // If we're not accessing anything in this constant, the result is undefined. 5938bcb0991SDimitry Andric if (Offset <= -1 * static_cast<int64_t>(BytesLoaded)) 594bdd1243dSDimitry Andric return PoisonValue::get(IntType); 5950b57cec5SDimitry Andric 596d781ede6SDimitry Andric // TODO: We should be able to support scalable types. 597d781ede6SDimitry Andric TypeSize InitializerSize = DL.getTypeAllocSize(C->getType()); 598d781ede6SDimitry Andric if (InitializerSize.isScalable()) 599d781ede6SDimitry Andric return nullptr; 600d781ede6SDimitry Andric 6010b57cec5SDimitry Andric // If we're not accessing anything in this constant, the result is undefined. 602d781ede6SDimitry Andric if (Offset >= (int64_t)InitializerSize.getFixedValue()) 603bdd1243dSDimitry Andric return PoisonValue::get(IntType); 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric unsigned char RawBytes[32] = {0}; 6060b57cec5SDimitry Andric unsigned char *CurPtr = RawBytes; 6070b57cec5SDimitry Andric unsigned BytesLeft = BytesLoaded; 6080b57cec5SDimitry Andric 6090b57cec5SDimitry Andric // If we're loading off the beginning of the global, some bytes may be valid. 6100b57cec5SDimitry Andric if (Offset < 0) { 6110b57cec5SDimitry Andric CurPtr += -Offset; 6120b57cec5SDimitry Andric BytesLeft += Offset; 6130b57cec5SDimitry Andric Offset = 0; 6140b57cec5SDimitry Andric } 6150b57cec5SDimitry Andric 616349cc55cSDimitry Andric if (!ReadDataFromGlobal(C, Offset, CurPtr, BytesLeft, DL)) 6170b57cec5SDimitry Andric return nullptr; 6180b57cec5SDimitry Andric 6190b57cec5SDimitry Andric APInt ResultVal = APInt(IntType->getBitWidth(), 0); 6200b57cec5SDimitry Andric if (DL.isLittleEndian()) { 6210b57cec5SDimitry Andric ResultVal = RawBytes[BytesLoaded - 1]; 6220b57cec5SDimitry Andric for (unsigned i = 1; i != BytesLoaded; ++i) { 6230b57cec5SDimitry Andric ResultVal <<= 8; 6240b57cec5SDimitry Andric ResultVal |= RawBytes[BytesLoaded - 1 - i]; 6250b57cec5SDimitry Andric } 6260b57cec5SDimitry Andric } else { 6270b57cec5SDimitry Andric ResultVal = RawBytes[0]; 6280b57cec5SDimitry Andric for (unsigned i = 1; i != BytesLoaded; ++i) { 6290b57cec5SDimitry Andric ResultVal <<= 8; 6300b57cec5SDimitry Andric ResultVal |= RawBytes[i]; 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric } 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric return ConstantInt::get(IntType->getContext(), ResultVal); 6350b57cec5SDimitry Andric } 6360b57cec5SDimitry Andric 63781ad6265SDimitry Andric } // anonymous namespace 63881ad6265SDimitry Andric 63981ad6265SDimitry Andric // If GV is a constant with an initializer read its representation starting 64081ad6265SDimitry Andric // at Offset and return it as a constant array of unsigned char. Otherwise 64181ad6265SDimitry Andric // return null. 64281ad6265SDimitry Andric Constant *llvm::ReadByteArrayFromGlobal(const GlobalVariable *GV, 64381ad6265SDimitry Andric uint64_t Offset) { 64481ad6265SDimitry Andric if (!GV->isConstant() || !GV->hasDefinitiveInitializer()) 64581ad6265SDimitry Andric return nullptr; 64681ad6265SDimitry Andric 6470fca6ea1SDimitry Andric const DataLayout &DL = GV->getDataLayout(); 64881ad6265SDimitry Andric Constant *Init = const_cast<Constant *>(GV->getInitializer()); 64981ad6265SDimitry Andric TypeSize InitSize = DL.getTypeAllocSize(Init->getType()); 65081ad6265SDimitry Andric if (InitSize < Offset) 65181ad6265SDimitry Andric return nullptr; 65281ad6265SDimitry Andric 65381ad6265SDimitry Andric uint64_t NBytes = InitSize - Offset; 65481ad6265SDimitry Andric if (NBytes > UINT16_MAX) 65581ad6265SDimitry Andric // Bail for large initializers in excess of 64K to avoid allocating 65681ad6265SDimitry Andric // too much memory. 65781ad6265SDimitry Andric // Offset is assumed to be less than or equal than InitSize (this 65881ad6265SDimitry Andric // is enforced in ReadDataFromGlobal). 65981ad6265SDimitry Andric return nullptr; 66081ad6265SDimitry Andric 66181ad6265SDimitry Andric SmallVector<unsigned char, 256> RawBytes(static_cast<size_t>(NBytes)); 66281ad6265SDimitry Andric unsigned char *CurPtr = RawBytes.data(); 66381ad6265SDimitry Andric 66481ad6265SDimitry Andric if (!ReadDataFromGlobal(Init, Offset, CurPtr, NBytes, DL)) 66581ad6265SDimitry Andric return nullptr; 66681ad6265SDimitry Andric 66781ad6265SDimitry Andric return ConstantDataArray::get(GV->getContext(), RawBytes); 66881ad6265SDimitry Andric } 66981ad6265SDimitry Andric 670349cc55cSDimitry Andric /// If this Offset points exactly to the start of an aggregate element, return 671349cc55cSDimitry Andric /// that element, otherwise return nullptr. 672349cc55cSDimitry Andric Constant *getConstantAtOffset(Constant *Base, APInt Offset, 6730b57cec5SDimitry Andric const DataLayout &DL) { 674349cc55cSDimitry Andric if (Offset.isZero()) 675349cc55cSDimitry Andric return Base; 676349cc55cSDimitry Andric 677349cc55cSDimitry Andric if (!isa<ConstantAggregate>(Base) && !isa<ConstantDataSequential>(Base)) 6780b57cec5SDimitry Andric return nullptr; 6790b57cec5SDimitry Andric 680349cc55cSDimitry Andric Type *ElemTy = Base->getType(); 681349cc55cSDimitry Andric SmallVector<APInt> Indices = DL.getGEPIndicesForOffset(ElemTy, Offset); 682349cc55cSDimitry Andric if (!Offset.isZero() || !Indices[0].isZero()) 683349cc55cSDimitry Andric return nullptr; 684349cc55cSDimitry Andric 685349cc55cSDimitry Andric Constant *C = Base; 686349cc55cSDimitry Andric for (const APInt &Index : drop_begin(Indices)) { 687349cc55cSDimitry Andric if (Index.isNegative() || Index.getActiveBits() >= 32) 688349cc55cSDimitry Andric return nullptr; 689349cc55cSDimitry Andric 690349cc55cSDimitry Andric C = C->getAggregateElement(Index.getZExtValue()); 691349cc55cSDimitry Andric if (!C) 692349cc55cSDimitry Andric return nullptr; 693349cc55cSDimitry Andric } 694349cc55cSDimitry Andric 695349cc55cSDimitry Andric return C; 6960b57cec5SDimitry Andric } 6970b57cec5SDimitry Andric 698349cc55cSDimitry Andric Constant *llvm::ConstantFoldLoadFromConst(Constant *C, Type *Ty, 699349cc55cSDimitry Andric const APInt &Offset, 7000b57cec5SDimitry Andric const DataLayout &DL) { 701349cc55cSDimitry Andric if (Constant *AtOffset = getConstantAtOffset(C, Offset, DL)) 702349cc55cSDimitry Andric if (Constant *Result = ConstantFoldLoadThroughBitcast(AtOffset, Ty, DL)) 703349cc55cSDimitry Andric return Result; 704349cc55cSDimitry Andric 705bdd1243dSDimitry Andric // Explicitly check for out-of-bounds access, so we return poison even if the 70604eeddc0SDimitry Andric // constant is a uniform value. 70704eeddc0SDimitry Andric TypeSize Size = DL.getTypeAllocSize(C->getType()); 708bdd1243dSDimitry Andric if (!Size.isScalable() && Offset.sge(Size.getFixedValue())) 709bdd1243dSDimitry Andric return PoisonValue::get(Ty); 71004eeddc0SDimitry Andric 71104eeddc0SDimitry Andric // Try an offset-independent fold of a uniform value. 7120fca6ea1SDimitry Andric if (Constant *Result = ConstantFoldLoadFromUniformValue(C, Ty, DL)) 71304eeddc0SDimitry Andric return Result; 71404eeddc0SDimitry Andric 715349cc55cSDimitry Andric // Try hard to fold loads from bitcasted strange and non-type-safe things. 71606c3fb27SDimitry Andric if (Offset.getSignificantBits() <= 64) 71704eeddc0SDimitry Andric if (Constant *Result = 71804eeddc0SDimitry Andric FoldReinterpretLoadFromConst(C, Ty, Offset.getSExtValue(), DL)) 71904eeddc0SDimitry Andric return Result; 720349cc55cSDimitry Andric 721349cc55cSDimitry Andric return nullptr; 722349cc55cSDimitry Andric } 723349cc55cSDimitry Andric 724349cc55cSDimitry Andric Constant *llvm::ConstantFoldLoadFromConst(Constant *C, Type *Ty, 725349cc55cSDimitry Andric const DataLayout &DL) { 726349cc55cSDimitry Andric return ConstantFoldLoadFromConst(C, Ty, APInt(64, 0), DL); 727349cc55cSDimitry Andric } 728349cc55cSDimitry Andric 729349cc55cSDimitry Andric Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, 730349cc55cSDimitry Andric APInt Offset, 731349cc55cSDimitry Andric const DataLayout &DL) { 73206c3fb27SDimitry Andric // We can only fold loads from constant globals with a definitive initializer. 73306c3fb27SDimitry Andric // Check this upfront, to skip expensive offset calculations. 73406c3fb27SDimitry Andric auto *GV = dyn_cast<GlobalVariable>(getUnderlyingObject(C)); 73506c3fb27SDimitry Andric if (!GV || !GV->isConstant() || !GV->hasDefinitiveInitializer()) 73606c3fb27SDimitry Andric return nullptr; 73706c3fb27SDimitry Andric 738349cc55cSDimitry Andric C = cast<Constant>(C->stripAndAccumulateConstantOffsets( 739349cc55cSDimitry Andric DL, Offset, /* AllowNonInbounds */ true)); 740349cc55cSDimitry Andric 74106c3fb27SDimitry Andric if (C == GV) 742349cc55cSDimitry Andric if (Constant *Result = ConstantFoldLoadFromConst(GV->getInitializer(), Ty, 743349cc55cSDimitry Andric Offset, DL)) 744349cc55cSDimitry Andric return Result; 7450b57cec5SDimitry Andric 74604eeddc0SDimitry Andric // If this load comes from anywhere in a uniform constant global, the value 74704eeddc0SDimitry Andric // is always the same, regardless of the loaded offset. 7480fca6ea1SDimitry Andric return ConstantFoldLoadFromUniformValue(GV->getInitializer(), Ty, DL); 749349cc55cSDimitry Andric } 750349cc55cSDimitry Andric 751349cc55cSDimitry Andric Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, 752349cc55cSDimitry Andric const DataLayout &DL) { 753349cc55cSDimitry Andric APInt Offset(DL.getIndexTypeSizeInBits(C->getType()), 0); 7540fca6ea1SDimitry Andric return ConstantFoldLoadFromConstPtr(C, Ty, std::move(Offset), DL); 7550b57cec5SDimitry Andric } 7560b57cec5SDimitry Andric 7570fca6ea1SDimitry Andric Constant *llvm::ConstantFoldLoadFromUniformValue(Constant *C, Type *Ty, 7580fca6ea1SDimitry Andric const DataLayout &DL) { 75904eeddc0SDimitry Andric if (isa<PoisonValue>(C)) 76004eeddc0SDimitry Andric return PoisonValue::get(Ty); 76104eeddc0SDimitry Andric if (isa<UndefValue>(C)) 76204eeddc0SDimitry Andric return UndefValue::get(Ty); 7630fca6ea1SDimitry Andric // If padding is needed when storing C to memory, then it isn't considered as 7640fca6ea1SDimitry Andric // uniform. 7650fca6ea1SDimitry Andric if (!DL.typeSizeEqualsStoreSize(C->getType())) 7660fca6ea1SDimitry Andric return nullptr; 76704eeddc0SDimitry Andric if (C->isNullValue() && !Ty->isX86_MMXTy() && !Ty->isX86_AMXTy()) 76804eeddc0SDimitry Andric return Constant::getNullValue(Ty); 76904eeddc0SDimitry Andric if (C->isAllOnesValue() && 77004eeddc0SDimitry Andric (Ty->isIntOrIntVectorTy() || Ty->isFPOrFPVectorTy())) 77104eeddc0SDimitry Andric return Constant::getAllOnesValue(Ty); 77204eeddc0SDimitry Andric return nullptr; 77304eeddc0SDimitry Andric } 77404eeddc0SDimitry Andric 7750b57cec5SDimitry Andric namespace { 7760b57cec5SDimitry Andric 7770b57cec5SDimitry Andric /// One of Op0/Op1 is a constant expression. 7780b57cec5SDimitry Andric /// Attempt to symbolically evaluate the result of a binary operator merging 7790b57cec5SDimitry Andric /// these together. If target data info is available, it is provided as DL, 7800b57cec5SDimitry Andric /// otherwise DL is null. 7810b57cec5SDimitry Andric Constant *SymbolicallyEvaluateBinop(unsigned Opc, Constant *Op0, Constant *Op1, 7820b57cec5SDimitry Andric const DataLayout &DL) { 7830b57cec5SDimitry Andric // SROA 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric // Fold (and 0xffffffff00000000, (shl x, 32)) -> shl. 7860b57cec5SDimitry Andric // Fold (lshr (or X, Y), 32) -> (lshr [X/Y], 32) if one doesn't contribute 7870b57cec5SDimitry Andric // bits. 7880b57cec5SDimitry Andric 7890b57cec5SDimitry Andric if (Opc == Instruction::And) { 7900b57cec5SDimitry Andric KnownBits Known0 = computeKnownBits(Op0, DL); 7910b57cec5SDimitry Andric KnownBits Known1 = computeKnownBits(Op1, DL); 792349cc55cSDimitry Andric if ((Known1.One | Known0.Zero).isAllOnes()) { 7930b57cec5SDimitry Andric // All the bits of Op0 that the 'and' could be masking are already zero. 7940b57cec5SDimitry Andric return Op0; 7950b57cec5SDimitry Andric } 796349cc55cSDimitry Andric if ((Known0.One | Known1.Zero).isAllOnes()) { 7970b57cec5SDimitry Andric // All the bits of Op1 that the 'and' could be masking are already zero. 7980b57cec5SDimitry Andric return Op1; 7990b57cec5SDimitry Andric } 8000b57cec5SDimitry Andric 8015ffd83dbSDimitry Andric Known0 &= Known1; 8020b57cec5SDimitry Andric if (Known0.isConstant()) 8030b57cec5SDimitry Andric return ConstantInt::get(Op0->getType(), Known0.getConstant()); 8040b57cec5SDimitry Andric } 8050b57cec5SDimitry Andric 8060b57cec5SDimitry Andric // If the constant expr is something like &A[123] - &A[4].f, fold this into a 8070b57cec5SDimitry Andric // constant. This happens frequently when iterating over a global array. 8080b57cec5SDimitry Andric if (Opc == Instruction::Sub) { 8090b57cec5SDimitry Andric GlobalValue *GV1, *GV2; 8100b57cec5SDimitry Andric APInt Offs1, Offs2; 8110b57cec5SDimitry Andric 8120b57cec5SDimitry Andric if (IsConstantOffsetFromGlobal(Op0, GV1, Offs1, DL)) 8130b57cec5SDimitry Andric if (IsConstantOffsetFromGlobal(Op1, GV2, Offs2, DL) && GV1 == GV2) { 8140b57cec5SDimitry Andric unsigned OpSize = DL.getTypeSizeInBits(Op0->getType()); 8150b57cec5SDimitry Andric 8160b57cec5SDimitry Andric // (&GV+C1) - (&GV+C2) -> C1-C2, pointer arithmetic cannot overflow. 8170b57cec5SDimitry Andric // PtrToInt may change the bitwidth so we have convert to the right size 8180b57cec5SDimitry Andric // first. 8190b57cec5SDimitry Andric return ConstantInt::get(Op0->getType(), Offs1.zextOrTrunc(OpSize) - 8200b57cec5SDimitry Andric Offs2.zextOrTrunc(OpSize)); 8210b57cec5SDimitry Andric } 8220b57cec5SDimitry Andric } 8230b57cec5SDimitry Andric 8240b57cec5SDimitry Andric return nullptr; 8250b57cec5SDimitry Andric } 8260b57cec5SDimitry Andric 8270b57cec5SDimitry Andric /// If array indices are not pointer-sized integers, explicitly cast them so 8280b57cec5SDimitry Andric /// that they aren't implicitly casted by the getelementptr. 8290b57cec5SDimitry Andric Constant *CastGEPIndices(Type *SrcElemTy, ArrayRef<Constant *> Ops, 8300fca6ea1SDimitry Andric Type *ResultTy, GEPNoWrapFlags NW, 8310fca6ea1SDimitry Andric std::optional<ConstantRange> InRange, 8320b57cec5SDimitry Andric const DataLayout &DL, const TargetLibraryInfo *TLI) { 833480093f4SDimitry Andric Type *IntIdxTy = DL.getIndexType(ResultTy); 834480093f4SDimitry Andric Type *IntIdxScalarTy = IntIdxTy->getScalarType(); 8350b57cec5SDimitry Andric 8360b57cec5SDimitry Andric bool Any = false; 8370b57cec5SDimitry Andric SmallVector<Constant*, 32> NewIdxs; 8380b57cec5SDimitry Andric for (unsigned i = 1, e = Ops.size(); i != e; ++i) { 8390b57cec5SDimitry Andric if ((i == 1 || 8400b57cec5SDimitry Andric !isa<StructType>(GetElementPtrInst::getIndexedType( 8410b57cec5SDimitry Andric SrcElemTy, Ops.slice(1, i - 1)))) && 842480093f4SDimitry Andric Ops[i]->getType()->getScalarType() != IntIdxScalarTy) { 8430b57cec5SDimitry Andric Any = true; 8445f757f3fSDimitry Andric Type *NewType = 8455f757f3fSDimitry Andric Ops[i]->getType()->isVectorTy() ? IntIdxTy : IntIdxScalarTy; 8465f757f3fSDimitry Andric Constant *NewIdx = ConstantFoldCastOperand( 8475f757f3fSDimitry Andric CastInst::getCastOpcode(Ops[i], true, NewType, true), Ops[i], NewType, 8485f757f3fSDimitry Andric DL); 8495f757f3fSDimitry Andric if (!NewIdx) 8505f757f3fSDimitry Andric return nullptr; 8515f757f3fSDimitry Andric NewIdxs.push_back(NewIdx); 8520b57cec5SDimitry Andric } else 8530b57cec5SDimitry Andric NewIdxs.push_back(Ops[i]); 8540b57cec5SDimitry Andric } 8550b57cec5SDimitry Andric 8560b57cec5SDimitry Andric if (!Any) 8570b57cec5SDimitry Andric return nullptr; 8580b57cec5SDimitry Andric 8590fca6ea1SDimitry Andric Constant *C = 8600fca6ea1SDimitry Andric ConstantExpr::getGetElementPtr(SrcElemTy, Ops[0], NewIdxs, NW, InRange); 8615ffd83dbSDimitry Andric return ConstantFoldConstant(C, DL, TLI); 8620b57cec5SDimitry Andric } 8630b57cec5SDimitry Andric 8640b57cec5SDimitry Andric /// If we can symbolically evaluate the GEP constant expression, do so. 8650b57cec5SDimitry Andric Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, 8660b57cec5SDimitry Andric ArrayRef<Constant *> Ops, 8670b57cec5SDimitry Andric const DataLayout &DL, 868349cc55cSDimitry Andric const TargetLibraryInfo *TLI) { 8690b57cec5SDimitry Andric Type *SrcElemTy = GEP->getSourceElementType(); 8700b57cec5SDimitry Andric Type *ResTy = GEP->getType(); 8715ffd83dbSDimitry Andric if (!SrcElemTy->isSized() || isa<ScalableVectorType>(SrcElemTy)) 8720b57cec5SDimitry Andric return nullptr; 8730b57cec5SDimitry Andric 8740fca6ea1SDimitry Andric if (Constant *C = CastGEPIndices(SrcElemTy, Ops, ResTy, GEP->getNoWrapFlags(), 8750fca6ea1SDimitry Andric GEP->getInRange(), DL, TLI)) 8760b57cec5SDimitry Andric return C; 8770b57cec5SDimitry Andric 8780b57cec5SDimitry Andric Constant *Ptr = Ops[0]; 8790b57cec5SDimitry Andric if (!Ptr->getType()->isPointerTy()) 8800b57cec5SDimitry Andric return nullptr; 8810b57cec5SDimitry Andric 882480093f4SDimitry Andric Type *IntIdxTy = DL.getIndexType(Ptr->getType()); 8830b57cec5SDimitry Andric 884fe6060f1SDimitry Andric for (unsigned i = 1, e = Ops.size(); i != e; ++i) 885fe6060f1SDimitry Andric if (!isa<ConstantInt>(Ops[i])) 8860b57cec5SDimitry Andric return nullptr; 8870b57cec5SDimitry Andric 888480093f4SDimitry Andric unsigned BitWidth = DL.getTypeSizeInBits(IntIdxTy); 889bdd1243dSDimitry Andric APInt Offset = APInt( 890bdd1243dSDimitry Andric BitWidth, 8910b57cec5SDimitry Andric DL.getIndexedOffsetInType( 892bdd1243dSDimitry Andric SrcElemTy, ArrayRef((Value *const *)Ops.data() + 1, Ops.size() - 1))); 8930b57cec5SDimitry Andric 8940fca6ea1SDimitry Andric std::optional<ConstantRange> InRange = GEP->getInRange(); 8950fca6ea1SDimitry Andric if (InRange) 8960fca6ea1SDimitry Andric InRange = InRange->sextOrTrunc(BitWidth); 8970fca6ea1SDimitry Andric 8980b57cec5SDimitry Andric // If this is a GEP of a GEP, fold it all into a single GEP. 8990fca6ea1SDimitry Andric GEPNoWrapFlags NW = GEP->getNoWrapFlags(); 9000fca6ea1SDimitry Andric bool Overflow = false; 9010b57cec5SDimitry Andric while (auto *GEP = dyn_cast<GEPOperator>(Ptr)) { 9020fca6ea1SDimitry Andric NW &= GEP->getNoWrapFlags(); 9030b57cec5SDimitry Andric 9040eae32dcSDimitry Andric SmallVector<Value *, 4> NestedOps(llvm::drop_begin(GEP->operands())); 9050b57cec5SDimitry Andric 9060b57cec5SDimitry Andric // Do not try the incorporate the sub-GEP if some index is not a number. 9070b57cec5SDimitry Andric bool AllConstantInt = true; 9080b57cec5SDimitry Andric for (Value *NestedOp : NestedOps) 9090b57cec5SDimitry Andric if (!isa<ConstantInt>(NestedOp)) { 9100b57cec5SDimitry Andric AllConstantInt = false; 9110b57cec5SDimitry Andric break; 9120b57cec5SDimitry Andric } 9130b57cec5SDimitry Andric if (!AllConstantInt) 9140b57cec5SDimitry Andric break; 9150b57cec5SDimitry Andric 9160fca6ea1SDimitry Andric // TODO: Try to intersect two inrange attributes? 9170fca6ea1SDimitry Andric if (!InRange) { 9180fca6ea1SDimitry Andric InRange = GEP->getInRange(); 9190fca6ea1SDimitry Andric if (InRange) 9200fca6ea1SDimitry Andric // Adjust inrange by offset until now. 9210fca6ea1SDimitry Andric InRange = InRange->sextOrTrunc(BitWidth).subtract(Offset); 9220fca6ea1SDimitry Andric } 9230fca6ea1SDimitry Andric 9240b57cec5SDimitry Andric Ptr = cast<Constant>(GEP->getOperand(0)); 9250b57cec5SDimitry Andric SrcElemTy = GEP->getSourceElementType(); 9260fca6ea1SDimitry Andric Offset = Offset.sadd_ov( 9270fca6ea1SDimitry Andric APInt(BitWidth, DL.getIndexedOffsetInType(SrcElemTy, NestedOps)), 9280fca6ea1SDimitry Andric Overflow); 9290b57cec5SDimitry Andric } 9300b57cec5SDimitry Andric 9310fca6ea1SDimitry Andric // Preserving nusw (without inbounds) also requires that the offset 9320fca6ea1SDimitry Andric // additions did not overflow. 9330fca6ea1SDimitry Andric if (NW.hasNoUnsignedSignedWrap() && !NW.isInBounds() && Overflow) 9340fca6ea1SDimitry Andric NW = NW.withoutNoUnsignedSignedWrap(); 9350fca6ea1SDimitry Andric 9360b57cec5SDimitry Andric // If the base value for this address is a literal integer value, fold the 9370b57cec5SDimitry Andric // getelementptr to the resulting integer value casted to the pointer type. 9380b57cec5SDimitry Andric APInt BasePtr(BitWidth, 0); 9390b57cec5SDimitry Andric if (auto *CE = dyn_cast<ConstantExpr>(Ptr)) { 9400b57cec5SDimitry Andric if (CE->getOpcode() == Instruction::IntToPtr) { 9410b57cec5SDimitry Andric if (auto *Base = dyn_cast<ConstantInt>(CE->getOperand(0))) 9420b57cec5SDimitry Andric BasePtr = Base->getValue().zextOrTrunc(BitWidth); 9430b57cec5SDimitry Andric } 9440b57cec5SDimitry Andric } 9450b57cec5SDimitry Andric 9460b57cec5SDimitry Andric auto *PTy = cast<PointerType>(Ptr->getType()); 9470b57cec5SDimitry Andric if ((Ptr->isNullValue() || BasePtr != 0) && 9480b57cec5SDimitry Andric !DL.isNonIntegralPointerType(PTy)) { 9490b57cec5SDimitry Andric Constant *C = ConstantInt::get(Ptr->getContext(), Offset + BasePtr); 9500b57cec5SDimitry Andric return ConstantExpr::getIntToPtr(C, ResTy); 9510b57cec5SDimitry Andric } 9520b57cec5SDimitry Andric 9530fca6ea1SDimitry Andric // Try to infer inbounds for GEPs of globals. 9540fca6ea1SDimitry Andric // TODO(gep_nowrap): Also infer nuw flag. 9550fca6ea1SDimitry Andric if (!NW.isInBounds() && Offset.isNonNegative()) { 9560fca6ea1SDimitry Andric bool CanBeNull, CanBeFreed; 9570fca6ea1SDimitry Andric uint64_t DerefBytes = 9580fca6ea1SDimitry Andric Ptr->getPointerDereferenceableBytes(DL, CanBeNull, CanBeFreed); 9590fca6ea1SDimitry Andric if (DerefBytes != 0 && !CanBeNull && Offset.sle(DerefBytes)) 9600fca6ea1SDimitry Andric NW |= GEPNoWrapFlags::inBounds(); 961349cc55cSDimitry Andric } 962349cc55cSDimitry Andric 9630fca6ea1SDimitry Andric // Otherwise canonicalize this to a single ptradd. 9640fca6ea1SDimitry Andric LLVMContext &Ctx = Ptr->getContext(); 9650fca6ea1SDimitry Andric return ConstantExpr::getGetElementPtr(Type::getInt8Ty(Ctx), Ptr, 9660fca6ea1SDimitry Andric ConstantInt::get(Ctx, Offset), NW, 9670fca6ea1SDimitry Andric InRange); 9680b57cec5SDimitry Andric } 9690b57cec5SDimitry Andric 9700b57cec5SDimitry Andric /// Attempt to constant fold an instruction with the 9710b57cec5SDimitry Andric /// specified opcode and operands. If successful, the constant result is 9720b57cec5SDimitry Andric /// returned, if not, null is returned. Note that this function can fail when 9730b57cec5SDimitry Andric /// attempting to fold instructions like loads and stores, which have no 9740b57cec5SDimitry Andric /// constant expression form. 9750b57cec5SDimitry Andric Constant *ConstantFoldInstOperandsImpl(const Value *InstOrCE, unsigned Opcode, 9760b57cec5SDimitry Andric ArrayRef<Constant *> Ops, 9770b57cec5SDimitry Andric const DataLayout &DL, 9780fca6ea1SDimitry Andric const TargetLibraryInfo *TLI, 9790fca6ea1SDimitry Andric bool AllowNonDeterministic) { 9800b57cec5SDimitry Andric Type *DestTy = InstOrCE->getType(); 9810b57cec5SDimitry Andric 9820b57cec5SDimitry Andric if (Instruction::isUnaryOp(Opcode)) 9830b57cec5SDimitry Andric return ConstantFoldUnaryOpOperand(Opcode, Ops[0], DL); 9840b57cec5SDimitry Andric 98581ad6265SDimitry Andric if (Instruction::isBinaryOp(Opcode)) { 98681ad6265SDimitry Andric switch (Opcode) { 98781ad6265SDimitry Andric default: 98881ad6265SDimitry Andric break; 98981ad6265SDimitry Andric case Instruction::FAdd: 99081ad6265SDimitry Andric case Instruction::FSub: 99181ad6265SDimitry Andric case Instruction::FMul: 99281ad6265SDimitry Andric case Instruction::FDiv: 99381ad6265SDimitry Andric case Instruction::FRem: 99481ad6265SDimitry Andric // Handle floating point instructions separately to account for denormals 99581ad6265SDimitry Andric // TODO: If a constant expression is being folded rather than an 99681ad6265SDimitry Andric // instruction, denormals will not be flushed/treated as zero 99781ad6265SDimitry Andric if (const auto *I = dyn_cast<Instruction>(InstOrCE)) { 9980fca6ea1SDimitry Andric return ConstantFoldFPInstOperands(Opcode, Ops[0], Ops[1], DL, I, 9990fca6ea1SDimitry Andric AllowNonDeterministic); 100081ad6265SDimitry Andric } 100181ad6265SDimitry Andric } 10020b57cec5SDimitry Andric return ConstantFoldBinaryOpOperands(Opcode, Ops[0], Ops[1], DL); 100381ad6265SDimitry Andric } 10040b57cec5SDimitry Andric 10050b57cec5SDimitry Andric if (Instruction::isCast(Opcode)) 10060b57cec5SDimitry Andric return ConstantFoldCastOperand(Opcode, Ops[0], DestTy, DL); 10070b57cec5SDimitry Andric 10080b57cec5SDimitry Andric if (auto *GEP = dyn_cast<GEPOperator>(InstOrCE)) { 100906c3fb27SDimitry Andric Type *SrcElemTy = GEP->getSourceElementType(); 101006c3fb27SDimitry Andric if (!ConstantExpr::isSupportedGetElementPtr(SrcElemTy)) 101106c3fb27SDimitry Andric return nullptr; 101206c3fb27SDimitry Andric 1013349cc55cSDimitry Andric if (Constant *C = SymbolicallyEvaluateGEP(GEP, Ops, DL, TLI)) 10140b57cec5SDimitry Andric return C; 10150b57cec5SDimitry Andric 101606c3fb27SDimitry Andric return ConstantExpr::getGetElementPtr(SrcElemTy, Ops[0], Ops.slice(1), 10170fca6ea1SDimitry Andric GEP->getNoWrapFlags(), 10180fca6ea1SDimitry Andric GEP->getInRange()); 10190b57cec5SDimitry Andric } 10200b57cec5SDimitry Andric 10210fca6ea1SDimitry Andric if (auto *CE = dyn_cast<ConstantExpr>(InstOrCE)) 10220b57cec5SDimitry Andric return CE->getWithOperands(Ops); 10230b57cec5SDimitry Andric 10240b57cec5SDimitry Andric switch (Opcode) { 10250b57cec5SDimitry Andric default: return nullptr; 10260b57cec5SDimitry Andric case Instruction::ICmp: 102781ad6265SDimitry Andric case Instruction::FCmp: { 102881ad6265SDimitry Andric auto *C = cast<CmpInst>(InstOrCE); 102981ad6265SDimitry Andric return ConstantFoldCompareInstOperands(C->getPredicate(), Ops[0], Ops[1], 103081ad6265SDimitry Andric DL, TLI, C); 103181ad6265SDimitry Andric } 1032e8d8bef9SDimitry Andric case Instruction::Freeze: 1033e8d8bef9SDimitry Andric return isGuaranteedNotToBeUndefOrPoison(Ops[0]) ? Ops[0] : nullptr; 10340b57cec5SDimitry Andric case Instruction::Call: 10350b57cec5SDimitry Andric if (auto *F = dyn_cast<Function>(Ops.back())) { 10360b57cec5SDimitry Andric const auto *Call = cast<CallBase>(InstOrCE); 10370b57cec5SDimitry Andric if (canConstantFoldCallTo(Call, F)) 10380fca6ea1SDimitry Andric return ConstantFoldCall(Call, F, Ops.slice(0, Ops.size() - 1), TLI, 10390fca6ea1SDimitry Andric AllowNonDeterministic); 10400b57cec5SDimitry Andric } 10410b57cec5SDimitry Andric return nullptr; 10420b57cec5SDimitry Andric case Instruction::Select: 104306c3fb27SDimitry Andric return ConstantFoldSelectInstruction(Ops[0], Ops[1], Ops[2]); 10440b57cec5SDimitry Andric case Instruction::ExtractElement: 10450b57cec5SDimitry Andric return ConstantExpr::getExtractElement(Ops[0], Ops[1]); 10460b57cec5SDimitry Andric case Instruction::ExtractValue: 104781ad6265SDimitry Andric return ConstantFoldExtractValueInstruction( 10488bcb0991SDimitry Andric Ops[0], cast<ExtractValueInst>(InstOrCE)->getIndices()); 10490b57cec5SDimitry Andric case Instruction::InsertElement: 10500b57cec5SDimitry Andric return ConstantExpr::getInsertElement(Ops[0], Ops[1], Ops[2]); 105181ad6265SDimitry Andric case Instruction::InsertValue: 105281ad6265SDimitry Andric return ConstantFoldInsertValueInstruction( 105381ad6265SDimitry Andric Ops[0], Ops[1], cast<InsertValueInst>(InstOrCE)->getIndices()); 10540b57cec5SDimitry Andric case Instruction::ShuffleVector: 10555ffd83dbSDimitry Andric return ConstantExpr::getShuffleVector( 10565ffd83dbSDimitry Andric Ops[0], Ops[1], cast<ShuffleVectorInst>(InstOrCE)->getShuffleMask()); 105781ad6265SDimitry Andric case Instruction::Load: { 105881ad6265SDimitry Andric const auto *LI = dyn_cast<LoadInst>(InstOrCE); 105981ad6265SDimitry Andric if (LI->isVolatile()) 106081ad6265SDimitry Andric return nullptr; 106181ad6265SDimitry Andric return ConstantFoldLoadFromConstPtr(Ops[0], LI->getType(), DL); 106281ad6265SDimitry Andric } 10630b57cec5SDimitry Andric } 10640b57cec5SDimitry Andric } 10650b57cec5SDimitry Andric 10660b57cec5SDimitry Andric } // end anonymous namespace 10670b57cec5SDimitry Andric 10680b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 10690b57cec5SDimitry Andric // Constant Folding public APIs 10700b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 10710b57cec5SDimitry Andric 10720b57cec5SDimitry Andric namespace { 10730b57cec5SDimitry Andric 10740b57cec5SDimitry Andric Constant * 10750b57cec5SDimitry Andric ConstantFoldConstantImpl(const Constant *C, const DataLayout &DL, 10760b57cec5SDimitry Andric const TargetLibraryInfo *TLI, 10770b57cec5SDimitry Andric SmallDenseMap<Constant *, Constant *> &FoldedOps) { 10780b57cec5SDimitry Andric if (!isa<ConstantVector>(C) && !isa<ConstantExpr>(C)) 10795ffd83dbSDimitry Andric return const_cast<Constant *>(C); 10800b57cec5SDimitry Andric 10810b57cec5SDimitry Andric SmallVector<Constant *, 8> Ops; 10825ffd83dbSDimitry Andric for (const Use &OldU : C->operands()) { 10835ffd83dbSDimitry Andric Constant *OldC = cast<Constant>(&OldU); 10845ffd83dbSDimitry Andric Constant *NewC = OldC; 10850b57cec5SDimitry Andric // Recursively fold the ConstantExpr's operands. If we have already folded 10860b57cec5SDimitry Andric // a ConstantExpr, we don't have to process it again. 10875ffd83dbSDimitry Andric if (isa<ConstantVector>(OldC) || isa<ConstantExpr>(OldC)) { 10885ffd83dbSDimitry Andric auto It = FoldedOps.find(OldC); 10890b57cec5SDimitry Andric if (It == FoldedOps.end()) { 10905ffd83dbSDimitry Andric NewC = ConstantFoldConstantImpl(OldC, DL, TLI, FoldedOps); 10915ffd83dbSDimitry Andric FoldedOps.insert({OldC, NewC}); 10920b57cec5SDimitry Andric } else { 10930b57cec5SDimitry Andric NewC = It->second; 10940b57cec5SDimitry Andric } 10950b57cec5SDimitry Andric } 10960b57cec5SDimitry Andric Ops.push_back(NewC); 10970b57cec5SDimitry Andric } 10980b57cec5SDimitry Andric 1099753f127fSDimitry Andric if (auto *CE = dyn_cast<ConstantExpr>(C)) { 11000fca6ea1SDimitry Andric if (Constant *Res = ConstantFoldInstOperandsImpl( 11010fca6ea1SDimitry Andric CE, CE->getOpcode(), Ops, DL, TLI, /*AllowNonDeterministic=*/true)) 1102753f127fSDimitry Andric return Res; 1103753f127fSDimitry Andric return const_cast<Constant *>(C); 1104753f127fSDimitry Andric } 11050b57cec5SDimitry Andric 11060b57cec5SDimitry Andric assert(isa<ConstantVector>(C)); 11070b57cec5SDimitry Andric return ConstantVector::get(Ops); 11080b57cec5SDimitry Andric } 11090b57cec5SDimitry Andric 11100b57cec5SDimitry Andric } // end anonymous namespace 11110b57cec5SDimitry Andric 11120b57cec5SDimitry Andric Constant *llvm::ConstantFoldInstruction(Instruction *I, const DataLayout &DL, 11130b57cec5SDimitry Andric const TargetLibraryInfo *TLI) { 11140b57cec5SDimitry Andric // Handle PHI nodes quickly here... 11150b57cec5SDimitry Andric if (auto *PN = dyn_cast<PHINode>(I)) { 11160b57cec5SDimitry Andric Constant *CommonValue = nullptr; 11170b57cec5SDimitry Andric 11180b57cec5SDimitry Andric SmallDenseMap<Constant *, Constant *> FoldedOps; 11190b57cec5SDimitry Andric for (Value *Incoming : PN->incoming_values()) { 11200b57cec5SDimitry Andric // If the incoming value is undef then skip it. Note that while we could 11210b57cec5SDimitry Andric // skip the value if it is equal to the phi node itself we choose not to 11220b57cec5SDimitry Andric // because that would break the rule that constant folding only applies if 11230b57cec5SDimitry Andric // all operands are constants. 11240b57cec5SDimitry Andric if (isa<UndefValue>(Incoming)) 11250b57cec5SDimitry Andric continue; 11260b57cec5SDimitry Andric // If the incoming value is not a constant, then give up. 11270b57cec5SDimitry Andric auto *C = dyn_cast<Constant>(Incoming); 11280b57cec5SDimitry Andric if (!C) 11290b57cec5SDimitry Andric return nullptr; 11300b57cec5SDimitry Andric // Fold the PHI's operands. 11315ffd83dbSDimitry Andric C = ConstantFoldConstantImpl(C, DL, TLI, FoldedOps); 11320b57cec5SDimitry Andric // If the incoming value is a different constant to 11330b57cec5SDimitry Andric // the one we saw previously, then give up. 11340b57cec5SDimitry Andric if (CommonValue && C != CommonValue) 11350b57cec5SDimitry Andric return nullptr; 11360b57cec5SDimitry Andric CommonValue = C; 11370b57cec5SDimitry Andric } 11380b57cec5SDimitry Andric 11390b57cec5SDimitry Andric // If we reach here, all incoming values are the same constant or undef. 11400b57cec5SDimitry Andric return CommonValue ? CommonValue : UndefValue::get(PN->getType()); 11410b57cec5SDimitry Andric } 11420b57cec5SDimitry Andric 11430b57cec5SDimitry Andric // Scan the operand list, checking to see if they are all constants, if so, 11440b57cec5SDimitry Andric // hand off to ConstantFoldInstOperandsImpl. 11450b57cec5SDimitry Andric if (!all_of(I->operands(), [](Use &U) { return isa<Constant>(U); })) 11460b57cec5SDimitry Andric return nullptr; 11470b57cec5SDimitry Andric 11480b57cec5SDimitry Andric SmallDenseMap<Constant *, Constant *> FoldedOps; 11490b57cec5SDimitry Andric SmallVector<Constant *, 8> Ops; 11500b57cec5SDimitry Andric for (const Use &OpU : I->operands()) { 11510b57cec5SDimitry Andric auto *Op = cast<Constant>(&OpU); 11520b57cec5SDimitry Andric // Fold the Instruction's operands. 11535ffd83dbSDimitry Andric Op = ConstantFoldConstantImpl(Op, DL, TLI, FoldedOps); 11540b57cec5SDimitry Andric Ops.push_back(Op); 11550b57cec5SDimitry Andric } 11560b57cec5SDimitry Andric 11570b57cec5SDimitry Andric return ConstantFoldInstOperands(I, Ops, DL, TLI); 11580b57cec5SDimitry Andric } 11590b57cec5SDimitry Andric 11600b57cec5SDimitry Andric Constant *llvm::ConstantFoldConstant(const Constant *C, const DataLayout &DL, 11610b57cec5SDimitry Andric const TargetLibraryInfo *TLI) { 11620b57cec5SDimitry Andric SmallDenseMap<Constant *, Constant *> FoldedOps; 11630b57cec5SDimitry Andric return ConstantFoldConstantImpl(C, DL, TLI, FoldedOps); 11640b57cec5SDimitry Andric } 11650b57cec5SDimitry Andric 11660b57cec5SDimitry Andric Constant *llvm::ConstantFoldInstOperands(Instruction *I, 11670b57cec5SDimitry Andric ArrayRef<Constant *> Ops, 11680b57cec5SDimitry Andric const DataLayout &DL, 11690fca6ea1SDimitry Andric const TargetLibraryInfo *TLI, 11700fca6ea1SDimitry Andric bool AllowNonDeterministic) { 11710fca6ea1SDimitry Andric return ConstantFoldInstOperandsImpl(I, I->getOpcode(), Ops, DL, TLI, 11720fca6ea1SDimitry Andric AllowNonDeterministic); 11730b57cec5SDimitry Andric } 11740b57cec5SDimitry Andric 117581ad6265SDimitry Andric Constant *llvm::ConstantFoldCompareInstOperands( 117681ad6265SDimitry Andric unsigned IntPredicate, Constant *Ops0, Constant *Ops1, const DataLayout &DL, 117781ad6265SDimitry Andric const TargetLibraryInfo *TLI, const Instruction *I) { 117804eeddc0SDimitry Andric CmpInst::Predicate Predicate = (CmpInst::Predicate)IntPredicate; 11790b57cec5SDimitry Andric // fold: icmp (inttoptr x), null -> icmp x, 0 11800b57cec5SDimitry Andric // fold: icmp null, (inttoptr x) -> icmp 0, x 11810b57cec5SDimitry Andric // fold: icmp (ptrtoint x), 0 -> icmp x, null 11820b57cec5SDimitry Andric // fold: icmp 0, (ptrtoint x) -> icmp null, x 11830b57cec5SDimitry Andric // fold: icmp (inttoptr x), (inttoptr y) -> icmp trunc/zext x, trunc/zext y 11840b57cec5SDimitry Andric // fold: icmp (ptrtoint x), (ptrtoint y) -> icmp x, y 11850b57cec5SDimitry Andric // 11860b57cec5SDimitry Andric // FIXME: The following comment is out of data and the DataLayout is here now. 11870b57cec5SDimitry Andric // ConstantExpr::getCompare cannot do this, because it doesn't have DL 11880b57cec5SDimitry Andric // around to know if bit truncation is happening. 11890b57cec5SDimitry Andric if (auto *CE0 = dyn_cast<ConstantExpr>(Ops0)) { 11900b57cec5SDimitry Andric if (Ops1->isNullValue()) { 11910b57cec5SDimitry Andric if (CE0->getOpcode() == Instruction::IntToPtr) { 11920b57cec5SDimitry Andric Type *IntPtrTy = DL.getIntPtrType(CE0->getType()); 11930b57cec5SDimitry Andric // Convert the integer value to the right size to ensure we get the 11940b57cec5SDimitry Andric // proper extension or truncation. 11955f757f3fSDimitry Andric if (Constant *C = ConstantFoldIntegerCast(CE0->getOperand(0), IntPtrTy, 11965f757f3fSDimitry Andric /*IsSigned*/ false, DL)) { 11970b57cec5SDimitry Andric Constant *Null = Constant::getNullValue(C->getType()); 11980b57cec5SDimitry Andric return ConstantFoldCompareInstOperands(Predicate, C, Null, DL, TLI); 11990b57cec5SDimitry Andric } 12005f757f3fSDimitry Andric } 12010b57cec5SDimitry Andric 12020b57cec5SDimitry Andric // Only do this transformation if the int is intptrty in size, otherwise 12030b57cec5SDimitry Andric // there is a truncation or extension that we aren't modeling. 12040b57cec5SDimitry Andric if (CE0->getOpcode() == Instruction::PtrToInt) { 12050b57cec5SDimitry Andric Type *IntPtrTy = DL.getIntPtrType(CE0->getOperand(0)->getType()); 12060b57cec5SDimitry Andric if (CE0->getType() == IntPtrTy) { 12070b57cec5SDimitry Andric Constant *C = CE0->getOperand(0); 12080b57cec5SDimitry Andric Constant *Null = Constant::getNullValue(C->getType()); 12090b57cec5SDimitry Andric return ConstantFoldCompareInstOperands(Predicate, C, Null, DL, TLI); 12100b57cec5SDimitry Andric } 12110b57cec5SDimitry Andric } 12120b57cec5SDimitry Andric } 12130b57cec5SDimitry Andric 12140b57cec5SDimitry Andric if (auto *CE1 = dyn_cast<ConstantExpr>(Ops1)) { 12150b57cec5SDimitry Andric if (CE0->getOpcode() == CE1->getOpcode()) { 12160b57cec5SDimitry Andric if (CE0->getOpcode() == Instruction::IntToPtr) { 12170b57cec5SDimitry Andric Type *IntPtrTy = DL.getIntPtrType(CE0->getType()); 12180b57cec5SDimitry Andric 12190b57cec5SDimitry Andric // Convert the integer value to the right size to ensure we get the 12200b57cec5SDimitry Andric // proper extension or truncation. 12215f757f3fSDimitry Andric Constant *C0 = ConstantFoldIntegerCast(CE0->getOperand(0), IntPtrTy, 12225f757f3fSDimitry Andric /*IsSigned*/ false, DL); 12235f757f3fSDimitry Andric Constant *C1 = ConstantFoldIntegerCast(CE1->getOperand(0), IntPtrTy, 12245f757f3fSDimitry Andric /*IsSigned*/ false, DL); 12255f757f3fSDimitry Andric if (C0 && C1) 12260b57cec5SDimitry Andric return ConstantFoldCompareInstOperands(Predicate, C0, C1, DL, TLI); 12270b57cec5SDimitry Andric } 12280b57cec5SDimitry Andric 12290b57cec5SDimitry Andric // Only do this transformation if the int is intptrty in size, otherwise 12300b57cec5SDimitry Andric // there is a truncation or extension that we aren't modeling. 12310b57cec5SDimitry Andric if (CE0->getOpcode() == Instruction::PtrToInt) { 12320b57cec5SDimitry Andric Type *IntPtrTy = DL.getIntPtrType(CE0->getOperand(0)->getType()); 12330b57cec5SDimitry Andric if (CE0->getType() == IntPtrTy && 12340b57cec5SDimitry Andric CE0->getOperand(0)->getType() == CE1->getOperand(0)->getType()) { 12350b57cec5SDimitry Andric return ConstantFoldCompareInstOperands( 12360b57cec5SDimitry Andric Predicate, CE0->getOperand(0), CE1->getOperand(0), DL, TLI); 12370b57cec5SDimitry Andric } 12380b57cec5SDimitry Andric } 12390b57cec5SDimitry Andric } 12400b57cec5SDimitry Andric } 12410b57cec5SDimitry Andric 124204eeddc0SDimitry Andric // Convert pointer comparison (base+offset1) pred (base+offset2) into 124304eeddc0SDimitry Andric // offset1 pred offset2, for the case where the offset is inbounds. This 124404eeddc0SDimitry Andric // only works for equality and unsigned comparison, as inbounds permits 124504eeddc0SDimitry Andric // crossing the sign boundary. However, the offset comparison itself is 124604eeddc0SDimitry Andric // signed. 124704eeddc0SDimitry Andric if (Ops0->getType()->isPointerTy() && !ICmpInst::isSigned(Predicate)) { 124804eeddc0SDimitry Andric unsigned IndexWidth = DL.getIndexTypeSizeInBits(Ops0->getType()); 124904eeddc0SDimitry Andric APInt Offset0(IndexWidth, 0); 125004eeddc0SDimitry Andric Value *Stripped0 = 125104eeddc0SDimitry Andric Ops0->stripAndAccumulateInBoundsConstantOffsets(DL, Offset0); 125204eeddc0SDimitry Andric APInt Offset1(IndexWidth, 0); 125304eeddc0SDimitry Andric Value *Stripped1 = 125404eeddc0SDimitry Andric Ops1->stripAndAccumulateInBoundsConstantOffsets(DL, Offset1); 125504eeddc0SDimitry Andric if (Stripped0 == Stripped1) 12560fca6ea1SDimitry Andric return ConstantInt::getBool( 12570fca6ea1SDimitry Andric Ops0->getContext(), 12580fca6ea1SDimitry Andric ICmpInst::compare(Offset0, Offset1, 12590fca6ea1SDimitry Andric ICmpInst::getSignedPredicate(Predicate))); 126004eeddc0SDimitry Andric } 12610b57cec5SDimitry Andric } else if (isa<ConstantExpr>(Ops1)) { 12620b57cec5SDimitry Andric // If RHS is a constant expression, but the left side isn't, swap the 12630b57cec5SDimitry Andric // operands and try again. 126404eeddc0SDimitry Andric Predicate = ICmpInst::getSwappedPredicate(Predicate); 12650b57cec5SDimitry Andric return ConstantFoldCompareInstOperands(Predicate, Ops1, Ops0, DL, TLI); 12660b57cec5SDimitry Andric } 12670b57cec5SDimitry Andric 126881ad6265SDimitry Andric // Flush any denormal constant float input according to denormal handling 126981ad6265SDimitry Andric // mode. 127081ad6265SDimitry Andric Ops0 = FlushFPConstant(Ops0, I, /* IsOutput */ false); 127106c3fb27SDimitry Andric if (!Ops0) 127206c3fb27SDimitry Andric return nullptr; 127381ad6265SDimitry Andric Ops1 = FlushFPConstant(Ops1, I, /* IsOutput */ false); 127406c3fb27SDimitry Andric if (!Ops1) 127506c3fb27SDimitry Andric return nullptr; 127681ad6265SDimitry Andric 12770fca6ea1SDimitry Andric return ConstantFoldCompareInstruction(Predicate, Ops0, Ops1); 12780b57cec5SDimitry Andric } 12790b57cec5SDimitry Andric 12800b57cec5SDimitry Andric Constant *llvm::ConstantFoldUnaryOpOperand(unsigned Opcode, Constant *Op, 12810b57cec5SDimitry Andric const DataLayout &DL) { 12820b57cec5SDimitry Andric assert(Instruction::isUnaryOp(Opcode)); 12830b57cec5SDimitry Andric 1284bdd1243dSDimitry Andric return ConstantFoldUnaryInstruction(Opcode, Op); 12850b57cec5SDimitry Andric } 12860b57cec5SDimitry Andric 12870b57cec5SDimitry Andric Constant *llvm::ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS, 12880b57cec5SDimitry Andric Constant *RHS, 12890b57cec5SDimitry Andric const DataLayout &DL) { 12900b57cec5SDimitry Andric assert(Instruction::isBinaryOp(Opcode)); 12910b57cec5SDimitry Andric if (isa<ConstantExpr>(LHS) || isa<ConstantExpr>(RHS)) 12920b57cec5SDimitry Andric if (Constant *C = SymbolicallyEvaluateBinop(Opcode, LHS, RHS, DL)) 12930b57cec5SDimitry Andric return C; 12940b57cec5SDimitry Andric 1295753f127fSDimitry Andric if (ConstantExpr::isDesirableBinOp(Opcode)) 12960b57cec5SDimitry Andric return ConstantExpr::get(Opcode, LHS, RHS); 1297753f127fSDimitry Andric return ConstantFoldBinaryInstruction(Opcode, LHS, RHS); 12980b57cec5SDimitry Andric } 12990b57cec5SDimitry Andric 130081ad6265SDimitry Andric Constant *llvm::FlushFPConstant(Constant *Operand, const Instruction *I, 130181ad6265SDimitry Andric bool IsOutput) { 130281ad6265SDimitry Andric if (!I || !I->getParent() || !I->getFunction()) 130381ad6265SDimitry Andric return Operand; 130481ad6265SDimitry Andric 130581ad6265SDimitry Andric ConstantFP *CFP = dyn_cast<ConstantFP>(Operand); 130681ad6265SDimitry Andric if (!CFP) 130781ad6265SDimitry Andric return Operand; 130881ad6265SDimitry Andric 130981ad6265SDimitry Andric const APFloat &APF = CFP->getValueAPF(); 131006c3fb27SDimitry Andric // TODO: Should this canonicalize nans? 131106c3fb27SDimitry Andric if (!APF.isDenormal()) 131206c3fb27SDimitry Andric return Operand; 131306c3fb27SDimitry Andric 131481ad6265SDimitry Andric Type *Ty = CFP->getType(); 131581ad6265SDimitry Andric DenormalMode DenormMode = 131681ad6265SDimitry Andric I->getFunction()->getDenormalMode(Ty->getFltSemantics()); 131781ad6265SDimitry Andric DenormalMode::DenormalModeKind Mode = 131881ad6265SDimitry Andric IsOutput ? DenormMode.Output : DenormMode.Input; 131981ad6265SDimitry Andric switch (Mode) { 132081ad6265SDimitry Andric default: 132181ad6265SDimitry Andric llvm_unreachable("unknown denormal mode"); 132206c3fb27SDimitry Andric case DenormalMode::Dynamic: 132306c3fb27SDimitry Andric return nullptr; 132481ad6265SDimitry Andric case DenormalMode::IEEE: 132581ad6265SDimitry Andric return Operand; 132681ad6265SDimitry Andric case DenormalMode::PreserveSign: 132781ad6265SDimitry Andric if (APF.isDenormal()) { 132881ad6265SDimitry Andric return ConstantFP::get( 132981ad6265SDimitry Andric Ty->getContext(), 133081ad6265SDimitry Andric APFloat::getZero(Ty->getFltSemantics(), APF.isNegative())); 133181ad6265SDimitry Andric } 133281ad6265SDimitry Andric return Operand; 133381ad6265SDimitry Andric case DenormalMode::PositiveZero: 133481ad6265SDimitry Andric if (APF.isDenormal()) { 133581ad6265SDimitry Andric return ConstantFP::get(Ty->getContext(), 133681ad6265SDimitry Andric APFloat::getZero(Ty->getFltSemantics(), false)); 133781ad6265SDimitry Andric } 133881ad6265SDimitry Andric return Operand; 133981ad6265SDimitry Andric } 134081ad6265SDimitry Andric return Operand; 134181ad6265SDimitry Andric } 134281ad6265SDimitry Andric 134381ad6265SDimitry Andric Constant *llvm::ConstantFoldFPInstOperands(unsigned Opcode, Constant *LHS, 134481ad6265SDimitry Andric Constant *RHS, const DataLayout &DL, 13450fca6ea1SDimitry Andric const Instruction *I, 13460fca6ea1SDimitry Andric bool AllowNonDeterministic) { 134781ad6265SDimitry Andric if (Instruction::isBinaryOp(Opcode)) { 134881ad6265SDimitry Andric // Flush denormal inputs if needed. 134981ad6265SDimitry Andric Constant *Op0 = FlushFPConstant(LHS, I, /* IsOutput */ false); 135006c3fb27SDimitry Andric if (!Op0) 135106c3fb27SDimitry Andric return nullptr; 135281ad6265SDimitry Andric Constant *Op1 = FlushFPConstant(RHS, I, /* IsOutput */ false); 135306c3fb27SDimitry Andric if (!Op1) 135406c3fb27SDimitry Andric return nullptr; 135581ad6265SDimitry Andric 13560fca6ea1SDimitry Andric // If nsz or an algebraic FMF flag is set, the result of the FP operation 13570fca6ea1SDimitry Andric // may change due to future optimization. Don't constant fold them if 13580fca6ea1SDimitry Andric // non-deterministic results are not allowed. 13590fca6ea1SDimitry Andric if (!AllowNonDeterministic) 13600fca6ea1SDimitry Andric if (auto *FP = dyn_cast_or_null<FPMathOperator>(I)) 13610fca6ea1SDimitry Andric if (FP->hasNoSignedZeros() || FP->hasAllowReassoc() || 13620fca6ea1SDimitry Andric FP->hasAllowContract() || FP->hasAllowReciprocal()) 13630fca6ea1SDimitry Andric return nullptr; 13640fca6ea1SDimitry Andric 136581ad6265SDimitry Andric // Calculate constant result. 136681ad6265SDimitry Andric Constant *C = ConstantFoldBinaryOpOperands(Opcode, Op0, Op1, DL); 1367753f127fSDimitry Andric if (!C) 1368753f127fSDimitry Andric return nullptr; 136981ad6265SDimitry Andric 137081ad6265SDimitry Andric // Flush denormal output if needed. 13710fca6ea1SDimitry Andric C = FlushFPConstant(C, I, /* IsOutput */ true); 13720fca6ea1SDimitry Andric if (!C) 13730fca6ea1SDimitry Andric return nullptr; 13740fca6ea1SDimitry Andric 13750fca6ea1SDimitry Andric // The precise NaN value is non-deterministic. 13760fca6ea1SDimitry Andric if (!AllowNonDeterministic && C->isNaN()) 13770fca6ea1SDimitry Andric return nullptr; 13780fca6ea1SDimitry Andric 13790fca6ea1SDimitry Andric return C; 138081ad6265SDimitry Andric } 138181ad6265SDimitry Andric // If instruction lacks a parent/function and the denormal mode cannot be 138281ad6265SDimitry Andric // determined, use the default (IEEE). 138381ad6265SDimitry Andric return ConstantFoldBinaryOpOperands(Opcode, LHS, RHS, DL); 138481ad6265SDimitry Andric } 138581ad6265SDimitry Andric 13860b57cec5SDimitry Andric Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C, 13870b57cec5SDimitry Andric Type *DestTy, const DataLayout &DL) { 13880b57cec5SDimitry Andric assert(Instruction::isCast(Opcode)); 13890b57cec5SDimitry Andric switch (Opcode) { 13900b57cec5SDimitry Andric default: 13910b57cec5SDimitry Andric llvm_unreachable("Missing case"); 13920b57cec5SDimitry Andric case Instruction::PtrToInt: 1393349cc55cSDimitry Andric if (auto *CE = dyn_cast<ConstantExpr>(C)) { 1394349cc55cSDimitry Andric Constant *FoldedValue = nullptr; 13950b57cec5SDimitry Andric // If the input is a inttoptr, eliminate the pair. This requires knowing 13960b57cec5SDimitry Andric // the width of a pointer, so it can't be done in ConstantExpr::getCast. 13970b57cec5SDimitry Andric if (CE->getOpcode() == Instruction::IntToPtr) { 1398349cc55cSDimitry Andric // zext/trunc the inttoptr to pointer size. 13995f757f3fSDimitry Andric FoldedValue = ConstantFoldIntegerCast(CE->getOperand(0), 14005f757f3fSDimitry Andric DL.getIntPtrType(CE->getType()), 14015f757f3fSDimitry Andric /*IsSigned=*/false, DL); 1402349cc55cSDimitry Andric } else if (auto *GEP = dyn_cast<GEPOperator>(CE)) { 1403349cc55cSDimitry Andric // If we have GEP, we can perform the following folds: 1404349cc55cSDimitry Andric // (ptrtoint (gep null, x)) -> x 1405349cc55cSDimitry Andric // (ptrtoint (gep (gep null, x), y) -> x + y, etc. 1406349cc55cSDimitry Andric unsigned BitWidth = DL.getIndexTypeSizeInBits(GEP->getType()); 1407349cc55cSDimitry Andric APInt BaseOffset(BitWidth, 0); 1408349cc55cSDimitry Andric auto *Base = cast<Constant>(GEP->stripAndAccumulateConstantOffsets( 1409349cc55cSDimitry Andric DL, BaseOffset, /*AllowNonInbounds=*/true)); 1410349cc55cSDimitry Andric if (Base->isNullValue()) { 1411349cc55cSDimitry Andric FoldedValue = ConstantInt::get(CE->getContext(), BaseOffset); 141281ad6265SDimitry Andric } else { 141381ad6265SDimitry Andric // ptrtoint (gep i8, Ptr, (sub 0, V)) -> sub (ptrtoint Ptr), V 141481ad6265SDimitry Andric if (GEP->getNumIndices() == 1 && 141581ad6265SDimitry Andric GEP->getSourceElementType()->isIntegerTy(8)) { 141681ad6265SDimitry Andric auto *Ptr = cast<Constant>(GEP->getPointerOperand()); 141781ad6265SDimitry Andric auto *Sub = dyn_cast<ConstantExpr>(GEP->getOperand(1)); 141881ad6265SDimitry Andric Type *IntIdxTy = DL.getIndexType(Ptr->getType()); 141981ad6265SDimitry Andric if (Sub && Sub->getType() == IntIdxTy && 142081ad6265SDimitry Andric Sub->getOpcode() == Instruction::Sub && 142181ad6265SDimitry Andric Sub->getOperand(0)->isNullValue()) 142281ad6265SDimitry Andric FoldedValue = ConstantExpr::getSub( 142381ad6265SDimitry Andric ConstantExpr::getPtrToInt(Ptr, IntIdxTy), Sub->getOperand(1)); 142481ad6265SDimitry Andric } 14250b57cec5SDimitry Andric } 1426349cc55cSDimitry Andric } 1427349cc55cSDimitry Andric if (FoldedValue) { 1428349cc55cSDimitry Andric // Do a zext or trunc to get to the ptrtoint dest size. 14295f757f3fSDimitry Andric return ConstantFoldIntegerCast(FoldedValue, DestTy, /*IsSigned=*/false, 14305f757f3fSDimitry Andric DL); 14310b57cec5SDimitry Andric } 14320b57cec5SDimitry Andric } 14335f757f3fSDimitry Andric break; 14340b57cec5SDimitry Andric case Instruction::IntToPtr: 14350b57cec5SDimitry Andric // If the input is a ptrtoint, turn the pair into a ptr to ptr bitcast if 14360b57cec5SDimitry Andric // the int size is >= the ptr size and the address spaces are the same. 14370b57cec5SDimitry Andric // This requires knowing the width of a pointer, so it can't be done in 14380b57cec5SDimitry Andric // ConstantExpr::getCast. 14390b57cec5SDimitry Andric if (auto *CE = dyn_cast<ConstantExpr>(C)) { 14400b57cec5SDimitry Andric if (CE->getOpcode() == Instruction::PtrToInt) { 14410b57cec5SDimitry Andric Constant *SrcPtr = CE->getOperand(0); 14420b57cec5SDimitry Andric unsigned SrcPtrSize = DL.getPointerTypeSizeInBits(SrcPtr->getType()); 14430b57cec5SDimitry Andric unsigned MidIntSize = CE->getType()->getScalarSizeInBits(); 14440b57cec5SDimitry Andric 14450b57cec5SDimitry Andric if (MidIntSize >= SrcPtrSize) { 14460b57cec5SDimitry Andric unsigned SrcAS = SrcPtr->getType()->getPointerAddressSpace(); 14470b57cec5SDimitry Andric if (SrcAS == DestTy->getPointerAddressSpace()) 14480b57cec5SDimitry Andric return FoldBitCast(CE->getOperand(0), DestTy, DL); 14490b57cec5SDimitry Andric } 14500b57cec5SDimitry Andric } 14510b57cec5SDimitry Andric } 14525f757f3fSDimitry Andric break; 14530b57cec5SDimitry Andric case Instruction::Trunc: 14540b57cec5SDimitry Andric case Instruction::ZExt: 14550b57cec5SDimitry Andric case Instruction::SExt: 14560b57cec5SDimitry Andric case Instruction::FPTrunc: 14570b57cec5SDimitry Andric case Instruction::FPExt: 14580b57cec5SDimitry Andric case Instruction::UIToFP: 14590b57cec5SDimitry Andric case Instruction::SIToFP: 14600b57cec5SDimitry Andric case Instruction::FPToUI: 14610b57cec5SDimitry Andric case Instruction::FPToSI: 14620b57cec5SDimitry Andric case Instruction::AddrSpaceCast: 14635f757f3fSDimitry Andric break; 14640b57cec5SDimitry Andric case Instruction::BitCast: 14650b57cec5SDimitry Andric return FoldBitCast(C, DestTy, DL); 14660b57cec5SDimitry Andric } 14675f757f3fSDimitry Andric 14685f757f3fSDimitry Andric if (ConstantExpr::isDesirableCastOp(Opcode)) 14695f757f3fSDimitry Andric return ConstantExpr::getCast(Opcode, C, DestTy); 14705f757f3fSDimitry Andric return ConstantFoldCastInstruction(Opcode, C, DestTy); 14715f757f3fSDimitry Andric } 14725f757f3fSDimitry Andric 14735f757f3fSDimitry Andric Constant *llvm::ConstantFoldIntegerCast(Constant *C, Type *DestTy, 14745f757f3fSDimitry Andric bool IsSigned, const DataLayout &DL) { 14755f757f3fSDimitry Andric Type *SrcTy = C->getType(); 14765f757f3fSDimitry Andric if (SrcTy == DestTy) 14775f757f3fSDimitry Andric return C; 14785f757f3fSDimitry Andric if (SrcTy->getScalarSizeInBits() > DestTy->getScalarSizeInBits()) 14795f757f3fSDimitry Andric return ConstantFoldCastOperand(Instruction::Trunc, C, DestTy, DL); 14805f757f3fSDimitry Andric if (IsSigned) 14815f757f3fSDimitry Andric return ConstantFoldCastOperand(Instruction::SExt, C, DestTy, DL); 14825f757f3fSDimitry Andric return ConstantFoldCastOperand(Instruction::ZExt, C, DestTy, DL); 14830b57cec5SDimitry Andric } 14840b57cec5SDimitry Andric 14850b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14860b57cec5SDimitry Andric // Constant Folding for Calls 14870b57cec5SDimitry Andric // 14880b57cec5SDimitry Andric 14890b57cec5SDimitry Andric bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) { 14905ffd83dbSDimitry Andric if (Call->isNoBuiltin()) 14910b57cec5SDimitry Andric return false; 149281ad6265SDimitry Andric if (Call->getFunctionType() != F->getFunctionType()) 149381ad6265SDimitry Andric return false; 14940b57cec5SDimitry Andric switch (F->getIntrinsicID()) { 14955ffd83dbSDimitry Andric // Operations that do not operate floating-point numbers and do not depend on 14965ffd83dbSDimitry Andric // FP environment can be folded even in strictfp functions. 14970b57cec5SDimitry Andric case Intrinsic::bswap: 14980b57cec5SDimitry Andric case Intrinsic::ctpop: 14990b57cec5SDimitry Andric case Intrinsic::ctlz: 15000b57cec5SDimitry Andric case Intrinsic::cttz: 15010b57cec5SDimitry Andric case Intrinsic::fshl: 15020b57cec5SDimitry Andric case Intrinsic::fshr: 15030b57cec5SDimitry Andric case Intrinsic::launder_invariant_group: 15040b57cec5SDimitry Andric case Intrinsic::strip_invariant_group: 15050b57cec5SDimitry Andric case Intrinsic::masked_load: 1506e8d8bef9SDimitry Andric case Intrinsic::get_active_lane_mask: 1507e8d8bef9SDimitry Andric case Intrinsic::abs: 1508e8d8bef9SDimitry Andric case Intrinsic::smax: 1509e8d8bef9SDimitry Andric case Intrinsic::smin: 1510e8d8bef9SDimitry Andric case Intrinsic::umax: 1511e8d8bef9SDimitry Andric case Intrinsic::umin: 15120fca6ea1SDimitry Andric case Intrinsic::scmp: 15130fca6ea1SDimitry Andric case Intrinsic::ucmp: 15140b57cec5SDimitry Andric case Intrinsic::sadd_with_overflow: 15150b57cec5SDimitry Andric case Intrinsic::uadd_with_overflow: 15160b57cec5SDimitry Andric case Intrinsic::ssub_with_overflow: 15170b57cec5SDimitry Andric case Intrinsic::usub_with_overflow: 15180b57cec5SDimitry Andric case Intrinsic::smul_with_overflow: 15190b57cec5SDimitry Andric case Intrinsic::umul_with_overflow: 15200b57cec5SDimitry Andric case Intrinsic::sadd_sat: 15210b57cec5SDimitry Andric case Intrinsic::uadd_sat: 15220b57cec5SDimitry Andric case Intrinsic::ssub_sat: 15230b57cec5SDimitry Andric case Intrinsic::usub_sat: 15240b57cec5SDimitry Andric case Intrinsic::smul_fix: 15250b57cec5SDimitry Andric case Intrinsic::smul_fix_sat: 15265ffd83dbSDimitry Andric case Intrinsic::bitreverse: 15275ffd83dbSDimitry Andric case Intrinsic::is_constant: 1528e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_add: 1529e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_mul: 1530e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_and: 1531e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_or: 1532e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_xor: 1533e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_smin: 1534e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_smax: 1535e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_umin: 1536e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_umax: 1537e8d8bef9SDimitry Andric // Target intrinsics 1538fe6060f1SDimitry Andric case Intrinsic::amdgcn_perm: 15395f757f3fSDimitry Andric case Intrinsic::amdgcn_wave_reduce_umin: 15405f757f3fSDimitry Andric case Intrinsic::amdgcn_wave_reduce_umax: 15415f757f3fSDimitry Andric case Intrinsic::amdgcn_s_wqm: 15425f757f3fSDimitry Andric case Intrinsic::amdgcn_s_quadmask: 15435f757f3fSDimitry Andric case Intrinsic::amdgcn_s_bitreplicate: 1544e8d8bef9SDimitry Andric case Intrinsic::arm_mve_vctp8: 1545e8d8bef9SDimitry Andric case Intrinsic::arm_mve_vctp16: 1546e8d8bef9SDimitry Andric case Intrinsic::arm_mve_vctp32: 1547e8d8bef9SDimitry Andric case Intrinsic::arm_mve_vctp64: 1548fe6060f1SDimitry Andric case Intrinsic::aarch64_sve_convert_from_svbool: 1549e8d8bef9SDimitry Andric // WebAssembly float semantics are always known 1550e8d8bef9SDimitry Andric case Intrinsic::wasm_trunc_signed: 1551e8d8bef9SDimitry Andric case Intrinsic::wasm_trunc_unsigned: 15525ffd83dbSDimitry Andric return true; 15535ffd83dbSDimitry Andric 15545ffd83dbSDimitry Andric // Floating point operations cannot be folded in strictfp functions in 15555ffd83dbSDimitry Andric // general case. They can be folded if FP environment is known to compiler. 15565ffd83dbSDimitry Andric case Intrinsic::minnum: 15575ffd83dbSDimitry Andric case Intrinsic::maxnum: 15585ffd83dbSDimitry Andric case Intrinsic::minimum: 15595ffd83dbSDimitry Andric case Intrinsic::maximum: 15605ffd83dbSDimitry Andric case Intrinsic::log: 15615ffd83dbSDimitry Andric case Intrinsic::log2: 15625ffd83dbSDimitry Andric case Intrinsic::log10: 15635ffd83dbSDimitry Andric case Intrinsic::exp: 15645ffd83dbSDimitry Andric case Intrinsic::exp2: 15655f757f3fSDimitry Andric case Intrinsic::exp10: 15665ffd83dbSDimitry Andric case Intrinsic::sqrt: 15675ffd83dbSDimitry Andric case Intrinsic::sin: 15685ffd83dbSDimitry Andric case Intrinsic::cos: 15695ffd83dbSDimitry Andric case Intrinsic::pow: 15705ffd83dbSDimitry Andric case Intrinsic::powi: 15715f757f3fSDimitry Andric case Intrinsic::ldexp: 15725ffd83dbSDimitry Andric case Intrinsic::fma: 15735ffd83dbSDimitry Andric case Intrinsic::fmuladd: 157406c3fb27SDimitry Andric case Intrinsic::frexp: 1575e8d8bef9SDimitry Andric case Intrinsic::fptoui_sat: 1576e8d8bef9SDimitry Andric case Intrinsic::fptosi_sat: 15770b57cec5SDimitry Andric case Intrinsic::convert_from_fp16: 15780b57cec5SDimitry Andric case Intrinsic::convert_to_fp16: 15795ffd83dbSDimitry Andric case Intrinsic::amdgcn_cos: 15805ffd83dbSDimitry Andric case Intrinsic::amdgcn_cubeid: 15815ffd83dbSDimitry Andric case Intrinsic::amdgcn_cubema: 15825ffd83dbSDimitry Andric case Intrinsic::amdgcn_cubesc: 15835ffd83dbSDimitry Andric case Intrinsic::amdgcn_cubetc: 15845ffd83dbSDimitry Andric case Intrinsic::amdgcn_fmul_legacy: 1585e8d8bef9SDimitry Andric case Intrinsic::amdgcn_fma_legacy: 15865ffd83dbSDimitry Andric case Intrinsic::amdgcn_fract: 15875ffd83dbSDimitry Andric case Intrinsic::amdgcn_sin: 15885ffd83dbSDimitry Andric // The intrinsics below depend on rounding mode in MXCSR. 15890b57cec5SDimitry Andric case Intrinsic::x86_sse_cvtss2si: 15900b57cec5SDimitry Andric case Intrinsic::x86_sse_cvtss2si64: 15910b57cec5SDimitry Andric case Intrinsic::x86_sse_cvttss2si: 15920b57cec5SDimitry Andric case Intrinsic::x86_sse_cvttss2si64: 15930b57cec5SDimitry Andric case Intrinsic::x86_sse2_cvtsd2si: 15940b57cec5SDimitry Andric case Intrinsic::x86_sse2_cvtsd2si64: 15950b57cec5SDimitry Andric case Intrinsic::x86_sse2_cvttsd2si: 15960b57cec5SDimitry Andric case Intrinsic::x86_sse2_cvttsd2si64: 15970b57cec5SDimitry Andric case Intrinsic::x86_avx512_vcvtss2si32: 15980b57cec5SDimitry Andric case Intrinsic::x86_avx512_vcvtss2si64: 15990b57cec5SDimitry Andric case Intrinsic::x86_avx512_cvttss2si: 16000b57cec5SDimitry Andric case Intrinsic::x86_avx512_cvttss2si64: 16010b57cec5SDimitry Andric case Intrinsic::x86_avx512_vcvtsd2si32: 16020b57cec5SDimitry Andric case Intrinsic::x86_avx512_vcvtsd2si64: 16030b57cec5SDimitry Andric case Intrinsic::x86_avx512_cvttsd2si: 16040b57cec5SDimitry Andric case Intrinsic::x86_avx512_cvttsd2si64: 16050b57cec5SDimitry Andric case Intrinsic::x86_avx512_vcvtss2usi32: 16060b57cec5SDimitry Andric case Intrinsic::x86_avx512_vcvtss2usi64: 16070b57cec5SDimitry Andric case Intrinsic::x86_avx512_cvttss2usi: 16080b57cec5SDimitry Andric case Intrinsic::x86_avx512_cvttss2usi64: 16090b57cec5SDimitry Andric case Intrinsic::x86_avx512_vcvtsd2usi32: 16100b57cec5SDimitry Andric case Intrinsic::x86_avx512_vcvtsd2usi64: 16110b57cec5SDimitry Andric case Intrinsic::x86_avx512_cvttsd2usi: 16120b57cec5SDimitry Andric case Intrinsic::x86_avx512_cvttsd2usi64: 16135ffd83dbSDimitry Andric return !Call->isStrictFP(); 16145ffd83dbSDimitry Andric 16155ffd83dbSDimitry Andric // Sign operations are actually bitwise operations, they do not raise 16165ffd83dbSDimitry Andric // exceptions even for SNANs. 16175ffd83dbSDimitry Andric case Intrinsic::fabs: 16185ffd83dbSDimitry Andric case Intrinsic::copysign: 1619bdd1243dSDimitry Andric case Intrinsic::is_fpclass: 16205ffd83dbSDimitry Andric // Non-constrained variants of rounding operations means default FP 16215ffd83dbSDimitry Andric // environment, they can be folded in any case. 16225ffd83dbSDimitry Andric case Intrinsic::ceil: 16235ffd83dbSDimitry Andric case Intrinsic::floor: 16245ffd83dbSDimitry Andric case Intrinsic::round: 16255ffd83dbSDimitry Andric case Intrinsic::roundeven: 16265ffd83dbSDimitry Andric case Intrinsic::trunc: 16275ffd83dbSDimitry Andric case Intrinsic::nearbyint: 16285ffd83dbSDimitry Andric case Intrinsic::rint: 1629bdd1243dSDimitry Andric case Intrinsic::canonicalize: 16305ffd83dbSDimitry Andric // Constrained intrinsics can be folded if FP environment is known 16315ffd83dbSDimitry Andric // to compiler. 1632fe6060f1SDimitry Andric case Intrinsic::experimental_constrained_fma: 1633fe6060f1SDimitry Andric case Intrinsic::experimental_constrained_fmuladd: 1634fe6060f1SDimitry Andric case Intrinsic::experimental_constrained_fadd: 1635fe6060f1SDimitry Andric case Intrinsic::experimental_constrained_fsub: 1636fe6060f1SDimitry Andric case Intrinsic::experimental_constrained_fmul: 1637fe6060f1SDimitry Andric case Intrinsic::experimental_constrained_fdiv: 1638fe6060f1SDimitry Andric case Intrinsic::experimental_constrained_frem: 16395ffd83dbSDimitry Andric case Intrinsic::experimental_constrained_ceil: 16405ffd83dbSDimitry Andric case Intrinsic::experimental_constrained_floor: 16415ffd83dbSDimitry Andric case Intrinsic::experimental_constrained_round: 16425ffd83dbSDimitry Andric case Intrinsic::experimental_constrained_roundeven: 16435ffd83dbSDimitry Andric case Intrinsic::experimental_constrained_trunc: 16445ffd83dbSDimitry Andric case Intrinsic::experimental_constrained_nearbyint: 16455ffd83dbSDimitry Andric case Intrinsic::experimental_constrained_rint: 164681ad6265SDimitry Andric case Intrinsic::experimental_constrained_fcmp: 164781ad6265SDimitry Andric case Intrinsic::experimental_constrained_fcmps: 16480b57cec5SDimitry Andric return true; 16490b57cec5SDimitry Andric default: 16500b57cec5SDimitry Andric return false; 16510b57cec5SDimitry Andric case Intrinsic::not_intrinsic: break; 16520b57cec5SDimitry Andric } 16530b57cec5SDimitry Andric 16545ffd83dbSDimitry Andric if (!F->hasName() || Call->isStrictFP()) 16550b57cec5SDimitry Andric return false; 16560b57cec5SDimitry Andric 16570b57cec5SDimitry Andric // In these cases, the check of the length is required. We don't want to 16580b57cec5SDimitry Andric // return true for a name like "cos\0blah" which strcmp would return equal to 16590b57cec5SDimitry Andric // "cos", but has length 8. 16608bcb0991SDimitry Andric StringRef Name = F->getName(); 16610b57cec5SDimitry Andric switch (Name[0]) { 16620b57cec5SDimitry Andric default: 16630b57cec5SDimitry Andric return false; 16640b57cec5SDimitry Andric case 'a': 16658bcb0991SDimitry Andric return Name == "acos" || Name == "acosf" || 16668bcb0991SDimitry Andric Name == "asin" || Name == "asinf" || 16678bcb0991SDimitry Andric Name == "atan" || Name == "atanf" || 16688bcb0991SDimitry Andric Name == "atan2" || Name == "atan2f"; 16690b57cec5SDimitry Andric case 'c': 16708bcb0991SDimitry Andric return Name == "ceil" || Name == "ceilf" || 16718bcb0991SDimitry Andric Name == "cos" || Name == "cosf" || 16728bcb0991SDimitry Andric Name == "cosh" || Name == "coshf"; 16730b57cec5SDimitry Andric case 'e': 16748bcb0991SDimitry Andric return Name == "exp" || Name == "expf" || 16758bcb0991SDimitry Andric Name == "exp2" || Name == "exp2f"; 16760b57cec5SDimitry Andric case 'f': 16778bcb0991SDimitry Andric return Name == "fabs" || Name == "fabsf" || 16788bcb0991SDimitry Andric Name == "floor" || Name == "floorf" || 16798bcb0991SDimitry Andric Name == "fmod" || Name == "fmodf"; 16800b57cec5SDimitry Andric case 'l': 16810fca6ea1SDimitry Andric return Name == "log" || Name == "logf" || Name == "log2" || 16820fca6ea1SDimitry Andric Name == "log2f" || Name == "log10" || Name == "log10f" || 16830fca6ea1SDimitry Andric Name == "logl"; 16848bcb0991SDimitry Andric case 'n': 16858bcb0991SDimitry Andric return Name == "nearbyint" || Name == "nearbyintf"; 16860b57cec5SDimitry Andric case 'p': 16870b57cec5SDimitry Andric return Name == "pow" || Name == "powf"; 16880b57cec5SDimitry Andric case 'r': 16895ffd83dbSDimitry Andric return Name == "remainder" || Name == "remainderf" || 16905ffd83dbSDimitry Andric Name == "rint" || Name == "rintf" || 16918bcb0991SDimitry Andric Name == "round" || Name == "roundf"; 16920b57cec5SDimitry Andric case 's': 16938bcb0991SDimitry Andric return Name == "sin" || Name == "sinf" || 16948bcb0991SDimitry Andric Name == "sinh" || Name == "sinhf" || 16958bcb0991SDimitry Andric Name == "sqrt" || Name == "sqrtf"; 16960b57cec5SDimitry Andric case 't': 16978bcb0991SDimitry Andric return Name == "tan" || Name == "tanf" || 16988bcb0991SDimitry Andric Name == "tanh" || Name == "tanhf" || 16998bcb0991SDimitry Andric Name == "trunc" || Name == "truncf"; 17000b57cec5SDimitry Andric case '_': 17010b57cec5SDimitry Andric // Check for various function names that get used for the math functions 17020b57cec5SDimitry Andric // when the header files are preprocessed with the macro 17030b57cec5SDimitry Andric // __FINITE_MATH_ONLY__ enabled. 17040b57cec5SDimitry Andric // The '12' here is the length of the shortest name that can match. 17050b57cec5SDimitry Andric // We need to check the size before looking at Name[1] and Name[2] 17060b57cec5SDimitry Andric // so we may as well check a limit that will eliminate mismatches. 17070b57cec5SDimitry Andric if (Name.size() < 12 || Name[1] != '_') 17080b57cec5SDimitry Andric return false; 17090b57cec5SDimitry Andric switch (Name[2]) { 17100b57cec5SDimitry Andric default: 17110b57cec5SDimitry Andric return false; 17120b57cec5SDimitry Andric case 'a': 17130b57cec5SDimitry Andric return Name == "__acos_finite" || Name == "__acosf_finite" || 17140b57cec5SDimitry Andric Name == "__asin_finite" || Name == "__asinf_finite" || 17150b57cec5SDimitry Andric Name == "__atan2_finite" || Name == "__atan2f_finite"; 17160b57cec5SDimitry Andric case 'c': 17170b57cec5SDimitry Andric return Name == "__cosh_finite" || Name == "__coshf_finite"; 17180b57cec5SDimitry Andric case 'e': 17190b57cec5SDimitry Andric return Name == "__exp_finite" || Name == "__expf_finite" || 17200b57cec5SDimitry Andric Name == "__exp2_finite" || Name == "__exp2f_finite"; 17210b57cec5SDimitry Andric case 'l': 17220b57cec5SDimitry Andric return Name == "__log_finite" || Name == "__logf_finite" || 17230b57cec5SDimitry Andric Name == "__log10_finite" || Name == "__log10f_finite"; 17240b57cec5SDimitry Andric case 'p': 17250b57cec5SDimitry Andric return Name == "__pow_finite" || Name == "__powf_finite"; 17260b57cec5SDimitry Andric case 's': 17270b57cec5SDimitry Andric return Name == "__sinh_finite" || Name == "__sinhf_finite"; 17280b57cec5SDimitry Andric } 17290b57cec5SDimitry Andric } 17300b57cec5SDimitry Andric } 17310b57cec5SDimitry Andric 17320b57cec5SDimitry Andric namespace { 17330b57cec5SDimitry Andric 17340b57cec5SDimitry Andric Constant *GetConstantFoldFPValue(double V, Type *Ty) { 17350b57cec5SDimitry Andric if (Ty->isHalfTy() || Ty->isFloatTy()) { 17360b57cec5SDimitry Andric APFloat APF(V); 17370b57cec5SDimitry Andric bool unused; 17380b57cec5SDimitry Andric APF.convert(Ty->getFltSemantics(), APFloat::rmNearestTiesToEven, &unused); 17390b57cec5SDimitry Andric return ConstantFP::get(Ty->getContext(), APF); 17400b57cec5SDimitry Andric } 17410b57cec5SDimitry Andric if (Ty->isDoubleTy()) 17420b57cec5SDimitry Andric return ConstantFP::get(Ty->getContext(), APFloat(V)); 17430b57cec5SDimitry Andric llvm_unreachable("Can only constant fold half/float/double"); 17440b57cec5SDimitry Andric } 17450b57cec5SDimitry Andric 17460fca6ea1SDimitry Andric #if defined(HAS_IEE754_FLOAT128) && defined(HAS_LOGF128) 17470fca6ea1SDimitry Andric Constant *GetConstantFoldFPValue128(float128 V, Type *Ty) { 17480fca6ea1SDimitry Andric if (Ty->isFP128Ty()) 17490fca6ea1SDimitry Andric return ConstantFP::get(Ty, V); 17500fca6ea1SDimitry Andric llvm_unreachable("Can only constant fold fp128"); 17510fca6ea1SDimitry Andric } 17520fca6ea1SDimitry Andric #endif 17530fca6ea1SDimitry Andric 17540b57cec5SDimitry Andric /// Clear the floating-point exception state. 17550b57cec5SDimitry Andric inline void llvm_fenv_clearexcept() { 17560b57cec5SDimitry Andric #if defined(HAVE_FENV_H) && HAVE_DECL_FE_ALL_EXCEPT 17570b57cec5SDimitry Andric feclearexcept(FE_ALL_EXCEPT); 17580b57cec5SDimitry Andric #endif 17590b57cec5SDimitry Andric errno = 0; 17600b57cec5SDimitry Andric } 17610b57cec5SDimitry Andric 17620b57cec5SDimitry Andric /// Test if a floating-point exception was raised. 17630b57cec5SDimitry Andric inline bool llvm_fenv_testexcept() { 17640b57cec5SDimitry Andric int errno_val = errno; 17650b57cec5SDimitry Andric if (errno_val == ERANGE || errno_val == EDOM) 17660b57cec5SDimitry Andric return true; 17670b57cec5SDimitry Andric #if defined(HAVE_FENV_H) && HAVE_DECL_FE_ALL_EXCEPT && HAVE_DECL_FE_INEXACT 17680b57cec5SDimitry Andric if (fetestexcept(FE_ALL_EXCEPT & ~FE_INEXACT)) 17690b57cec5SDimitry Andric return true; 17700b57cec5SDimitry Andric #endif 17710b57cec5SDimitry Andric return false; 17720b57cec5SDimitry Andric } 17730b57cec5SDimitry Andric 1774fe6060f1SDimitry Andric Constant *ConstantFoldFP(double (*NativeFP)(double), const APFloat &V, 1775fe6060f1SDimitry Andric Type *Ty) { 17760b57cec5SDimitry Andric llvm_fenv_clearexcept(); 1777fe6060f1SDimitry Andric double Result = NativeFP(V.convertToDouble()); 17780b57cec5SDimitry Andric if (llvm_fenv_testexcept()) { 17790b57cec5SDimitry Andric llvm_fenv_clearexcept(); 17800b57cec5SDimitry Andric return nullptr; 17810b57cec5SDimitry Andric } 17820b57cec5SDimitry Andric 1783fe6060f1SDimitry Andric return GetConstantFoldFPValue(Result, Ty); 17840b57cec5SDimitry Andric } 17850b57cec5SDimitry Andric 17860fca6ea1SDimitry Andric #if defined(HAS_IEE754_FLOAT128) && defined(HAS_LOGF128) 1787*d686ce93SDimitry Andric Constant *ConstantFoldFP128(float128 (*NativeFP)(float128), const APFloat &V, 1788*d686ce93SDimitry Andric Type *Ty) { 17890fca6ea1SDimitry Andric llvm_fenv_clearexcept(); 17900fca6ea1SDimitry Andric float128 Result = NativeFP(V.convertToQuad()); 17910fca6ea1SDimitry Andric if (llvm_fenv_testexcept()) { 17920fca6ea1SDimitry Andric llvm_fenv_clearexcept(); 17930fca6ea1SDimitry Andric return nullptr; 17940fca6ea1SDimitry Andric } 17950fca6ea1SDimitry Andric 17960fca6ea1SDimitry Andric return GetConstantFoldFPValue128(Result, Ty); 17970fca6ea1SDimitry Andric } 17980fca6ea1SDimitry Andric #endif 17990fca6ea1SDimitry Andric 1800fe6060f1SDimitry Andric Constant *ConstantFoldBinaryFP(double (*NativeFP)(double, double), 1801fe6060f1SDimitry Andric const APFloat &V, const APFloat &W, Type *Ty) { 18020b57cec5SDimitry Andric llvm_fenv_clearexcept(); 1803fe6060f1SDimitry Andric double Result = NativeFP(V.convertToDouble(), W.convertToDouble()); 18040b57cec5SDimitry Andric if (llvm_fenv_testexcept()) { 18050b57cec5SDimitry Andric llvm_fenv_clearexcept(); 18060b57cec5SDimitry Andric return nullptr; 18070b57cec5SDimitry Andric } 18080b57cec5SDimitry Andric 1809fe6060f1SDimitry Andric return GetConstantFoldFPValue(Result, Ty); 18100b57cec5SDimitry Andric } 18110b57cec5SDimitry Andric 1812fe6060f1SDimitry Andric Constant *constantFoldVectorReduce(Intrinsic::ID IID, Constant *Op) { 18135ffd83dbSDimitry Andric FixedVectorType *VT = dyn_cast<FixedVectorType>(Op->getType()); 18145ffd83dbSDimitry Andric if (!VT) 18155ffd83dbSDimitry Andric return nullptr; 18165ffd83dbSDimitry Andric 1817fe6060f1SDimitry Andric // This isn't strictly necessary, but handle the special/common case of zero: 1818fe6060f1SDimitry Andric // all integer reductions of a zero input produce zero. 1819fe6060f1SDimitry Andric if (isa<ConstantAggregateZero>(Op)) 1820fe6060f1SDimitry Andric return ConstantInt::get(VT->getElementType(), 0); 1821fe6060f1SDimitry Andric 1822fe6060f1SDimitry Andric // This is the same as the underlying binops - poison propagates. 1823fe6060f1SDimitry Andric if (isa<PoisonValue>(Op) || Op->containsPoisonElement()) 1824fe6060f1SDimitry Andric return PoisonValue::get(VT->getElementType()); 1825fe6060f1SDimitry Andric 1826fe6060f1SDimitry Andric // TODO: Handle undef. 1827fe6060f1SDimitry Andric if (!isa<ConstantVector>(Op) && !isa<ConstantDataVector>(Op)) 18285ffd83dbSDimitry Andric return nullptr; 1829fe6060f1SDimitry Andric 1830fe6060f1SDimitry Andric auto *EltC = dyn_cast<ConstantInt>(Op->getAggregateElement(0U)); 1831fe6060f1SDimitry Andric if (!EltC) 1832fe6060f1SDimitry Andric return nullptr; 1833fe6060f1SDimitry Andric 1834fe6060f1SDimitry Andric APInt Acc = EltC->getValue(); 1835fe6060f1SDimitry Andric for (unsigned I = 1, E = VT->getNumElements(); I != E; I++) { 1836fe6060f1SDimitry Andric if (!(EltC = dyn_cast<ConstantInt>(Op->getAggregateElement(I)))) 1837fe6060f1SDimitry Andric return nullptr; 1838fe6060f1SDimitry Andric const APInt &X = EltC->getValue(); 18395ffd83dbSDimitry Andric switch (IID) { 1840e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_add: 18415ffd83dbSDimitry Andric Acc = Acc + X; 18425ffd83dbSDimitry Andric break; 1843e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_mul: 18445ffd83dbSDimitry Andric Acc = Acc * X; 18455ffd83dbSDimitry Andric break; 1846e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_and: 18475ffd83dbSDimitry Andric Acc = Acc & X; 18485ffd83dbSDimitry Andric break; 1849e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_or: 18505ffd83dbSDimitry Andric Acc = Acc | X; 18515ffd83dbSDimitry Andric break; 1852e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_xor: 18535ffd83dbSDimitry Andric Acc = Acc ^ X; 18545ffd83dbSDimitry Andric break; 1855e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_smin: 18565ffd83dbSDimitry Andric Acc = APIntOps::smin(Acc, X); 18575ffd83dbSDimitry Andric break; 1858e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_smax: 18595ffd83dbSDimitry Andric Acc = APIntOps::smax(Acc, X); 18605ffd83dbSDimitry Andric break; 1861e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_umin: 18625ffd83dbSDimitry Andric Acc = APIntOps::umin(Acc, X); 18635ffd83dbSDimitry Andric break; 1864e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_umax: 18655ffd83dbSDimitry Andric Acc = APIntOps::umax(Acc, X); 18665ffd83dbSDimitry Andric break; 18675ffd83dbSDimitry Andric } 18685ffd83dbSDimitry Andric } 18695ffd83dbSDimitry Andric 18705ffd83dbSDimitry Andric return ConstantInt::get(Op->getContext(), Acc); 18715ffd83dbSDimitry Andric } 18725ffd83dbSDimitry Andric 18730b57cec5SDimitry Andric /// Attempt to fold an SSE floating point to integer conversion of a constant 18740b57cec5SDimitry Andric /// floating point. If roundTowardZero is false, the default IEEE rounding is 18750b57cec5SDimitry Andric /// used (toward nearest, ties to even). This matches the behavior of the 18760b57cec5SDimitry Andric /// non-truncating SSE instructions in the default rounding mode. The desired 18770b57cec5SDimitry Andric /// integer type Ty is used to select how many bits are available for the 18780b57cec5SDimitry Andric /// result. Returns null if the conversion cannot be performed, otherwise 18790b57cec5SDimitry Andric /// returns the Constant value resulting from the conversion. 18800b57cec5SDimitry Andric Constant *ConstantFoldSSEConvertToInt(const APFloat &Val, bool roundTowardZero, 18810b57cec5SDimitry Andric Type *Ty, bool IsSigned) { 18820b57cec5SDimitry Andric // All of these conversion intrinsics form an integer of at most 64bits. 18830b57cec5SDimitry Andric unsigned ResultWidth = Ty->getIntegerBitWidth(); 18840b57cec5SDimitry Andric assert(ResultWidth <= 64 && 18850b57cec5SDimitry Andric "Can only constant fold conversions to 64 and 32 bit ints"); 18860b57cec5SDimitry Andric 18870b57cec5SDimitry Andric uint64_t UIntVal; 18880b57cec5SDimitry Andric bool isExact = false; 18890b57cec5SDimitry Andric APFloat::roundingMode mode = roundTowardZero? APFloat::rmTowardZero 18900b57cec5SDimitry Andric : APFloat::rmNearestTiesToEven; 18910b57cec5SDimitry Andric APFloat::opStatus status = 1892bdd1243dSDimitry Andric Val.convertToInteger(MutableArrayRef(UIntVal), ResultWidth, 18930b57cec5SDimitry Andric IsSigned, mode, &isExact); 18940b57cec5SDimitry Andric if (status != APFloat::opOK && 18950b57cec5SDimitry Andric (!roundTowardZero || status != APFloat::opInexact)) 18960b57cec5SDimitry Andric return nullptr; 18970b57cec5SDimitry Andric return ConstantInt::get(Ty, UIntVal, IsSigned); 18980b57cec5SDimitry Andric } 18990b57cec5SDimitry Andric 19000b57cec5SDimitry Andric double getValueAsDouble(ConstantFP *Op) { 19010b57cec5SDimitry Andric Type *Ty = Op->getType(); 19020b57cec5SDimitry Andric 1903fe6060f1SDimitry Andric if (Ty->isBFloatTy() || Ty->isHalfTy() || Ty->isFloatTy() || Ty->isDoubleTy()) 19040b57cec5SDimitry Andric return Op->getValueAPF().convertToDouble(); 19050b57cec5SDimitry Andric 19060b57cec5SDimitry Andric bool unused; 19070b57cec5SDimitry Andric APFloat APF = Op->getValueAPF(); 19080b57cec5SDimitry Andric APF.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &unused); 19090b57cec5SDimitry Andric return APF.convertToDouble(); 19100b57cec5SDimitry Andric } 19110b57cec5SDimitry Andric 19120b57cec5SDimitry Andric static bool getConstIntOrUndef(Value *Op, const APInt *&C) { 19130b57cec5SDimitry Andric if (auto *CI = dyn_cast<ConstantInt>(Op)) { 19140b57cec5SDimitry Andric C = &CI->getValue(); 19150b57cec5SDimitry Andric return true; 19160b57cec5SDimitry Andric } 19170b57cec5SDimitry Andric if (isa<UndefValue>(Op)) { 19180b57cec5SDimitry Andric C = nullptr; 19190b57cec5SDimitry Andric return true; 19200b57cec5SDimitry Andric } 19210b57cec5SDimitry Andric return false; 19220b57cec5SDimitry Andric } 19230b57cec5SDimitry Andric 1924fe6060f1SDimitry Andric /// Checks if the given intrinsic call, which evaluates to constant, is allowed 1925fe6060f1SDimitry Andric /// to be folded. 1926fe6060f1SDimitry Andric /// 1927fe6060f1SDimitry Andric /// \param CI Constrained intrinsic call. 1928fe6060f1SDimitry Andric /// \param St Exception flags raised during constant evaluation. 1929fe6060f1SDimitry Andric static bool mayFoldConstrained(ConstrainedFPIntrinsic *CI, 1930fe6060f1SDimitry Andric APFloat::opStatus St) { 1931bdd1243dSDimitry Andric std::optional<RoundingMode> ORM = CI->getRoundingMode(); 1932bdd1243dSDimitry Andric std::optional<fp::ExceptionBehavior> EB = CI->getExceptionBehavior(); 1933fe6060f1SDimitry Andric 1934fe6060f1SDimitry Andric // If the operation does not change exception status flags, it is safe 1935fe6060f1SDimitry Andric // to fold. 19360eae32dcSDimitry Andric if (St == APFloat::opStatus::opOK) 1937fe6060f1SDimitry Andric return true; 1938fe6060f1SDimitry Andric 1939fe6060f1SDimitry Andric // If evaluation raised FP exception, the result can depend on rounding 1940fe6060f1SDimitry Andric // mode. If the latter is unknown, folding is not possible. 194181ad6265SDimitry Andric if (ORM && *ORM == RoundingMode::Dynamic) 1942fe6060f1SDimitry Andric return false; 1943fe6060f1SDimitry Andric 1944fe6060f1SDimitry Andric // If FP exceptions are ignored, fold the call, even if such exception is 1945fe6060f1SDimitry Andric // raised. 194681ad6265SDimitry Andric if (EB && *EB != fp::ExceptionBehavior::ebStrict) 1947fe6060f1SDimitry Andric return true; 1948fe6060f1SDimitry Andric 1949fe6060f1SDimitry Andric // Leave the calculation for runtime so that exception flags be correctly set 1950fe6060f1SDimitry Andric // in hardware. 1951fe6060f1SDimitry Andric return false; 1952fe6060f1SDimitry Andric } 1953fe6060f1SDimitry Andric 1954fe6060f1SDimitry Andric /// Returns the rounding mode that should be used for constant evaluation. 1955fe6060f1SDimitry Andric static RoundingMode 1956fe6060f1SDimitry Andric getEvaluationRoundingMode(const ConstrainedFPIntrinsic *CI) { 1957bdd1243dSDimitry Andric std::optional<RoundingMode> ORM = CI->getRoundingMode(); 1958fe6060f1SDimitry Andric if (!ORM || *ORM == RoundingMode::Dynamic) 1959fe6060f1SDimitry Andric // Even if the rounding mode is unknown, try evaluating the operation. 1960fe6060f1SDimitry Andric // If it does not raise inexact exception, rounding was not applied, 1961fe6060f1SDimitry Andric // so the result is exact and does not depend on rounding mode. Whether 1962fe6060f1SDimitry Andric // other FP exceptions are raised, it does not depend on rounding mode. 1963fe6060f1SDimitry Andric return RoundingMode::NearestTiesToEven; 1964fe6060f1SDimitry Andric return *ORM; 1965fe6060f1SDimitry Andric } 1966fe6060f1SDimitry Andric 1967bdd1243dSDimitry Andric /// Try to constant fold llvm.canonicalize for the given caller and value. 1968bdd1243dSDimitry Andric static Constant *constantFoldCanonicalize(const Type *Ty, const CallBase *CI, 1969bdd1243dSDimitry Andric const APFloat &Src) { 1970bdd1243dSDimitry Andric // Zero, positive and negative, is always OK to fold. 1971bdd1243dSDimitry Andric if (Src.isZero()) { 1972bdd1243dSDimitry Andric // Get a fresh 0, since ppc_fp128 does have non-canonical zeros. 1973bdd1243dSDimitry Andric return ConstantFP::get( 1974bdd1243dSDimitry Andric CI->getContext(), 1975bdd1243dSDimitry Andric APFloat::getZero(Src.getSemantics(), Src.isNegative())); 1976bdd1243dSDimitry Andric } 1977bdd1243dSDimitry Andric 1978bdd1243dSDimitry Andric if (!Ty->isIEEELikeFPTy()) 1979bdd1243dSDimitry Andric return nullptr; 1980bdd1243dSDimitry Andric 1981bdd1243dSDimitry Andric // Zero is always canonical and the sign must be preserved. 1982bdd1243dSDimitry Andric // 1983bdd1243dSDimitry Andric // Denorms and nans may have special encodings, but it should be OK to fold a 1984bdd1243dSDimitry Andric // totally average number. 1985bdd1243dSDimitry Andric if (Src.isNormal() || Src.isInfinity()) 1986bdd1243dSDimitry Andric return ConstantFP::get(CI->getContext(), Src); 1987bdd1243dSDimitry Andric 1988bdd1243dSDimitry Andric if (Src.isDenormal() && CI->getParent() && CI->getFunction()) { 1989bdd1243dSDimitry Andric DenormalMode DenormMode = 1990bdd1243dSDimitry Andric CI->getFunction()->getDenormalMode(Src.getSemantics()); 199106c3fb27SDimitry Andric 1992bdd1243dSDimitry Andric if (DenormMode == DenormalMode::getIEEE()) 199306c3fb27SDimitry Andric return ConstantFP::get(CI->getContext(), Src); 199406c3fb27SDimitry Andric 199506c3fb27SDimitry Andric if (DenormMode.Input == DenormalMode::Dynamic) 199606c3fb27SDimitry Andric return nullptr; 199706c3fb27SDimitry Andric 199806c3fb27SDimitry Andric // If we know if either input or output is flushed, we can fold. 199906c3fb27SDimitry Andric if ((DenormMode.Input == DenormalMode::Dynamic && 200006c3fb27SDimitry Andric DenormMode.Output == DenormalMode::IEEE) || 200106c3fb27SDimitry Andric (DenormMode.Input == DenormalMode::IEEE && 200206c3fb27SDimitry Andric DenormMode.Output == DenormalMode::Dynamic)) 2003bdd1243dSDimitry Andric return nullptr; 2004bdd1243dSDimitry Andric 2005bdd1243dSDimitry Andric bool IsPositive = 2006bdd1243dSDimitry Andric (!Src.isNegative() || DenormMode.Input == DenormalMode::PositiveZero || 2007bdd1243dSDimitry Andric (DenormMode.Output == DenormalMode::PositiveZero && 2008bdd1243dSDimitry Andric DenormMode.Input == DenormalMode::IEEE)); 200906c3fb27SDimitry Andric 2010bdd1243dSDimitry Andric return ConstantFP::get(CI->getContext(), 2011bdd1243dSDimitry Andric APFloat::getZero(Src.getSemantics(), !IsPositive)); 2012bdd1243dSDimitry Andric } 2013bdd1243dSDimitry Andric 2014bdd1243dSDimitry Andric return nullptr; 2015bdd1243dSDimitry Andric } 2016bdd1243dSDimitry Andric 20170b57cec5SDimitry Andric static Constant *ConstantFoldScalarCall1(StringRef Name, 20180b57cec5SDimitry Andric Intrinsic::ID IntrinsicID, 20190b57cec5SDimitry Andric Type *Ty, 20200b57cec5SDimitry Andric ArrayRef<Constant *> Operands, 20210b57cec5SDimitry Andric const TargetLibraryInfo *TLI, 20220b57cec5SDimitry Andric const CallBase *Call) { 20230b57cec5SDimitry Andric assert(Operands.size() == 1 && "Wrong number of operands."); 20240b57cec5SDimitry Andric 20250b57cec5SDimitry Andric if (IntrinsicID == Intrinsic::is_constant) { 20260b57cec5SDimitry Andric // We know we have a "Constant" argument. But we want to only 20270b57cec5SDimitry Andric // return true for manifest constants, not those that depend on 20280b57cec5SDimitry Andric // constants with unknowable values, e.g. GlobalValue or BlockAddress. 202923408297SDimitry Andric if (Operands[0]->isManifestConstant()) 20300b57cec5SDimitry Andric return ConstantInt::getTrue(Ty->getContext()); 20310b57cec5SDimitry Andric return nullptr; 20320b57cec5SDimitry Andric } 2033bdd1243dSDimitry Andric 2034bdd1243dSDimitry Andric if (isa<PoisonValue>(Operands[0])) { 2035bdd1243dSDimitry Andric // TODO: All of these operations should probably propagate poison. 2036bdd1243dSDimitry Andric if (IntrinsicID == Intrinsic::canonicalize) 2037bdd1243dSDimitry Andric return PoisonValue::get(Ty); 2038bdd1243dSDimitry Andric } 2039bdd1243dSDimitry Andric 20400b57cec5SDimitry Andric if (isa<UndefValue>(Operands[0])) { 20410b57cec5SDimitry Andric // cosine(arg) is between -1 and 1. cosine(invalid arg) is NaN. 20420b57cec5SDimitry Andric // ctpop() is between 0 and bitwidth, pick 0 for undef. 2043e8d8bef9SDimitry Andric // fptoui.sat and fptosi.sat can always fold to zero (for a zero input). 20440b57cec5SDimitry Andric if (IntrinsicID == Intrinsic::cos || 2045e8d8bef9SDimitry Andric IntrinsicID == Intrinsic::ctpop || 2046e8d8bef9SDimitry Andric IntrinsicID == Intrinsic::fptoui_sat || 2047bdd1243dSDimitry Andric IntrinsicID == Intrinsic::fptosi_sat || 2048bdd1243dSDimitry Andric IntrinsicID == Intrinsic::canonicalize) 20490b57cec5SDimitry Andric return Constant::getNullValue(Ty); 20500b57cec5SDimitry Andric if (IntrinsicID == Intrinsic::bswap || 20510b57cec5SDimitry Andric IntrinsicID == Intrinsic::bitreverse || 20520b57cec5SDimitry Andric IntrinsicID == Intrinsic::launder_invariant_group || 20530b57cec5SDimitry Andric IntrinsicID == Intrinsic::strip_invariant_group) 20540b57cec5SDimitry Andric return Operands[0]; 20550b57cec5SDimitry Andric } 20560b57cec5SDimitry Andric 20570b57cec5SDimitry Andric if (isa<ConstantPointerNull>(Operands[0])) { 20580b57cec5SDimitry Andric // launder(null) == null == strip(null) iff in addrspace 0 20590b57cec5SDimitry Andric if (IntrinsicID == Intrinsic::launder_invariant_group || 20600b57cec5SDimitry Andric IntrinsicID == Intrinsic::strip_invariant_group) { 20610b57cec5SDimitry Andric // If instruction is not yet put in a basic block (e.g. when cloning 20620b57cec5SDimitry Andric // a function during inlining), Call's caller may not be available. 20630b57cec5SDimitry Andric // So check Call's BB first before querying Call->getCaller. 20640b57cec5SDimitry Andric const Function *Caller = 20650b57cec5SDimitry Andric Call->getParent() ? Call->getCaller() : nullptr; 20660b57cec5SDimitry Andric if (Caller && 20670b57cec5SDimitry Andric !NullPointerIsDefined( 20680b57cec5SDimitry Andric Caller, Operands[0]->getType()->getPointerAddressSpace())) { 20690b57cec5SDimitry Andric return Operands[0]; 20700b57cec5SDimitry Andric } 20710b57cec5SDimitry Andric return nullptr; 20720b57cec5SDimitry Andric } 20730b57cec5SDimitry Andric } 20740b57cec5SDimitry Andric 20750b57cec5SDimitry Andric if (auto *Op = dyn_cast<ConstantFP>(Operands[0])) { 20760b57cec5SDimitry Andric if (IntrinsicID == Intrinsic::convert_to_fp16) { 20770b57cec5SDimitry Andric APFloat Val(Op->getValueAPF()); 20780b57cec5SDimitry Andric 20790b57cec5SDimitry Andric bool lost = false; 20800b57cec5SDimitry Andric Val.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &lost); 20810b57cec5SDimitry Andric 20820b57cec5SDimitry Andric return ConstantInt::get(Ty->getContext(), Val.bitcastToAPInt()); 20830b57cec5SDimitry Andric } 20840b57cec5SDimitry Andric 2085e8d8bef9SDimitry Andric APFloat U = Op->getValueAPF(); 2086e8d8bef9SDimitry Andric 2087e8d8bef9SDimitry Andric if (IntrinsicID == Intrinsic::wasm_trunc_signed || 2088fe6060f1SDimitry Andric IntrinsicID == Intrinsic::wasm_trunc_unsigned) { 2089fe6060f1SDimitry Andric bool Signed = IntrinsicID == Intrinsic::wasm_trunc_signed; 2090e8d8bef9SDimitry Andric 2091e8d8bef9SDimitry Andric if (U.isNaN()) 2092fe6060f1SDimitry Andric return nullptr; 2093e8d8bef9SDimitry Andric 2094e8d8bef9SDimitry Andric unsigned Width = Ty->getIntegerBitWidth(); 2095e8d8bef9SDimitry Andric APSInt Int(Width, !Signed); 2096e8d8bef9SDimitry Andric bool IsExact = false; 2097e8d8bef9SDimitry Andric APFloat::opStatus Status = 2098e8d8bef9SDimitry Andric U.convertToInteger(Int, APFloat::rmTowardZero, &IsExact); 2099e8d8bef9SDimitry Andric 2100e8d8bef9SDimitry Andric if (Status == APFloat::opOK || Status == APFloat::opInexact) 2101e8d8bef9SDimitry Andric return ConstantInt::get(Ty, Int); 2102e8d8bef9SDimitry Andric 2103e8d8bef9SDimitry Andric return nullptr; 2104e8d8bef9SDimitry Andric } 2105e8d8bef9SDimitry Andric 2106e8d8bef9SDimitry Andric if (IntrinsicID == Intrinsic::fptoui_sat || 2107e8d8bef9SDimitry Andric IntrinsicID == Intrinsic::fptosi_sat) { 2108e8d8bef9SDimitry Andric // convertToInteger() already has the desired saturation semantics. 2109e8d8bef9SDimitry Andric APSInt Int(Ty->getIntegerBitWidth(), 2110e8d8bef9SDimitry Andric IntrinsicID == Intrinsic::fptoui_sat); 2111e8d8bef9SDimitry Andric bool IsExact; 2112e8d8bef9SDimitry Andric U.convertToInteger(Int, APFloat::rmTowardZero, &IsExact); 2113e8d8bef9SDimitry Andric return ConstantInt::get(Ty, Int); 2114e8d8bef9SDimitry Andric } 2115e8d8bef9SDimitry Andric 2116bdd1243dSDimitry Andric if (IntrinsicID == Intrinsic::canonicalize) 2117bdd1243dSDimitry Andric return constantFoldCanonicalize(Ty, Call, U); 2118bdd1243dSDimitry Andric 21190fca6ea1SDimitry Andric #if defined(HAS_IEE754_FLOAT128) && defined(HAS_LOGF128) 21200fca6ea1SDimitry Andric if (Ty->isFP128Ty()) { 21210fca6ea1SDimitry Andric if (IntrinsicID == Intrinsic::log) { 21220fca6ea1SDimitry Andric float128 Result = logf128(Op->getValueAPF().convertToQuad()); 21230fca6ea1SDimitry Andric return GetConstantFoldFPValue128(Result, Ty); 21240fca6ea1SDimitry Andric } 21250fca6ea1SDimitry Andric 21260fca6ea1SDimitry Andric LibFunc Fp128Func = NotLibFunc; 21270fca6ea1SDimitry Andric if (TLI->getLibFunc(Name, Fp128Func) && TLI->has(Fp128Func) && 21280fca6ea1SDimitry Andric Fp128Func == LibFunc_logl) 21290fca6ea1SDimitry Andric return ConstantFoldFP128(logf128, Op->getValueAPF(), Ty); 21300fca6ea1SDimitry Andric } 21310fca6ea1SDimitry Andric #endif 21320fca6ea1SDimitry Andric 21330b57cec5SDimitry Andric if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy()) 21340b57cec5SDimitry Andric return nullptr; 21350b57cec5SDimitry Andric 21368bcb0991SDimitry Andric // Use internal versions of these intrinsics. 21378bcb0991SDimitry Andric 21388bcb0991SDimitry Andric if (IntrinsicID == Intrinsic::nearbyint || IntrinsicID == Intrinsic::rint) { 21398bcb0991SDimitry Andric U.roundToIntegral(APFloat::rmNearestTiesToEven); 21408bcb0991SDimitry Andric return ConstantFP::get(Ty->getContext(), U); 21410b57cec5SDimitry Andric } 21420b57cec5SDimitry Andric 21438bcb0991SDimitry Andric if (IntrinsicID == Intrinsic::round) { 21448bcb0991SDimitry Andric U.roundToIntegral(APFloat::rmNearestTiesToAway); 21458bcb0991SDimitry Andric return ConstantFP::get(Ty->getContext(), U); 21460b57cec5SDimitry Andric } 21470b57cec5SDimitry Andric 21485ffd83dbSDimitry Andric if (IntrinsicID == Intrinsic::roundeven) { 21495ffd83dbSDimitry Andric U.roundToIntegral(APFloat::rmNearestTiesToEven); 21505ffd83dbSDimitry Andric return ConstantFP::get(Ty->getContext(), U); 21515ffd83dbSDimitry Andric } 21525ffd83dbSDimitry Andric 21530b57cec5SDimitry Andric if (IntrinsicID == Intrinsic::ceil) { 21548bcb0991SDimitry Andric U.roundToIntegral(APFloat::rmTowardPositive); 21558bcb0991SDimitry Andric return ConstantFP::get(Ty->getContext(), U); 21568bcb0991SDimitry Andric } 21578bcb0991SDimitry Andric 21588bcb0991SDimitry Andric if (IntrinsicID == Intrinsic::floor) { 21598bcb0991SDimitry Andric U.roundToIntegral(APFloat::rmTowardNegative); 21608bcb0991SDimitry Andric return ConstantFP::get(Ty->getContext(), U); 21610b57cec5SDimitry Andric } 21620b57cec5SDimitry Andric 21630b57cec5SDimitry Andric if (IntrinsicID == Intrinsic::trunc) { 21648bcb0991SDimitry Andric U.roundToIntegral(APFloat::rmTowardZero); 21658bcb0991SDimitry Andric return ConstantFP::get(Ty->getContext(), U); 21660b57cec5SDimitry Andric } 21670b57cec5SDimitry Andric 21688bcb0991SDimitry Andric if (IntrinsicID == Intrinsic::fabs) { 21698bcb0991SDimitry Andric U.clearSign(); 21708bcb0991SDimitry Andric return ConstantFP::get(Ty->getContext(), U); 21710b57cec5SDimitry Andric } 21720b57cec5SDimitry Andric 21735ffd83dbSDimitry Andric if (IntrinsicID == Intrinsic::amdgcn_fract) { 21745ffd83dbSDimitry Andric // The v_fract instruction behaves like the OpenCL spec, which defines 21755ffd83dbSDimitry Andric // fract(x) as fmin(x - floor(x), 0x1.fffffep-1f): "The min() operator is 21765ffd83dbSDimitry Andric // there to prevent fract(-small) from returning 1.0. It returns the 21775ffd83dbSDimitry Andric // largest positive floating-point number less than 1.0." 21785ffd83dbSDimitry Andric APFloat FloorU(U); 21795ffd83dbSDimitry Andric FloorU.roundToIntegral(APFloat::rmTowardNegative); 21805ffd83dbSDimitry Andric APFloat FractU(U - FloorU); 21815ffd83dbSDimitry Andric APFloat AlmostOne(U.getSemantics(), 1); 21825ffd83dbSDimitry Andric AlmostOne.next(/*nextDown*/ true); 21835ffd83dbSDimitry Andric return ConstantFP::get(Ty->getContext(), minimum(FractU, AlmostOne)); 21845ffd83dbSDimitry Andric } 21855ffd83dbSDimitry Andric 21865ffd83dbSDimitry Andric // Rounding operations (floor, trunc, ceil, round and nearbyint) do not 21875ffd83dbSDimitry Andric // raise FP exceptions, unless the argument is signaling NaN. 21885ffd83dbSDimitry Andric 2189bdd1243dSDimitry Andric std::optional<APFloat::roundingMode> RM; 21905ffd83dbSDimitry Andric switch (IntrinsicID) { 21915ffd83dbSDimitry Andric default: 21925ffd83dbSDimitry Andric break; 21935ffd83dbSDimitry Andric case Intrinsic::experimental_constrained_nearbyint: 21945ffd83dbSDimitry Andric case Intrinsic::experimental_constrained_rint: { 21955ffd83dbSDimitry Andric auto CI = cast<ConstrainedFPIntrinsic>(Call); 21965ffd83dbSDimitry Andric RM = CI->getRoundingMode(); 219781ad6265SDimitry Andric if (!RM || *RM == RoundingMode::Dynamic) 21985ffd83dbSDimitry Andric return nullptr; 21995ffd83dbSDimitry Andric break; 22005ffd83dbSDimitry Andric } 22015ffd83dbSDimitry Andric case Intrinsic::experimental_constrained_round: 22025ffd83dbSDimitry Andric RM = APFloat::rmNearestTiesToAway; 22035ffd83dbSDimitry Andric break; 22045ffd83dbSDimitry Andric case Intrinsic::experimental_constrained_ceil: 22055ffd83dbSDimitry Andric RM = APFloat::rmTowardPositive; 22065ffd83dbSDimitry Andric break; 22075ffd83dbSDimitry Andric case Intrinsic::experimental_constrained_floor: 22085ffd83dbSDimitry Andric RM = APFloat::rmTowardNegative; 22095ffd83dbSDimitry Andric break; 22105ffd83dbSDimitry Andric case Intrinsic::experimental_constrained_trunc: 22115ffd83dbSDimitry Andric RM = APFloat::rmTowardZero; 22125ffd83dbSDimitry Andric break; 22135ffd83dbSDimitry Andric } 22145ffd83dbSDimitry Andric if (RM) { 22155ffd83dbSDimitry Andric auto CI = cast<ConstrainedFPIntrinsic>(Call); 22165ffd83dbSDimitry Andric if (U.isFinite()) { 22175ffd83dbSDimitry Andric APFloat::opStatus St = U.roundToIntegral(*RM); 22185ffd83dbSDimitry Andric if (IntrinsicID == Intrinsic::experimental_constrained_rint && 22195ffd83dbSDimitry Andric St == APFloat::opInexact) { 2220bdd1243dSDimitry Andric std::optional<fp::ExceptionBehavior> EB = CI->getExceptionBehavior(); 22215ffd83dbSDimitry Andric if (EB && *EB == fp::ebStrict) 22225ffd83dbSDimitry Andric return nullptr; 22235ffd83dbSDimitry Andric } 22245ffd83dbSDimitry Andric } else if (U.isSignaling()) { 2225bdd1243dSDimitry Andric std::optional<fp::ExceptionBehavior> EB = CI->getExceptionBehavior(); 22265ffd83dbSDimitry Andric if (EB && *EB != fp::ebIgnore) 22275ffd83dbSDimitry Andric return nullptr; 22285ffd83dbSDimitry Andric U = APFloat::getQNaN(U.getSemantics()); 22295ffd83dbSDimitry Andric } 22305ffd83dbSDimitry Andric return ConstantFP::get(Ty->getContext(), U); 22315ffd83dbSDimitry Andric } 22325ffd83dbSDimitry Andric 22330b57cec5SDimitry Andric /// We only fold functions with finite arguments. Folding NaN and inf is 22340b57cec5SDimitry Andric /// likely to be aborted with an exception anyway, and some host libms 22350b57cec5SDimitry Andric /// have known errors raising exceptions. 22365ffd83dbSDimitry Andric if (!U.isFinite()) 22370b57cec5SDimitry Andric return nullptr; 22380b57cec5SDimitry Andric 22390b57cec5SDimitry Andric /// Currently APFloat versions of these functions do not exist, so we use 22400b57cec5SDimitry Andric /// the host native double versions. Float versions are not called 22410b57cec5SDimitry Andric /// directly but for all these it is true (float)(f((double)arg)) == 22420b57cec5SDimitry Andric /// f(arg). Long double not supported yet. 2243349cc55cSDimitry Andric const APFloat &APF = Op->getValueAPF(); 22440b57cec5SDimitry Andric 22450b57cec5SDimitry Andric switch (IntrinsicID) { 22460b57cec5SDimitry Andric default: break; 22470b57cec5SDimitry Andric case Intrinsic::log: 2248fe6060f1SDimitry Andric return ConstantFoldFP(log, APF, Ty); 22498bcb0991SDimitry Andric case Intrinsic::log2: 22508bcb0991SDimitry Andric // TODO: What about hosts that lack a C99 library? 2251bdd1243dSDimitry Andric return ConstantFoldFP(log2, APF, Ty); 22520b57cec5SDimitry Andric case Intrinsic::log10: 22538bcb0991SDimitry Andric // TODO: What about hosts that lack a C99 library? 2254fe6060f1SDimitry Andric return ConstantFoldFP(log10, APF, Ty); 22550b57cec5SDimitry Andric case Intrinsic::exp: 2256fe6060f1SDimitry Andric return ConstantFoldFP(exp, APF, Ty); 22570b57cec5SDimitry Andric case Intrinsic::exp2: 22588bcb0991SDimitry Andric // Fold exp2(x) as pow(2, x), in case the host lacks a C99 library. 2259fe6060f1SDimitry Andric return ConstantFoldBinaryFP(pow, APFloat(2.0), APF, Ty); 22605f757f3fSDimitry Andric case Intrinsic::exp10: 22615f757f3fSDimitry Andric // Fold exp10(x) as pow(10, x), in case the host lacks a C99 library. 22625f757f3fSDimitry Andric return ConstantFoldBinaryFP(pow, APFloat(10.0), APF, Ty); 22630b57cec5SDimitry Andric case Intrinsic::sin: 2264fe6060f1SDimitry Andric return ConstantFoldFP(sin, APF, Ty); 22650b57cec5SDimitry Andric case Intrinsic::cos: 2266fe6060f1SDimitry Andric return ConstantFoldFP(cos, APF, Ty); 22670b57cec5SDimitry Andric case Intrinsic::sqrt: 2268fe6060f1SDimitry Andric return ConstantFoldFP(sqrt, APF, Ty); 22695ffd83dbSDimitry Andric case Intrinsic::amdgcn_cos: 2270fe6060f1SDimitry Andric case Intrinsic::amdgcn_sin: { 2271fe6060f1SDimitry Andric double V = getValueAsDouble(Op); 22725ffd83dbSDimitry Andric if (V < -256.0 || V > 256.0) 22735ffd83dbSDimitry Andric // The gfx8 and gfx9 architectures handle arguments outside the range 22745ffd83dbSDimitry Andric // [-256, 256] differently. This should be a rare case so bail out 22755ffd83dbSDimitry Andric // rather than trying to handle the difference. 22765ffd83dbSDimitry Andric return nullptr; 22775ffd83dbSDimitry Andric bool IsCos = IntrinsicID == Intrinsic::amdgcn_cos; 22785ffd83dbSDimitry Andric double V4 = V * 4.0; 22795ffd83dbSDimitry Andric if (V4 == floor(V4)) { 22805ffd83dbSDimitry Andric // Force exact results for quarter-integer inputs. 22815ffd83dbSDimitry Andric const double SinVals[4] = { 0.0, 1.0, 0.0, -1.0 }; 22825ffd83dbSDimitry Andric V = SinVals[((int)V4 + (IsCos ? 1 : 0)) & 3]; 22835ffd83dbSDimitry Andric } else { 22845ffd83dbSDimitry Andric if (IsCos) 22855ffd83dbSDimitry Andric V = cos(V * 2.0 * numbers::pi); 22865ffd83dbSDimitry Andric else 22875ffd83dbSDimitry Andric V = sin(V * 2.0 * numbers::pi); 22885ffd83dbSDimitry Andric } 22895ffd83dbSDimitry Andric return GetConstantFoldFPValue(V, Ty); 22900b57cec5SDimitry Andric } 2291fe6060f1SDimitry Andric } 22920b57cec5SDimitry Andric 22930b57cec5SDimitry Andric if (!TLI) 22940b57cec5SDimitry Andric return nullptr; 22950b57cec5SDimitry Andric 22968bcb0991SDimitry Andric LibFunc Func = NotLibFunc; 2297349cc55cSDimitry Andric if (!TLI->getLibFunc(Name, Func)) 2298349cc55cSDimitry Andric return nullptr; 2299349cc55cSDimitry Andric 23008bcb0991SDimitry Andric switch (Func) { 23018bcb0991SDimitry Andric default: 23028bcb0991SDimitry Andric break; 23038bcb0991SDimitry Andric case LibFunc_acos: 23048bcb0991SDimitry Andric case LibFunc_acosf: 23058bcb0991SDimitry Andric case LibFunc_acos_finite: 23068bcb0991SDimitry Andric case LibFunc_acosf_finite: 23078bcb0991SDimitry Andric if (TLI->has(Func)) 2308fe6060f1SDimitry Andric return ConstantFoldFP(acos, APF, Ty); 23098bcb0991SDimitry Andric break; 23108bcb0991SDimitry Andric case LibFunc_asin: 23118bcb0991SDimitry Andric case LibFunc_asinf: 23128bcb0991SDimitry Andric case LibFunc_asin_finite: 23138bcb0991SDimitry Andric case LibFunc_asinf_finite: 23148bcb0991SDimitry Andric if (TLI->has(Func)) 2315fe6060f1SDimitry Andric return ConstantFoldFP(asin, APF, Ty); 23168bcb0991SDimitry Andric break; 23178bcb0991SDimitry Andric case LibFunc_atan: 23188bcb0991SDimitry Andric case LibFunc_atanf: 23198bcb0991SDimitry Andric if (TLI->has(Func)) 2320fe6060f1SDimitry Andric return ConstantFoldFP(atan, APF, Ty); 23210b57cec5SDimitry Andric break; 23228bcb0991SDimitry Andric case LibFunc_ceil: 23238bcb0991SDimitry Andric case LibFunc_ceilf: 23248bcb0991SDimitry Andric if (TLI->has(Func)) { 23258bcb0991SDimitry Andric U.roundToIntegral(APFloat::rmTowardPositive); 23268bcb0991SDimitry Andric return ConstantFP::get(Ty->getContext(), U); 23278bcb0991SDimitry Andric } 23288bcb0991SDimitry Andric break; 23298bcb0991SDimitry Andric case LibFunc_cos: 23308bcb0991SDimitry Andric case LibFunc_cosf: 23318bcb0991SDimitry Andric if (TLI->has(Func)) 2332fe6060f1SDimitry Andric return ConstantFoldFP(cos, APF, Ty); 23338bcb0991SDimitry Andric break; 23348bcb0991SDimitry Andric case LibFunc_cosh: 23358bcb0991SDimitry Andric case LibFunc_coshf: 23368bcb0991SDimitry Andric case LibFunc_cosh_finite: 23378bcb0991SDimitry Andric case LibFunc_coshf_finite: 23388bcb0991SDimitry Andric if (TLI->has(Func)) 2339fe6060f1SDimitry Andric return ConstantFoldFP(cosh, APF, Ty); 23400b57cec5SDimitry Andric break; 23418bcb0991SDimitry Andric case LibFunc_exp: 23428bcb0991SDimitry Andric case LibFunc_expf: 23438bcb0991SDimitry Andric case LibFunc_exp_finite: 23448bcb0991SDimitry Andric case LibFunc_expf_finite: 23458bcb0991SDimitry Andric if (TLI->has(Func)) 2346fe6060f1SDimitry Andric return ConstantFoldFP(exp, APF, Ty); 23478bcb0991SDimitry Andric break; 23488bcb0991SDimitry Andric case LibFunc_exp2: 23498bcb0991SDimitry Andric case LibFunc_exp2f: 23508bcb0991SDimitry Andric case LibFunc_exp2_finite: 23518bcb0991SDimitry Andric case LibFunc_exp2f_finite: 23528bcb0991SDimitry Andric if (TLI->has(Func)) 23538bcb0991SDimitry Andric // Fold exp2(x) as pow(2, x), in case the host lacks a C99 library. 2354fe6060f1SDimitry Andric return ConstantFoldBinaryFP(pow, APFloat(2.0), APF, Ty); 23550b57cec5SDimitry Andric break; 23568bcb0991SDimitry Andric case LibFunc_fabs: 23578bcb0991SDimitry Andric case LibFunc_fabsf: 23588bcb0991SDimitry Andric if (TLI->has(Func)) { 23598bcb0991SDimitry Andric U.clearSign(); 23608bcb0991SDimitry Andric return ConstantFP::get(Ty->getContext(), U); 23618bcb0991SDimitry Andric } 23620b57cec5SDimitry Andric break; 23638bcb0991SDimitry Andric case LibFunc_floor: 23648bcb0991SDimitry Andric case LibFunc_floorf: 23658bcb0991SDimitry Andric if (TLI->has(Func)) { 23668bcb0991SDimitry Andric U.roundToIntegral(APFloat::rmTowardNegative); 23678bcb0991SDimitry Andric return ConstantFP::get(Ty->getContext(), U); 23688bcb0991SDimitry Andric } 23698bcb0991SDimitry Andric break; 23708bcb0991SDimitry Andric case LibFunc_log: 23718bcb0991SDimitry Andric case LibFunc_logf: 23728bcb0991SDimitry Andric case LibFunc_log_finite: 23738bcb0991SDimitry Andric case LibFunc_logf_finite: 2374fe6060f1SDimitry Andric if (!APF.isNegative() && !APF.isZero() && TLI->has(Func)) 2375fe6060f1SDimitry Andric return ConstantFoldFP(log, APF, Ty); 23768bcb0991SDimitry Andric break; 23778bcb0991SDimitry Andric case LibFunc_log2: 23788bcb0991SDimitry Andric case LibFunc_log2f: 23798bcb0991SDimitry Andric case LibFunc_log2_finite: 23808bcb0991SDimitry Andric case LibFunc_log2f_finite: 2381fe6060f1SDimitry Andric if (!APF.isNegative() && !APF.isZero() && TLI->has(Func)) 23828bcb0991SDimitry Andric // TODO: What about hosts that lack a C99 library? 2383bdd1243dSDimitry Andric return ConstantFoldFP(log2, APF, Ty); 23848bcb0991SDimitry Andric break; 23858bcb0991SDimitry Andric case LibFunc_log10: 23868bcb0991SDimitry Andric case LibFunc_log10f: 23878bcb0991SDimitry Andric case LibFunc_log10_finite: 23888bcb0991SDimitry Andric case LibFunc_log10f_finite: 2389fe6060f1SDimitry Andric if (!APF.isNegative() && !APF.isZero() && TLI->has(Func)) 23908bcb0991SDimitry Andric // TODO: What about hosts that lack a C99 library? 2391fe6060f1SDimitry Andric return ConstantFoldFP(log10, APF, Ty); 23920b57cec5SDimitry Andric break; 23930fca6ea1SDimitry Andric case LibFunc_logl: 23940fca6ea1SDimitry Andric return nullptr; 23958bcb0991SDimitry Andric case LibFunc_nearbyint: 23968bcb0991SDimitry Andric case LibFunc_nearbyintf: 23978bcb0991SDimitry Andric case LibFunc_rint: 23988bcb0991SDimitry Andric case LibFunc_rintf: 23998bcb0991SDimitry Andric if (TLI->has(Func)) { 24008bcb0991SDimitry Andric U.roundToIntegral(APFloat::rmNearestTiesToEven); 24018bcb0991SDimitry Andric return ConstantFP::get(Ty->getContext(), U); 24028bcb0991SDimitry Andric } 24030b57cec5SDimitry Andric break; 24048bcb0991SDimitry Andric case LibFunc_round: 24058bcb0991SDimitry Andric case LibFunc_roundf: 24068bcb0991SDimitry Andric if (TLI->has(Func)) { 24078bcb0991SDimitry Andric U.roundToIntegral(APFloat::rmNearestTiesToAway); 24088bcb0991SDimitry Andric return ConstantFP::get(Ty->getContext(), U); 24098bcb0991SDimitry Andric } 24108bcb0991SDimitry Andric break; 24118bcb0991SDimitry Andric case LibFunc_sin: 24128bcb0991SDimitry Andric case LibFunc_sinf: 24138bcb0991SDimitry Andric if (TLI->has(Func)) 2414fe6060f1SDimitry Andric return ConstantFoldFP(sin, APF, Ty); 24158bcb0991SDimitry Andric break; 24168bcb0991SDimitry Andric case LibFunc_sinh: 24178bcb0991SDimitry Andric case LibFunc_sinhf: 24188bcb0991SDimitry Andric case LibFunc_sinh_finite: 24198bcb0991SDimitry Andric case LibFunc_sinhf_finite: 24208bcb0991SDimitry Andric if (TLI->has(Func)) 2421fe6060f1SDimitry Andric return ConstantFoldFP(sinh, APF, Ty); 24228bcb0991SDimitry Andric break; 24238bcb0991SDimitry Andric case LibFunc_sqrt: 24248bcb0991SDimitry Andric case LibFunc_sqrtf: 2425fe6060f1SDimitry Andric if (!APF.isNegative() && TLI->has(Func)) 2426fe6060f1SDimitry Andric return ConstantFoldFP(sqrt, APF, Ty); 24270b57cec5SDimitry Andric break; 24288bcb0991SDimitry Andric case LibFunc_tan: 24298bcb0991SDimitry Andric case LibFunc_tanf: 24308bcb0991SDimitry Andric if (TLI->has(Func)) 2431fe6060f1SDimitry Andric return ConstantFoldFP(tan, APF, Ty); 24328bcb0991SDimitry Andric break; 24338bcb0991SDimitry Andric case LibFunc_tanh: 24348bcb0991SDimitry Andric case LibFunc_tanhf: 24358bcb0991SDimitry Andric if (TLI->has(Func)) 2436fe6060f1SDimitry Andric return ConstantFoldFP(tanh, APF, Ty); 24370b57cec5SDimitry Andric break; 24388bcb0991SDimitry Andric case LibFunc_trunc: 24398bcb0991SDimitry Andric case LibFunc_truncf: 24408bcb0991SDimitry Andric if (TLI->has(Func)) { 24418bcb0991SDimitry Andric U.roundToIntegral(APFloat::rmTowardZero); 24428bcb0991SDimitry Andric return ConstantFP::get(Ty->getContext(), U); 24438bcb0991SDimitry Andric } 24440b57cec5SDimitry Andric break; 24450b57cec5SDimitry Andric } 24460b57cec5SDimitry Andric return nullptr; 24470b57cec5SDimitry Andric } 24480b57cec5SDimitry Andric 24490b57cec5SDimitry Andric if (auto *Op = dyn_cast<ConstantInt>(Operands[0])) { 24500b57cec5SDimitry Andric switch (IntrinsicID) { 24510b57cec5SDimitry Andric case Intrinsic::bswap: 24520b57cec5SDimitry Andric return ConstantInt::get(Ty->getContext(), Op->getValue().byteSwap()); 24530b57cec5SDimitry Andric case Intrinsic::ctpop: 245406c3fb27SDimitry Andric return ConstantInt::get(Ty, Op->getValue().popcount()); 24550b57cec5SDimitry Andric case Intrinsic::bitreverse: 24560b57cec5SDimitry Andric return ConstantInt::get(Ty->getContext(), Op->getValue().reverseBits()); 24570b57cec5SDimitry Andric case Intrinsic::convert_from_fp16: { 24580b57cec5SDimitry Andric APFloat Val(APFloat::IEEEhalf(), Op->getValue()); 24590b57cec5SDimitry Andric 24600b57cec5SDimitry Andric bool lost = false; 24610b57cec5SDimitry Andric APFloat::opStatus status = Val.convert( 24620b57cec5SDimitry Andric Ty->getFltSemantics(), APFloat::rmNearestTiesToEven, &lost); 24630b57cec5SDimitry Andric 24640b57cec5SDimitry Andric // Conversion is always precise. 24650b57cec5SDimitry Andric (void)status; 2466bdd1243dSDimitry Andric assert(status != APFloat::opInexact && !lost && 24670b57cec5SDimitry Andric "Precision lost during fp16 constfolding"); 24680b57cec5SDimitry Andric 24690b57cec5SDimitry Andric return ConstantFP::get(Ty->getContext(), Val); 24700b57cec5SDimitry Andric } 24715f757f3fSDimitry Andric 24725f757f3fSDimitry Andric case Intrinsic::amdgcn_s_wqm: { 24735f757f3fSDimitry Andric uint64_t Val = Op->getZExtValue(); 24745f757f3fSDimitry Andric Val |= (Val & 0x5555555555555555ULL) << 1 | 24755f757f3fSDimitry Andric ((Val >> 1) & 0x5555555555555555ULL); 24765f757f3fSDimitry Andric Val |= (Val & 0x3333333333333333ULL) << 2 | 24775f757f3fSDimitry Andric ((Val >> 2) & 0x3333333333333333ULL); 24785f757f3fSDimitry Andric return ConstantInt::get(Ty, Val); 24795f757f3fSDimitry Andric } 24805f757f3fSDimitry Andric 24815f757f3fSDimitry Andric case Intrinsic::amdgcn_s_quadmask: { 24825f757f3fSDimitry Andric uint64_t Val = Op->getZExtValue(); 24835f757f3fSDimitry Andric uint64_t QuadMask = 0; 24845f757f3fSDimitry Andric for (unsigned I = 0; I < Op->getBitWidth() / 4; ++I, Val >>= 4) { 24855f757f3fSDimitry Andric if (!(Val & 0xF)) 24865f757f3fSDimitry Andric continue; 24875f757f3fSDimitry Andric 24885f757f3fSDimitry Andric QuadMask |= (1ULL << I); 24895f757f3fSDimitry Andric } 24905f757f3fSDimitry Andric return ConstantInt::get(Ty, QuadMask); 24915f757f3fSDimitry Andric } 24925f757f3fSDimitry Andric 24935f757f3fSDimitry Andric case Intrinsic::amdgcn_s_bitreplicate: { 24945f757f3fSDimitry Andric uint64_t Val = Op->getZExtValue(); 24955f757f3fSDimitry Andric Val = (Val & 0x000000000000FFFFULL) | (Val & 0x00000000FFFF0000ULL) << 16; 24965f757f3fSDimitry Andric Val = (Val & 0x000000FF000000FFULL) | (Val & 0x0000FF000000FF00ULL) << 8; 24975f757f3fSDimitry Andric Val = (Val & 0x000F000F000F000FULL) | (Val & 0x00F000F000F000F0ULL) << 4; 24985f757f3fSDimitry Andric Val = (Val & 0x0303030303030303ULL) | (Val & 0x0C0C0C0C0C0C0C0CULL) << 2; 24995f757f3fSDimitry Andric Val = (Val & 0x1111111111111111ULL) | (Val & 0x2222222222222222ULL) << 1; 25005f757f3fSDimitry Andric Val = Val | Val << 1; 25015f757f3fSDimitry Andric return ConstantInt::get(Ty, Val); 25025f757f3fSDimitry Andric } 25035f757f3fSDimitry Andric 25040b57cec5SDimitry Andric default: 25050b57cec5SDimitry Andric return nullptr; 25060b57cec5SDimitry Andric } 25070b57cec5SDimitry Andric } 25080b57cec5SDimitry Andric 25095ffd83dbSDimitry Andric switch (IntrinsicID) { 25105ffd83dbSDimitry Andric default: break; 2511e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_add: 2512e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_mul: 2513e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_and: 2514e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_or: 2515e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_xor: 2516e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_smin: 2517e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_smax: 2518e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_umin: 2519e8d8bef9SDimitry Andric case Intrinsic::vector_reduce_umax: 2520fe6060f1SDimitry Andric if (Constant *C = constantFoldVectorReduce(IntrinsicID, Operands[0])) 2521fe6060f1SDimitry Andric return C; 2522fe6060f1SDimitry Andric break; 25235ffd83dbSDimitry Andric } 25245ffd83dbSDimitry Andric 25250b57cec5SDimitry Andric // Support ConstantVector in case we have an Undef in the top. 25260b57cec5SDimitry Andric if (isa<ConstantVector>(Operands[0]) || 25270b57cec5SDimitry Andric isa<ConstantDataVector>(Operands[0])) { 25280b57cec5SDimitry Andric auto *Op = cast<Constant>(Operands[0]); 25290b57cec5SDimitry Andric switch (IntrinsicID) { 25300b57cec5SDimitry Andric default: break; 25310b57cec5SDimitry Andric case Intrinsic::x86_sse_cvtss2si: 25320b57cec5SDimitry Andric case Intrinsic::x86_sse_cvtss2si64: 25330b57cec5SDimitry Andric case Intrinsic::x86_sse2_cvtsd2si: 25340b57cec5SDimitry Andric case Intrinsic::x86_sse2_cvtsd2si64: 25350b57cec5SDimitry Andric if (ConstantFP *FPOp = 25360b57cec5SDimitry Andric dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U))) 25370b57cec5SDimitry Andric return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(), 25380b57cec5SDimitry Andric /*roundTowardZero=*/false, Ty, 25390b57cec5SDimitry Andric /*IsSigned*/true); 25400b57cec5SDimitry Andric break; 25410b57cec5SDimitry Andric case Intrinsic::x86_sse_cvttss2si: 25420b57cec5SDimitry Andric case Intrinsic::x86_sse_cvttss2si64: 25430b57cec5SDimitry Andric case Intrinsic::x86_sse2_cvttsd2si: 25440b57cec5SDimitry Andric case Intrinsic::x86_sse2_cvttsd2si64: 25450b57cec5SDimitry Andric if (ConstantFP *FPOp = 25460b57cec5SDimitry Andric dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U))) 25470b57cec5SDimitry Andric return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(), 25480b57cec5SDimitry Andric /*roundTowardZero=*/true, Ty, 25490b57cec5SDimitry Andric /*IsSigned*/true); 25500b57cec5SDimitry Andric break; 25510b57cec5SDimitry Andric } 25520b57cec5SDimitry Andric } 25530b57cec5SDimitry Andric 25540b57cec5SDimitry Andric return nullptr; 25550b57cec5SDimitry Andric } 25560b57cec5SDimitry Andric 255781ad6265SDimitry Andric static Constant *evaluateCompare(const APFloat &Op1, const APFloat &Op2, 255881ad6265SDimitry Andric const ConstrainedFPIntrinsic *Call) { 255981ad6265SDimitry Andric APFloat::opStatus St = APFloat::opOK; 256081ad6265SDimitry Andric auto *FCmp = cast<ConstrainedFPCmpIntrinsic>(Call); 256181ad6265SDimitry Andric FCmpInst::Predicate Cond = FCmp->getPredicate(); 256281ad6265SDimitry Andric if (FCmp->isSignaling()) { 256381ad6265SDimitry Andric if (Op1.isNaN() || Op2.isNaN()) 256481ad6265SDimitry Andric St = APFloat::opInvalidOp; 256581ad6265SDimitry Andric } else { 256681ad6265SDimitry Andric if (Op1.isSignaling() || Op2.isSignaling()) 256781ad6265SDimitry Andric St = APFloat::opInvalidOp; 256881ad6265SDimitry Andric } 256981ad6265SDimitry Andric bool Result = FCmpInst::compare(Op1, Op2, Cond); 257081ad6265SDimitry Andric if (mayFoldConstrained(const_cast<ConstrainedFPCmpIntrinsic *>(FCmp), St)) 257181ad6265SDimitry Andric return ConstantInt::get(Call->getType()->getScalarType(), Result); 257281ad6265SDimitry Andric return nullptr; 257381ad6265SDimitry Andric } 257481ad6265SDimitry Andric 25750fca6ea1SDimitry Andric static Constant *ConstantFoldLibCall2(StringRef Name, Type *Ty, 25760b57cec5SDimitry Andric ArrayRef<Constant *> Operands, 25770fca6ea1SDimitry Andric const TargetLibraryInfo *TLI) { 25780fca6ea1SDimitry Andric if (!TLI) 25790fca6ea1SDimitry Andric return nullptr; 25800fca6ea1SDimitry Andric 25810fca6ea1SDimitry Andric LibFunc Func = NotLibFunc; 25820fca6ea1SDimitry Andric if (!TLI->getLibFunc(Name, Func)) 25830fca6ea1SDimitry Andric return nullptr; 25840fca6ea1SDimitry Andric 25850fca6ea1SDimitry Andric const auto *Op1 = dyn_cast<ConstantFP>(Operands[0]); 25860fca6ea1SDimitry Andric if (!Op1) 25870fca6ea1SDimitry Andric return nullptr; 25880fca6ea1SDimitry Andric 25890fca6ea1SDimitry Andric const auto *Op2 = dyn_cast<ConstantFP>(Operands[1]); 25900fca6ea1SDimitry Andric if (!Op2) 25910fca6ea1SDimitry Andric return nullptr; 25920fca6ea1SDimitry Andric 25930fca6ea1SDimitry Andric const APFloat &Op1V = Op1->getValueAPF(); 25940fca6ea1SDimitry Andric const APFloat &Op2V = Op2->getValueAPF(); 25950fca6ea1SDimitry Andric 25960fca6ea1SDimitry Andric switch (Func) { 25970fca6ea1SDimitry Andric default: 25980fca6ea1SDimitry Andric break; 25990fca6ea1SDimitry Andric case LibFunc_pow: 26000fca6ea1SDimitry Andric case LibFunc_powf: 26010fca6ea1SDimitry Andric case LibFunc_pow_finite: 26020fca6ea1SDimitry Andric case LibFunc_powf_finite: 26030fca6ea1SDimitry Andric if (TLI->has(Func)) 26040fca6ea1SDimitry Andric return ConstantFoldBinaryFP(pow, Op1V, Op2V, Ty); 26050fca6ea1SDimitry Andric break; 26060fca6ea1SDimitry Andric case LibFunc_fmod: 26070fca6ea1SDimitry Andric case LibFunc_fmodf: 26080fca6ea1SDimitry Andric if (TLI->has(Func)) { 26090fca6ea1SDimitry Andric APFloat V = Op1->getValueAPF(); 26100fca6ea1SDimitry Andric if (APFloat::opStatus::opOK == V.mod(Op2->getValueAPF())) 26110fca6ea1SDimitry Andric return ConstantFP::get(Ty->getContext(), V); 26120fca6ea1SDimitry Andric } 26130fca6ea1SDimitry Andric break; 26140fca6ea1SDimitry Andric case LibFunc_remainder: 26150fca6ea1SDimitry Andric case LibFunc_remainderf: 26160fca6ea1SDimitry Andric if (TLI->has(Func)) { 26170fca6ea1SDimitry Andric APFloat V = Op1->getValueAPF(); 26180fca6ea1SDimitry Andric if (APFloat::opStatus::opOK == V.remainder(Op2->getValueAPF())) 26190fca6ea1SDimitry Andric return ConstantFP::get(Ty->getContext(), V); 26200fca6ea1SDimitry Andric } 26210fca6ea1SDimitry Andric break; 26220fca6ea1SDimitry Andric case LibFunc_atan2: 26230fca6ea1SDimitry Andric case LibFunc_atan2f: 26240fca6ea1SDimitry Andric // atan2(+/-0.0, +/-0.0) is known to raise an exception on some libm 26250fca6ea1SDimitry Andric // (Solaris), so we do not assume a known result for that. 26260fca6ea1SDimitry Andric if (Op1V.isZero() && Op2V.isZero()) 26270fca6ea1SDimitry Andric return nullptr; 26280fca6ea1SDimitry Andric [[fallthrough]]; 26290fca6ea1SDimitry Andric case LibFunc_atan2_finite: 26300fca6ea1SDimitry Andric case LibFunc_atan2f_finite: 26310fca6ea1SDimitry Andric if (TLI->has(Func)) 26320fca6ea1SDimitry Andric return ConstantFoldBinaryFP(atan2, Op1V, Op2V, Ty); 26330fca6ea1SDimitry Andric break; 26340fca6ea1SDimitry Andric } 26350fca6ea1SDimitry Andric 26360fca6ea1SDimitry Andric return nullptr; 26370fca6ea1SDimitry Andric } 26380fca6ea1SDimitry Andric 26390fca6ea1SDimitry Andric static Constant *ConstantFoldIntrinsicCall2(Intrinsic::ID IntrinsicID, Type *Ty, 26400fca6ea1SDimitry Andric ArrayRef<Constant *> Operands, 26410b57cec5SDimitry Andric const CallBase *Call) { 26420b57cec5SDimitry Andric assert(Operands.size() == 2 && "Wrong number of operands."); 26430b57cec5SDimitry Andric 2644e8d8bef9SDimitry Andric if (Ty->isFloatingPointTy()) { 2645e8d8bef9SDimitry Andric // TODO: We should have undef handling for all of the FP intrinsics that 2646e8d8bef9SDimitry Andric // are attempted to be folded in this function. 2647e8d8bef9SDimitry Andric bool IsOp0Undef = isa<UndefValue>(Operands[0]); 2648e8d8bef9SDimitry Andric bool IsOp1Undef = isa<UndefValue>(Operands[1]); 2649e8d8bef9SDimitry Andric switch (IntrinsicID) { 2650e8d8bef9SDimitry Andric case Intrinsic::maxnum: 2651e8d8bef9SDimitry Andric case Intrinsic::minnum: 2652e8d8bef9SDimitry Andric case Intrinsic::maximum: 2653e8d8bef9SDimitry Andric case Intrinsic::minimum: 2654e8d8bef9SDimitry Andric // If one argument is undef, return the other argument. 2655e8d8bef9SDimitry Andric if (IsOp0Undef) 2656e8d8bef9SDimitry Andric return Operands[1]; 2657e8d8bef9SDimitry Andric if (IsOp1Undef) 2658e8d8bef9SDimitry Andric return Operands[0]; 2659e8d8bef9SDimitry Andric break; 2660e8d8bef9SDimitry Andric } 2661e8d8bef9SDimitry Andric } 2662e8d8bef9SDimitry Andric 2663fe6060f1SDimitry Andric if (const auto *Op1 = dyn_cast<ConstantFP>(Operands[0])) { 2664349cc55cSDimitry Andric const APFloat &Op1V = Op1->getValueAPF(); 26650b57cec5SDimitry Andric 2666fe6060f1SDimitry Andric if (const auto *Op2 = dyn_cast<ConstantFP>(Operands[1])) { 26670b57cec5SDimitry Andric if (Op2->getType() != Op1->getType()) 26680b57cec5SDimitry Andric return nullptr; 2669349cc55cSDimitry Andric const APFloat &Op2V = Op2->getValueAPF(); 26700b57cec5SDimitry Andric 26710fca6ea1SDimitry Andric if (const auto *ConstrIntr = 26720fca6ea1SDimitry Andric dyn_cast_if_present<ConstrainedFPIntrinsic>(Call)) { 2673fe6060f1SDimitry Andric RoundingMode RM = getEvaluationRoundingMode(ConstrIntr); 2674fe6060f1SDimitry Andric APFloat Res = Op1V; 2675fe6060f1SDimitry Andric APFloat::opStatus St; 2676fe6060f1SDimitry Andric switch (IntrinsicID) { 2677fe6060f1SDimitry Andric default: 2678fe6060f1SDimitry Andric return nullptr; 2679fe6060f1SDimitry Andric case Intrinsic::experimental_constrained_fadd: 2680fe6060f1SDimitry Andric St = Res.add(Op2V, RM); 2681fe6060f1SDimitry Andric break; 2682fe6060f1SDimitry Andric case Intrinsic::experimental_constrained_fsub: 2683fe6060f1SDimitry Andric St = Res.subtract(Op2V, RM); 2684fe6060f1SDimitry Andric break; 2685fe6060f1SDimitry Andric case Intrinsic::experimental_constrained_fmul: 2686fe6060f1SDimitry Andric St = Res.multiply(Op2V, RM); 2687fe6060f1SDimitry Andric break; 2688fe6060f1SDimitry Andric case Intrinsic::experimental_constrained_fdiv: 2689fe6060f1SDimitry Andric St = Res.divide(Op2V, RM); 2690fe6060f1SDimitry Andric break; 2691fe6060f1SDimitry Andric case Intrinsic::experimental_constrained_frem: 2692fe6060f1SDimitry Andric St = Res.mod(Op2V); 2693fe6060f1SDimitry Andric break; 269481ad6265SDimitry Andric case Intrinsic::experimental_constrained_fcmp: 269581ad6265SDimitry Andric case Intrinsic::experimental_constrained_fcmps: 269681ad6265SDimitry Andric return evaluateCompare(Op1V, Op2V, ConstrIntr); 2697fe6060f1SDimitry Andric } 2698fe6060f1SDimitry Andric if (mayFoldConstrained(const_cast<ConstrainedFPIntrinsic *>(ConstrIntr), 2699fe6060f1SDimitry Andric St)) 2700fe6060f1SDimitry Andric return ConstantFP::get(Ty->getContext(), Res); 2701fe6060f1SDimitry Andric return nullptr; 2702fe6060f1SDimitry Andric } 2703fe6060f1SDimitry Andric 2704fe6060f1SDimitry Andric switch (IntrinsicID) { 2705fe6060f1SDimitry Andric default: 2706fe6060f1SDimitry Andric break; 2707fe6060f1SDimitry Andric case Intrinsic::copysign: 2708fe6060f1SDimitry Andric return ConstantFP::get(Ty->getContext(), APFloat::copySign(Op1V, Op2V)); 2709fe6060f1SDimitry Andric case Intrinsic::minnum: 2710fe6060f1SDimitry Andric return ConstantFP::get(Ty->getContext(), minnum(Op1V, Op2V)); 2711fe6060f1SDimitry Andric case Intrinsic::maxnum: 2712fe6060f1SDimitry Andric return ConstantFP::get(Ty->getContext(), maxnum(Op1V, Op2V)); 2713fe6060f1SDimitry Andric case Intrinsic::minimum: 2714fe6060f1SDimitry Andric return ConstantFP::get(Ty->getContext(), minimum(Op1V, Op2V)); 2715fe6060f1SDimitry Andric case Intrinsic::maximum: 2716fe6060f1SDimitry Andric return ConstantFP::get(Ty->getContext(), maximum(Op1V, Op2V)); 2717fe6060f1SDimitry Andric } 2718fe6060f1SDimitry Andric 2719fe6060f1SDimitry Andric if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy()) 2720fe6060f1SDimitry Andric return nullptr; 2721fe6060f1SDimitry Andric 2722fe6060f1SDimitry Andric switch (IntrinsicID) { 2723fe6060f1SDimitry Andric default: 2724fe6060f1SDimitry Andric break; 2725fe6060f1SDimitry Andric case Intrinsic::pow: 27260b57cec5SDimitry Andric return ConstantFoldBinaryFP(pow, Op1V, Op2V, Ty); 2727fe6060f1SDimitry Andric case Intrinsic::amdgcn_fmul_legacy: 2728e8d8bef9SDimitry Andric // The legacy behaviour is that multiplying +/- 0.0 by anything, even 2729e8d8bef9SDimitry Andric // NaN or infinity, gives +0.0. 2730fe6060f1SDimitry Andric if (Op1V.isZero() || Op2V.isZero()) 273106c3fb27SDimitry Andric return ConstantFP::getZero(Ty); 2732fe6060f1SDimitry Andric return ConstantFP::get(Ty->getContext(), Op1V * Op2V); 27335ffd83dbSDimitry Andric } 27345ffd83dbSDimitry Andric 27350b57cec5SDimitry Andric } else if (auto *Op2C = dyn_cast<ConstantInt>(Operands[1])) { 2736bdd1243dSDimitry Andric switch (IntrinsicID) { 27375f757f3fSDimitry Andric case Intrinsic::ldexp: { 27385f757f3fSDimitry Andric return ConstantFP::get( 27395f757f3fSDimitry Andric Ty->getContext(), 27405f757f3fSDimitry Andric scalbn(Op1V, Op2C->getSExtValue(), APFloat::rmNearestTiesToEven)); 27415f757f3fSDimitry Andric } 2742bdd1243dSDimitry Andric case Intrinsic::is_fpclass: { 274306c3fb27SDimitry Andric FPClassTest Mask = static_cast<FPClassTest>(Op2C->getZExtValue()); 2744bdd1243dSDimitry Andric bool Result = 2745bdd1243dSDimitry Andric ((Mask & fcSNan) && Op1V.isNaN() && Op1V.isSignaling()) || 2746bdd1243dSDimitry Andric ((Mask & fcQNan) && Op1V.isNaN() && !Op1V.isSignaling()) || 274706c3fb27SDimitry Andric ((Mask & fcNegInf) && Op1V.isNegInfinity()) || 2748bdd1243dSDimitry Andric ((Mask & fcNegNormal) && Op1V.isNormal() && Op1V.isNegative()) || 2749bdd1243dSDimitry Andric ((Mask & fcNegSubnormal) && Op1V.isDenormal() && Op1V.isNegative()) || 2750bdd1243dSDimitry Andric ((Mask & fcNegZero) && Op1V.isZero() && Op1V.isNegative()) || 2751bdd1243dSDimitry Andric ((Mask & fcPosZero) && Op1V.isZero() && !Op1V.isNegative()) || 2752bdd1243dSDimitry Andric ((Mask & fcPosSubnormal) && Op1V.isDenormal() && !Op1V.isNegative()) || 2753bdd1243dSDimitry Andric ((Mask & fcPosNormal) && Op1V.isNormal() && !Op1V.isNegative()) || 275406c3fb27SDimitry Andric ((Mask & fcPosInf) && Op1V.isPosInfinity()); 2755bdd1243dSDimitry Andric return ConstantInt::get(Ty, Result); 2756bdd1243dSDimitry Andric } 27570fca6ea1SDimitry Andric case Intrinsic::powi: { 27580fca6ea1SDimitry Andric int Exp = static_cast<int>(Op2C->getSExtValue()); 27590fca6ea1SDimitry Andric switch (Ty->getTypeID()) { 27600fca6ea1SDimitry Andric case Type::HalfTyID: 27610fca6ea1SDimitry Andric case Type::FloatTyID: { 27620fca6ea1SDimitry Andric APFloat Res(static_cast<float>(std::pow(Op1V.convertToFloat(), Exp))); 27630fca6ea1SDimitry Andric if (Ty->isHalfTy()) { 27640fca6ea1SDimitry Andric bool Unused; 27650fca6ea1SDimitry Andric Res.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, 27660fca6ea1SDimitry Andric &Unused); 27670fca6ea1SDimitry Andric } 27680fca6ea1SDimitry Andric return ConstantFP::get(Ty->getContext(), Res); 27690fca6ea1SDimitry Andric } 27700fca6ea1SDimitry Andric case Type::DoubleTyID: 27710fca6ea1SDimitry Andric return ConstantFP::get(Ty, std::pow(Op1V.convertToDouble(), Exp)); 27720fca6ea1SDimitry Andric default: 27730fca6ea1SDimitry Andric return nullptr; 27740fca6ea1SDimitry Andric } 27750fca6ea1SDimitry Andric } 2776bdd1243dSDimitry Andric default: 2777bdd1243dSDimitry Andric break; 2778bdd1243dSDimitry Andric } 27790b57cec5SDimitry Andric } 27800b57cec5SDimitry Andric return nullptr; 27810b57cec5SDimitry Andric } 27820b57cec5SDimitry Andric 27830b57cec5SDimitry Andric if (Operands[0]->getType()->isIntegerTy() && 27840b57cec5SDimitry Andric Operands[1]->getType()->isIntegerTy()) { 27850b57cec5SDimitry Andric const APInt *C0, *C1; 27860b57cec5SDimitry Andric if (!getConstIntOrUndef(Operands[0], C0) || 27870b57cec5SDimitry Andric !getConstIntOrUndef(Operands[1], C1)) 27880b57cec5SDimitry Andric return nullptr; 27890b57cec5SDimitry Andric 27900b57cec5SDimitry Andric switch (IntrinsicID) { 27910b57cec5SDimitry Andric default: break; 2792e8d8bef9SDimitry Andric case Intrinsic::smax: 2793e8d8bef9SDimitry Andric case Intrinsic::smin: 2794e8d8bef9SDimitry Andric case Intrinsic::umax: 2795e8d8bef9SDimitry Andric case Intrinsic::umin: 279681ad6265SDimitry Andric // This is the same as for binary ops - poison propagates. 279781ad6265SDimitry Andric // TODO: Poison handling should be consolidated. 279881ad6265SDimitry Andric if (isa<PoisonValue>(Operands[0]) || isa<PoisonValue>(Operands[1])) 279981ad6265SDimitry Andric return PoisonValue::get(Ty); 280081ad6265SDimitry Andric 2801e8d8bef9SDimitry Andric if (!C0 && !C1) 2802e8d8bef9SDimitry Andric return UndefValue::get(Ty); 2803e8d8bef9SDimitry Andric if (!C0 || !C1) 280404eeddc0SDimitry Andric return MinMaxIntrinsic::getSaturationPoint(IntrinsicID, Ty); 280504eeddc0SDimitry Andric return ConstantInt::get( 280604eeddc0SDimitry Andric Ty, ICmpInst::compare(*C0, *C1, 280704eeddc0SDimitry Andric MinMaxIntrinsic::getPredicate(IntrinsicID)) 280804eeddc0SDimitry Andric ? *C0 280904eeddc0SDimitry Andric : *C1); 2810e8d8bef9SDimitry Andric 28110fca6ea1SDimitry Andric case Intrinsic::scmp: 28120fca6ea1SDimitry Andric case Intrinsic::ucmp: 28130fca6ea1SDimitry Andric if (isa<PoisonValue>(Operands[0]) || isa<PoisonValue>(Operands[1])) 28140fca6ea1SDimitry Andric return PoisonValue::get(Ty); 28150fca6ea1SDimitry Andric 28160fca6ea1SDimitry Andric if (!C0 || !C1) 28170fca6ea1SDimitry Andric return ConstantInt::get(Ty, 0); 28180fca6ea1SDimitry Andric 28190fca6ea1SDimitry Andric int Res; 28200fca6ea1SDimitry Andric if (IntrinsicID == Intrinsic::scmp) 28210fca6ea1SDimitry Andric Res = C0->sgt(*C1) ? 1 : C0->slt(*C1) ? -1 : 0; 28220fca6ea1SDimitry Andric else 28230fca6ea1SDimitry Andric Res = C0->ugt(*C1) ? 1 : C0->ult(*C1) ? -1 : 0; 28240fca6ea1SDimitry Andric return ConstantInt::get(Ty, Res, /*IsSigned=*/true); 28250fca6ea1SDimitry Andric 28268bcb0991SDimitry Andric case Intrinsic::usub_with_overflow: 28278bcb0991SDimitry Andric case Intrinsic::ssub_with_overflow: 2828fe6060f1SDimitry Andric // X - undef -> { 0, false } 2829fe6060f1SDimitry Andric // undef - X -> { 0, false } 2830fe6060f1SDimitry Andric if (!C0 || !C1) 2831fe6060f1SDimitry Andric return Constant::getNullValue(Ty); 2832bdd1243dSDimitry Andric [[fallthrough]]; 28338bcb0991SDimitry Andric case Intrinsic::uadd_with_overflow: 28348bcb0991SDimitry Andric case Intrinsic::sadd_with_overflow: 2835fe6060f1SDimitry Andric // X + undef -> { -1, false } 2836fe6060f1SDimitry Andric // undef + x -> { -1, false } 28378bcb0991SDimitry Andric if (!C0 || !C1) { 28388bcb0991SDimitry Andric return ConstantStruct::get( 28398bcb0991SDimitry Andric cast<StructType>(Ty), 2840fe6060f1SDimitry Andric {Constant::getAllOnesValue(Ty->getStructElementType(0)), 28418bcb0991SDimitry Andric Constant::getNullValue(Ty->getStructElementType(1))}); 28428bcb0991SDimitry Andric } 2843bdd1243dSDimitry Andric [[fallthrough]]; 28440b57cec5SDimitry Andric case Intrinsic::smul_with_overflow: 28458bcb0991SDimitry Andric case Intrinsic::umul_with_overflow: { 28468bcb0991SDimitry Andric // undef * X -> { 0, false } 28478bcb0991SDimitry Andric // X * undef -> { 0, false } 28480b57cec5SDimitry Andric if (!C0 || !C1) 28490b57cec5SDimitry Andric return Constant::getNullValue(Ty); 28500b57cec5SDimitry Andric 28510b57cec5SDimitry Andric APInt Res; 28520b57cec5SDimitry Andric bool Overflow; 28530b57cec5SDimitry Andric switch (IntrinsicID) { 28540b57cec5SDimitry Andric default: llvm_unreachable("Invalid case"); 28550b57cec5SDimitry Andric case Intrinsic::sadd_with_overflow: 28560b57cec5SDimitry Andric Res = C0->sadd_ov(*C1, Overflow); 28570b57cec5SDimitry Andric break; 28580b57cec5SDimitry Andric case Intrinsic::uadd_with_overflow: 28590b57cec5SDimitry Andric Res = C0->uadd_ov(*C1, Overflow); 28600b57cec5SDimitry Andric break; 28610b57cec5SDimitry Andric case Intrinsic::ssub_with_overflow: 28620b57cec5SDimitry Andric Res = C0->ssub_ov(*C1, Overflow); 28630b57cec5SDimitry Andric break; 28640b57cec5SDimitry Andric case Intrinsic::usub_with_overflow: 28650b57cec5SDimitry Andric Res = C0->usub_ov(*C1, Overflow); 28660b57cec5SDimitry Andric break; 28670b57cec5SDimitry Andric case Intrinsic::smul_with_overflow: 28680b57cec5SDimitry Andric Res = C0->smul_ov(*C1, Overflow); 28690b57cec5SDimitry Andric break; 28700b57cec5SDimitry Andric case Intrinsic::umul_with_overflow: 28710b57cec5SDimitry Andric Res = C0->umul_ov(*C1, Overflow); 28720b57cec5SDimitry Andric break; 28730b57cec5SDimitry Andric } 28740b57cec5SDimitry Andric Constant *Ops[] = { 28750b57cec5SDimitry Andric ConstantInt::get(Ty->getContext(), Res), 28760b57cec5SDimitry Andric ConstantInt::get(Type::getInt1Ty(Ty->getContext()), Overflow) 28770b57cec5SDimitry Andric }; 28780b57cec5SDimitry Andric return ConstantStruct::get(cast<StructType>(Ty), Ops); 28790b57cec5SDimitry Andric } 28800b57cec5SDimitry Andric case Intrinsic::uadd_sat: 28810b57cec5SDimitry Andric case Intrinsic::sadd_sat: 288281ad6265SDimitry Andric // This is the same as for binary ops - poison propagates. 288381ad6265SDimitry Andric // TODO: Poison handling should be consolidated. 288481ad6265SDimitry Andric if (isa<PoisonValue>(Operands[0]) || isa<PoisonValue>(Operands[1])) 288581ad6265SDimitry Andric return PoisonValue::get(Ty); 288681ad6265SDimitry Andric 28870b57cec5SDimitry Andric if (!C0 && !C1) 28880b57cec5SDimitry Andric return UndefValue::get(Ty); 28890b57cec5SDimitry Andric if (!C0 || !C1) 28900b57cec5SDimitry Andric return Constant::getAllOnesValue(Ty); 28910b57cec5SDimitry Andric if (IntrinsicID == Intrinsic::uadd_sat) 28920b57cec5SDimitry Andric return ConstantInt::get(Ty, C0->uadd_sat(*C1)); 28930b57cec5SDimitry Andric else 28940b57cec5SDimitry Andric return ConstantInt::get(Ty, C0->sadd_sat(*C1)); 28950b57cec5SDimitry Andric case Intrinsic::usub_sat: 28960b57cec5SDimitry Andric case Intrinsic::ssub_sat: 289781ad6265SDimitry Andric // This is the same as for binary ops - poison propagates. 289881ad6265SDimitry Andric // TODO: Poison handling should be consolidated. 289981ad6265SDimitry Andric if (isa<PoisonValue>(Operands[0]) || isa<PoisonValue>(Operands[1])) 290081ad6265SDimitry Andric return PoisonValue::get(Ty); 290181ad6265SDimitry Andric 29020b57cec5SDimitry Andric if (!C0 && !C1) 29030b57cec5SDimitry Andric return UndefValue::get(Ty); 29040b57cec5SDimitry Andric if (!C0 || !C1) 29050b57cec5SDimitry Andric return Constant::getNullValue(Ty); 29060b57cec5SDimitry Andric if (IntrinsicID == Intrinsic::usub_sat) 29070b57cec5SDimitry Andric return ConstantInt::get(Ty, C0->usub_sat(*C1)); 29080b57cec5SDimitry Andric else 29090b57cec5SDimitry Andric return ConstantInt::get(Ty, C0->ssub_sat(*C1)); 29100b57cec5SDimitry Andric case Intrinsic::cttz: 29110b57cec5SDimitry Andric case Intrinsic::ctlz: 29120b57cec5SDimitry Andric assert(C1 && "Must be constant int"); 29130b57cec5SDimitry Andric 291404eeddc0SDimitry Andric // cttz(0, 1) and ctlz(0, 1) are poison. 2915349cc55cSDimitry Andric if (C1->isOne() && (!C0 || C0->isZero())) 291604eeddc0SDimitry Andric return PoisonValue::get(Ty); 29170b57cec5SDimitry Andric if (!C0) 29180b57cec5SDimitry Andric return Constant::getNullValue(Ty); 29190b57cec5SDimitry Andric if (IntrinsicID == Intrinsic::cttz) 292006c3fb27SDimitry Andric return ConstantInt::get(Ty, C0->countr_zero()); 29210b57cec5SDimitry Andric else 292206c3fb27SDimitry Andric return ConstantInt::get(Ty, C0->countl_zero()); 2923e8d8bef9SDimitry Andric 2924e8d8bef9SDimitry Andric case Intrinsic::abs: 2925e8d8bef9SDimitry Andric assert(C1 && "Must be constant int"); 292604eeddc0SDimitry Andric assert((C1->isOne() || C1->isZero()) && "Must be 0 or 1"); 292704eeddc0SDimitry Andric 292804eeddc0SDimitry Andric // Undef or minimum val operand with poison min --> undef 2929349cc55cSDimitry Andric if (C1->isOne() && (!C0 || C0->isMinSignedValue())) 2930e8d8bef9SDimitry Andric return UndefValue::get(Ty); 2931e8d8bef9SDimitry Andric 2932e8d8bef9SDimitry Andric // Undef operand with no poison min --> 0 (sign bit must be clear) 293304eeddc0SDimitry Andric if (!C0) 2934e8d8bef9SDimitry Andric return Constant::getNullValue(Ty); 2935e8d8bef9SDimitry Andric 2936e8d8bef9SDimitry Andric return ConstantInt::get(Ty, C0->abs()); 29375f757f3fSDimitry Andric case Intrinsic::amdgcn_wave_reduce_umin: 29385f757f3fSDimitry Andric case Intrinsic::amdgcn_wave_reduce_umax: 29395f757f3fSDimitry Andric return dyn_cast<Constant>(Operands[0]); 29400b57cec5SDimitry Andric } 29410b57cec5SDimitry Andric 29420b57cec5SDimitry Andric return nullptr; 29430b57cec5SDimitry Andric } 29440b57cec5SDimitry Andric 29450b57cec5SDimitry Andric // Support ConstantVector in case we have an Undef in the top. 29460b57cec5SDimitry Andric if ((isa<ConstantVector>(Operands[0]) || 29470b57cec5SDimitry Andric isa<ConstantDataVector>(Operands[0])) && 29480b57cec5SDimitry Andric // Check for default rounding mode. 29490b57cec5SDimitry Andric // FIXME: Support other rounding modes? 29500b57cec5SDimitry Andric isa<ConstantInt>(Operands[1]) && 29510b57cec5SDimitry Andric cast<ConstantInt>(Operands[1])->getValue() == 4) { 29520b57cec5SDimitry Andric auto *Op = cast<Constant>(Operands[0]); 29530b57cec5SDimitry Andric switch (IntrinsicID) { 29540b57cec5SDimitry Andric default: break; 29550b57cec5SDimitry Andric case Intrinsic::x86_avx512_vcvtss2si32: 29560b57cec5SDimitry Andric case Intrinsic::x86_avx512_vcvtss2si64: 29570b57cec5SDimitry Andric case Intrinsic::x86_avx512_vcvtsd2si32: 29580b57cec5SDimitry Andric case Intrinsic::x86_avx512_vcvtsd2si64: 29590b57cec5SDimitry Andric if (ConstantFP *FPOp = 29600b57cec5SDimitry Andric dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U))) 29610b57cec5SDimitry Andric return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(), 29620b57cec5SDimitry Andric /*roundTowardZero=*/false, Ty, 29630b57cec5SDimitry Andric /*IsSigned*/true); 29640b57cec5SDimitry Andric break; 29650b57cec5SDimitry Andric case Intrinsic::x86_avx512_vcvtss2usi32: 29660b57cec5SDimitry Andric case Intrinsic::x86_avx512_vcvtss2usi64: 29670b57cec5SDimitry Andric case Intrinsic::x86_avx512_vcvtsd2usi32: 29680b57cec5SDimitry Andric case Intrinsic::x86_avx512_vcvtsd2usi64: 29690b57cec5SDimitry Andric if (ConstantFP *FPOp = 29700b57cec5SDimitry Andric dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U))) 29710b57cec5SDimitry Andric return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(), 29720b57cec5SDimitry Andric /*roundTowardZero=*/false, Ty, 29730b57cec5SDimitry Andric /*IsSigned*/false); 29740b57cec5SDimitry Andric break; 29750b57cec5SDimitry Andric case Intrinsic::x86_avx512_cvttss2si: 29760b57cec5SDimitry Andric case Intrinsic::x86_avx512_cvttss2si64: 29770b57cec5SDimitry Andric case Intrinsic::x86_avx512_cvttsd2si: 29780b57cec5SDimitry Andric case Intrinsic::x86_avx512_cvttsd2si64: 29790b57cec5SDimitry Andric if (ConstantFP *FPOp = 29800b57cec5SDimitry Andric dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U))) 29810b57cec5SDimitry Andric return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(), 29820b57cec5SDimitry Andric /*roundTowardZero=*/true, Ty, 29830b57cec5SDimitry Andric /*IsSigned*/true); 29840b57cec5SDimitry Andric break; 29850b57cec5SDimitry Andric case Intrinsic::x86_avx512_cvttss2usi: 29860b57cec5SDimitry Andric case Intrinsic::x86_avx512_cvttss2usi64: 29870b57cec5SDimitry Andric case Intrinsic::x86_avx512_cvttsd2usi: 29880b57cec5SDimitry Andric case Intrinsic::x86_avx512_cvttsd2usi64: 29890b57cec5SDimitry Andric if (ConstantFP *FPOp = 29900b57cec5SDimitry Andric dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U))) 29910b57cec5SDimitry Andric return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(), 29920b57cec5SDimitry Andric /*roundTowardZero=*/true, Ty, 29930b57cec5SDimitry Andric /*IsSigned*/false); 29940b57cec5SDimitry Andric break; 29950b57cec5SDimitry Andric } 29960b57cec5SDimitry Andric } 29970b57cec5SDimitry Andric return nullptr; 29980b57cec5SDimitry Andric } 29990b57cec5SDimitry Andric 30005ffd83dbSDimitry Andric static APFloat ConstantFoldAMDGCNCubeIntrinsic(Intrinsic::ID IntrinsicID, 30015ffd83dbSDimitry Andric const APFloat &S0, 30025ffd83dbSDimitry Andric const APFloat &S1, 30035ffd83dbSDimitry Andric const APFloat &S2) { 30045ffd83dbSDimitry Andric unsigned ID; 30055ffd83dbSDimitry Andric const fltSemantics &Sem = S0.getSemantics(); 30065ffd83dbSDimitry Andric APFloat MA(Sem), SC(Sem), TC(Sem); 30075ffd83dbSDimitry Andric if (abs(S2) >= abs(S0) && abs(S2) >= abs(S1)) { 30085ffd83dbSDimitry Andric if (S2.isNegative() && S2.isNonZero() && !S2.isNaN()) { 30095ffd83dbSDimitry Andric // S2 < 0 30105ffd83dbSDimitry Andric ID = 5; 30115ffd83dbSDimitry Andric SC = -S0; 30125ffd83dbSDimitry Andric } else { 30135ffd83dbSDimitry Andric ID = 4; 30145ffd83dbSDimitry Andric SC = S0; 30155ffd83dbSDimitry Andric } 30165ffd83dbSDimitry Andric MA = S2; 30175ffd83dbSDimitry Andric TC = -S1; 30185ffd83dbSDimitry Andric } else if (abs(S1) >= abs(S0)) { 30195ffd83dbSDimitry Andric if (S1.isNegative() && S1.isNonZero() && !S1.isNaN()) { 30205ffd83dbSDimitry Andric // S1 < 0 30215ffd83dbSDimitry Andric ID = 3; 30225ffd83dbSDimitry Andric TC = -S2; 30235ffd83dbSDimitry Andric } else { 30245ffd83dbSDimitry Andric ID = 2; 30255ffd83dbSDimitry Andric TC = S2; 30265ffd83dbSDimitry Andric } 30275ffd83dbSDimitry Andric MA = S1; 30285ffd83dbSDimitry Andric SC = S0; 30295ffd83dbSDimitry Andric } else { 30305ffd83dbSDimitry Andric if (S0.isNegative() && S0.isNonZero() && !S0.isNaN()) { 30315ffd83dbSDimitry Andric // S0 < 0 30325ffd83dbSDimitry Andric ID = 1; 30335ffd83dbSDimitry Andric SC = S2; 30345ffd83dbSDimitry Andric } else { 30355ffd83dbSDimitry Andric ID = 0; 30365ffd83dbSDimitry Andric SC = -S2; 30375ffd83dbSDimitry Andric } 30385ffd83dbSDimitry Andric MA = S0; 30395ffd83dbSDimitry Andric TC = -S1; 30405ffd83dbSDimitry Andric } 30415ffd83dbSDimitry Andric switch (IntrinsicID) { 30425ffd83dbSDimitry Andric default: 30435ffd83dbSDimitry Andric llvm_unreachable("unhandled amdgcn cube intrinsic"); 30445ffd83dbSDimitry Andric case Intrinsic::amdgcn_cubeid: 30455ffd83dbSDimitry Andric return APFloat(Sem, ID); 30465ffd83dbSDimitry Andric case Intrinsic::amdgcn_cubema: 30475ffd83dbSDimitry Andric return MA + MA; 30485ffd83dbSDimitry Andric case Intrinsic::amdgcn_cubesc: 30495ffd83dbSDimitry Andric return SC; 30505ffd83dbSDimitry Andric case Intrinsic::amdgcn_cubetc: 30515ffd83dbSDimitry Andric return TC; 30525ffd83dbSDimitry Andric } 30535ffd83dbSDimitry Andric } 30545ffd83dbSDimitry Andric 3055fe6060f1SDimitry Andric static Constant *ConstantFoldAMDGCNPermIntrinsic(ArrayRef<Constant *> Operands, 3056fe6060f1SDimitry Andric Type *Ty) { 3057fe6060f1SDimitry Andric const APInt *C0, *C1, *C2; 3058fe6060f1SDimitry Andric if (!getConstIntOrUndef(Operands[0], C0) || 3059fe6060f1SDimitry Andric !getConstIntOrUndef(Operands[1], C1) || 3060fe6060f1SDimitry Andric !getConstIntOrUndef(Operands[2], C2)) 3061fe6060f1SDimitry Andric return nullptr; 3062fe6060f1SDimitry Andric 3063fe6060f1SDimitry Andric if (!C2) 3064fe6060f1SDimitry Andric return UndefValue::get(Ty); 3065fe6060f1SDimitry Andric 3066fe6060f1SDimitry Andric APInt Val(32, 0); 3067fe6060f1SDimitry Andric unsigned NumUndefBytes = 0; 3068fe6060f1SDimitry Andric for (unsigned I = 0; I < 32; I += 8) { 3069fe6060f1SDimitry Andric unsigned Sel = C2->extractBitsAsZExtValue(8, I); 3070fe6060f1SDimitry Andric unsigned B = 0; 3071fe6060f1SDimitry Andric 3072fe6060f1SDimitry Andric if (Sel >= 13) 3073fe6060f1SDimitry Andric B = 0xff; 3074fe6060f1SDimitry Andric else if (Sel == 12) 3075fe6060f1SDimitry Andric B = 0x00; 3076fe6060f1SDimitry Andric else { 3077fe6060f1SDimitry Andric const APInt *Src = ((Sel & 10) == 10 || (Sel & 12) == 4) ? C0 : C1; 3078fe6060f1SDimitry Andric if (!Src) 3079fe6060f1SDimitry Andric ++NumUndefBytes; 3080fe6060f1SDimitry Andric else if (Sel < 8) 3081fe6060f1SDimitry Andric B = Src->extractBitsAsZExtValue(8, (Sel & 3) * 8); 3082fe6060f1SDimitry Andric else 3083fe6060f1SDimitry Andric B = Src->extractBitsAsZExtValue(1, (Sel & 1) ? 31 : 15) * 0xff; 3084fe6060f1SDimitry Andric } 3085fe6060f1SDimitry Andric 3086fe6060f1SDimitry Andric Val.insertBits(B, I, 8); 3087fe6060f1SDimitry Andric } 3088fe6060f1SDimitry Andric 3089fe6060f1SDimitry Andric if (NumUndefBytes == 4) 3090fe6060f1SDimitry Andric return UndefValue::get(Ty); 3091fe6060f1SDimitry Andric 3092fe6060f1SDimitry Andric return ConstantInt::get(Ty, Val); 3093fe6060f1SDimitry Andric } 3094fe6060f1SDimitry Andric 30950b57cec5SDimitry Andric static Constant *ConstantFoldScalarCall3(StringRef Name, 30960b57cec5SDimitry Andric Intrinsic::ID IntrinsicID, 30970b57cec5SDimitry Andric Type *Ty, 30980b57cec5SDimitry Andric ArrayRef<Constant *> Operands, 30990b57cec5SDimitry Andric const TargetLibraryInfo *TLI, 31000b57cec5SDimitry Andric const CallBase *Call) { 31010b57cec5SDimitry Andric assert(Operands.size() == 3 && "Wrong number of operands."); 31020b57cec5SDimitry Andric 31030b57cec5SDimitry Andric if (const auto *Op1 = dyn_cast<ConstantFP>(Operands[0])) { 31040b57cec5SDimitry Andric if (const auto *Op2 = dyn_cast<ConstantFP>(Operands[1])) { 31050b57cec5SDimitry Andric if (const auto *Op3 = dyn_cast<ConstantFP>(Operands[2])) { 3106fe6060f1SDimitry Andric const APFloat &C1 = Op1->getValueAPF(); 3107fe6060f1SDimitry Andric const APFloat &C2 = Op2->getValueAPF(); 3108fe6060f1SDimitry Andric const APFloat &C3 = Op3->getValueAPF(); 3109fe6060f1SDimitry Andric 3110fe6060f1SDimitry Andric if (const auto *ConstrIntr = dyn_cast<ConstrainedFPIntrinsic>(Call)) { 3111fe6060f1SDimitry Andric RoundingMode RM = getEvaluationRoundingMode(ConstrIntr); 3112fe6060f1SDimitry Andric APFloat Res = C1; 3113fe6060f1SDimitry Andric APFloat::opStatus St; 3114fe6060f1SDimitry Andric switch (IntrinsicID) { 3115fe6060f1SDimitry Andric default: 3116fe6060f1SDimitry Andric return nullptr; 3117fe6060f1SDimitry Andric case Intrinsic::experimental_constrained_fma: 3118fe6060f1SDimitry Andric case Intrinsic::experimental_constrained_fmuladd: 3119fe6060f1SDimitry Andric St = Res.fusedMultiplyAdd(C2, C3, RM); 3120fe6060f1SDimitry Andric break; 3121fe6060f1SDimitry Andric } 3122fe6060f1SDimitry Andric if (mayFoldConstrained( 3123fe6060f1SDimitry Andric const_cast<ConstrainedFPIntrinsic *>(ConstrIntr), St)) 3124fe6060f1SDimitry Andric return ConstantFP::get(Ty->getContext(), Res); 3125fe6060f1SDimitry Andric return nullptr; 3126fe6060f1SDimitry Andric } 3127fe6060f1SDimitry Andric 31280b57cec5SDimitry Andric switch (IntrinsicID) { 31290b57cec5SDimitry Andric default: break; 3130e8d8bef9SDimitry Andric case Intrinsic::amdgcn_fma_legacy: { 3131e8d8bef9SDimitry Andric // The legacy behaviour is that multiplying +/- 0.0 by anything, even 3132e8d8bef9SDimitry Andric // NaN or infinity, gives +0.0. 3133e8d8bef9SDimitry Andric if (C1.isZero() || C2.isZero()) { 3134e8d8bef9SDimitry Andric // It's tempting to just return C3 here, but that would give the 3135e8d8bef9SDimitry Andric // wrong result if C3 was -0.0. 3136e8d8bef9SDimitry Andric return ConstantFP::get(Ty->getContext(), APFloat(0.0f) + C3); 3137e8d8bef9SDimitry Andric } 3138bdd1243dSDimitry Andric [[fallthrough]]; 3139e8d8bef9SDimitry Andric } 31400b57cec5SDimitry Andric case Intrinsic::fma: 31410b57cec5SDimitry Andric case Intrinsic::fmuladd: { 3142fe6060f1SDimitry Andric APFloat V = C1; 3143fe6060f1SDimitry Andric V.fusedMultiplyAdd(C2, C3, APFloat::rmNearestTiesToEven); 31440b57cec5SDimitry Andric return ConstantFP::get(Ty->getContext(), V); 31450b57cec5SDimitry Andric } 31465ffd83dbSDimitry Andric case Intrinsic::amdgcn_cubeid: 31475ffd83dbSDimitry Andric case Intrinsic::amdgcn_cubema: 31485ffd83dbSDimitry Andric case Intrinsic::amdgcn_cubesc: 31495ffd83dbSDimitry Andric case Intrinsic::amdgcn_cubetc: { 3150fe6060f1SDimitry Andric APFloat V = ConstantFoldAMDGCNCubeIntrinsic(IntrinsicID, C1, C2, C3); 31515ffd83dbSDimitry Andric return ConstantFP::get(Ty->getContext(), V); 31525ffd83dbSDimitry Andric } 31530b57cec5SDimitry Andric } 31540b57cec5SDimitry Andric } 31550b57cec5SDimitry Andric } 31560b57cec5SDimitry Andric } 31570b57cec5SDimitry Andric 3158fe6060f1SDimitry Andric if (IntrinsicID == Intrinsic::smul_fix || 3159fe6060f1SDimitry Andric IntrinsicID == Intrinsic::smul_fix_sat) { 3160fe6060f1SDimitry Andric // poison * C -> poison 3161fe6060f1SDimitry Andric // C * poison -> poison 3162fe6060f1SDimitry Andric if (isa<PoisonValue>(Operands[0]) || isa<PoisonValue>(Operands[1])) 3163fe6060f1SDimitry Andric return PoisonValue::get(Ty); 3164fe6060f1SDimitry Andric 3165fe6060f1SDimitry Andric const APInt *C0, *C1; 3166fe6060f1SDimitry Andric if (!getConstIntOrUndef(Operands[0], C0) || 3167fe6060f1SDimitry Andric !getConstIntOrUndef(Operands[1], C1)) 3168fe6060f1SDimitry Andric return nullptr; 3169fe6060f1SDimitry Andric 3170fe6060f1SDimitry Andric // undef * C -> 0 3171fe6060f1SDimitry Andric // C * undef -> 0 3172fe6060f1SDimitry Andric if (!C0 || !C1) 3173fe6060f1SDimitry Andric return Constant::getNullValue(Ty); 3174fe6060f1SDimitry Andric 3175fe6060f1SDimitry Andric // This code performs rounding towards negative infinity in case the result 3176fe6060f1SDimitry Andric // cannot be represented exactly for the given scale. Targets that do care 3177fe6060f1SDimitry Andric // about rounding should use a target hook for specifying how rounding 3178fe6060f1SDimitry Andric // should be done, and provide their own folding to be consistent with 3179fe6060f1SDimitry Andric // rounding. This is the same approach as used by 31800b57cec5SDimitry Andric // DAGTypeLegalizer::ExpandIntRes_MULFIX. 3181fe6060f1SDimitry Andric unsigned Scale = cast<ConstantInt>(Operands[2])->getZExtValue(); 3182fe6060f1SDimitry Andric unsigned Width = C0->getBitWidth(); 31830b57cec5SDimitry Andric assert(Scale < Width && "Illegal scale."); 31840b57cec5SDimitry Andric unsigned ExtendedWidth = Width * 2; 318581ad6265SDimitry Andric APInt Product = 318681ad6265SDimitry Andric (C0->sext(ExtendedWidth) * C1->sext(ExtendedWidth)).ashr(Scale); 31870b57cec5SDimitry Andric if (IntrinsicID == Intrinsic::smul_fix_sat) { 318881ad6265SDimitry Andric APInt Max = APInt::getSignedMaxValue(Width).sext(ExtendedWidth); 318981ad6265SDimitry Andric APInt Min = APInt::getSignedMinValue(Width).sext(ExtendedWidth); 3190fe6060f1SDimitry Andric Product = APIntOps::smin(Product, Max); 3191fe6060f1SDimitry Andric Product = APIntOps::smax(Product, Min); 31920b57cec5SDimitry Andric } 3193fe6060f1SDimitry Andric return ConstantInt::get(Ty->getContext(), Product.sextOrTrunc(Width)); 31940b57cec5SDimitry Andric } 31950b57cec5SDimitry Andric 31960b57cec5SDimitry Andric if (IntrinsicID == Intrinsic::fshl || IntrinsicID == Intrinsic::fshr) { 31970b57cec5SDimitry Andric const APInt *C0, *C1, *C2; 31980b57cec5SDimitry Andric if (!getConstIntOrUndef(Operands[0], C0) || 31990b57cec5SDimitry Andric !getConstIntOrUndef(Operands[1], C1) || 32000b57cec5SDimitry Andric !getConstIntOrUndef(Operands[2], C2)) 32010b57cec5SDimitry Andric return nullptr; 32020b57cec5SDimitry Andric 32030b57cec5SDimitry Andric bool IsRight = IntrinsicID == Intrinsic::fshr; 32040b57cec5SDimitry Andric if (!C2) 32050b57cec5SDimitry Andric return Operands[IsRight ? 1 : 0]; 32060b57cec5SDimitry Andric if (!C0 && !C1) 32070b57cec5SDimitry Andric return UndefValue::get(Ty); 32080b57cec5SDimitry Andric 32090b57cec5SDimitry Andric // The shift amount is interpreted as modulo the bitwidth. If the shift 32100b57cec5SDimitry Andric // amount is effectively 0, avoid UB due to oversized inverse shift below. 32110b57cec5SDimitry Andric unsigned BitWidth = C2->getBitWidth(); 32120b57cec5SDimitry Andric unsigned ShAmt = C2->urem(BitWidth); 32130b57cec5SDimitry Andric if (!ShAmt) 32140b57cec5SDimitry Andric return Operands[IsRight ? 1 : 0]; 32150b57cec5SDimitry Andric 32160b57cec5SDimitry Andric // (C0 << ShlAmt) | (C1 >> LshrAmt) 32170b57cec5SDimitry Andric unsigned LshrAmt = IsRight ? ShAmt : BitWidth - ShAmt; 32180b57cec5SDimitry Andric unsigned ShlAmt = !IsRight ? ShAmt : BitWidth - ShAmt; 32190b57cec5SDimitry Andric if (!C0) 32200b57cec5SDimitry Andric return ConstantInt::get(Ty, C1->lshr(LshrAmt)); 32210b57cec5SDimitry Andric if (!C1) 32220b57cec5SDimitry Andric return ConstantInt::get(Ty, C0->shl(ShlAmt)); 32230b57cec5SDimitry Andric return ConstantInt::get(Ty, C0->shl(ShlAmt) | C1->lshr(LshrAmt)); 32240b57cec5SDimitry Andric } 32250b57cec5SDimitry Andric 3226fe6060f1SDimitry Andric if (IntrinsicID == Intrinsic::amdgcn_perm) 3227fe6060f1SDimitry Andric return ConstantFoldAMDGCNPermIntrinsic(Operands, Ty); 3228fe6060f1SDimitry Andric 32290b57cec5SDimitry Andric return nullptr; 32300b57cec5SDimitry Andric } 32310b57cec5SDimitry Andric 32320b57cec5SDimitry Andric static Constant *ConstantFoldScalarCall(StringRef Name, 32330b57cec5SDimitry Andric Intrinsic::ID IntrinsicID, 32340b57cec5SDimitry Andric Type *Ty, 32350b57cec5SDimitry Andric ArrayRef<Constant *> Operands, 32360b57cec5SDimitry Andric const TargetLibraryInfo *TLI, 32370b57cec5SDimitry Andric const CallBase *Call) { 32380b57cec5SDimitry Andric if (Operands.size() == 1) 32390b57cec5SDimitry Andric return ConstantFoldScalarCall1(Name, IntrinsicID, Ty, Operands, TLI, Call); 32400b57cec5SDimitry Andric 32410fca6ea1SDimitry Andric if (Operands.size() == 2) { 32420fca6ea1SDimitry Andric if (Constant *FoldedLibCall = 32430fca6ea1SDimitry Andric ConstantFoldLibCall2(Name, Ty, Operands, TLI)) { 32440fca6ea1SDimitry Andric return FoldedLibCall; 32450fca6ea1SDimitry Andric } 32460fca6ea1SDimitry Andric return ConstantFoldIntrinsicCall2(IntrinsicID, Ty, Operands, Call); 32470fca6ea1SDimitry Andric } 32480b57cec5SDimitry Andric 32490b57cec5SDimitry Andric if (Operands.size() == 3) 32500b57cec5SDimitry Andric return ConstantFoldScalarCall3(Name, IntrinsicID, Ty, Operands, TLI, Call); 32510b57cec5SDimitry Andric 32520b57cec5SDimitry Andric return nullptr; 32530b57cec5SDimitry Andric } 32540b57cec5SDimitry Andric 3255fe6060f1SDimitry Andric static Constant *ConstantFoldFixedVectorCall( 3256fe6060f1SDimitry Andric StringRef Name, Intrinsic::ID IntrinsicID, FixedVectorType *FVTy, 3257fe6060f1SDimitry Andric ArrayRef<Constant *> Operands, const DataLayout &DL, 3258fe6060f1SDimitry Andric const TargetLibraryInfo *TLI, const CallBase *Call) { 32595ffd83dbSDimitry Andric SmallVector<Constant *, 4> Result(FVTy->getNumElements()); 32600b57cec5SDimitry Andric SmallVector<Constant *, 4> Lane(Operands.size()); 32615ffd83dbSDimitry Andric Type *Ty = FVTy->getElementType(); 32620b57cec5SDimitry Andric 3263e8d8bef9SDimitry Andric switch (IntrinsicID) { 3264e8d8bef9SDimitry Andric case Intrinsic::masked_load: { 32650b57cec5SDimitry Andric auto *SrcPtr = Operands[0]; 32660b57cec5SDimitry Andric auto *Mask = Operands[2]; 32670b57cec5SDimitry Andric auto *Passthru = Operands[3]; 32680b57cec5SDimitry Andric 32695ffd83dbSDimitry Andric Constant *VecData = ConstantFoldLoadFromConstPtr(SrcPtr, FVTy, DL); 32700b57cec5SDimitry Andric 32710b57cec5SDimitry Andric SmallVector<Constant *, 32> NewElements; 32725ffd83dbSDimitry Andric for (unsigned I = 0, E = FVTy->getNumElements(); I != E; ++I) { 32730b57cec5SDimitry Andric auto *MaskElt = Mask->getAggregateElement(I); 32740b57cec5SDimitry Andric if (!MaskElt) 32750b57cec5SDimitry Andric break; 32760b57cec5SDimitry Andric auto *PassthruElt = Passthru->getAggregateElement(I); 32770b57cec5SDimitry Andric auto *VecElt = VecData ? VecData->getAggregateElement(I) : nullptr; 32780b57cec5SDimitry Andric if (isa<UndefValue>(MaskElt)) { 32790b57cec5SDimitry Andric if (PassthruElt) 32800b57cec5SDimitry Andric NewElements.push_back(PassthruElt); 32810b57cec5SDimitry Andric else if (VecElt) 32820b57cec5SDimitry Andric NewElements.push_back(VecElt); 32830b57cec5SDimitry Andric else 32840b57cec5SDimitry Andric return nullptr; 32850b57cec5SDimitry Andric } 32860b57cec5SDimitry Andric if (MaskElt->isNullValue()) { 32870b57cec5SDimitry Andric if (!PassthruElt) 32880b57cec5SDimitry Andric return nullptr; 32890b57cec5SDimitry Andric NewElements.push_back(PassthruElt); 32900b57cec5SDimitry Andric } else if (MaskElt->isOneValue()) { 32910b57cec5SDimitry Andric if (!VecElt) 32920b57cec5SDimitry Andric return nullptr; 32930b57cec5SDimitry Andric NewElements.push_back(VecElt); 32940b57cec5SDimitry Andric } else { 32950b57cec5SDimitry Andric return nullptr; 32960b57cec5SDimitry Andric } 32970b57cec5SDimitry Andric } 32985ffd83dbSDimitry Andric if (NewElements.size() != FVTy->getNumElements()) 32990b57cec5SDimitry Andric return nullptr; 33000b57cec5SDimitry Andric return ConstantVector::get(NewElements); 33010b57cec5SDimitry Andric } 3302e8d8bef9SDimitry Andric case Intrinsic::arm_mve_vctp8: 3303e8d8bef9SDimitry Andric case Intrinsic::arm_mve_vctp16: 3304e8d8bef9SDimitry Andric case Intrinsic::arm_mve_vctp32: 3305e8d8bef9SDimitry Andric case Intrinsic::arm_mve_vctp64: { 3306e8d8bef9SDimitry Andric if (auto *Op = dyn_cast<ConstantInt>(Operands[0])) { 3307e8d8bef9SDimitry Andric unsigned Lanes = FVTy->getNumElements(); 3308e8d8bef9SDimitry Andric uint64_t Limit = Op->getZExtValue(); 3309e8d8bef9SDimitry Andric 3310e8d8bef9SDimitry Andric SmallVector<Constant *, 16> NCs; 3311e8d8bef9SDimitry Andric for (unsigned i = 0; i < Lanes; i++) { 3312e8d8bef9SDimitry Andric if (i < Limit) 3313e8d8bef9SDimitry Andric NCs.push_back(ConstantInt::getTrue(Ty)); 3314e8d8bef9SDimitry Andric else 3315e8d8bef9SDimitry Andric NCs.push_back(ConstantInt::getFalse(Ty)); 3316e8d8bef9SDimitry Andric } 3317e8d8bef9SDimitry Andric return ConstantVector::get(NCs); 3318e8d8bef9SDimitry Andric } 331961cfbce3SDimitry Andric return nullptr; 3320e8d8bef9SDimitry Andric } 3321e8d8bef9SDimitry Andric case Intrinsic::get_active_lane_mask: { 3322e8d8bef9SDimitry Andric auto *Op0 = dyn_cast<ConstantInt>(Operands[0]); 3323e8d8bef9SDimitry Andric auto *Op1 = dyn_cast<ConstantInt>(Operands[1]); 3324e8d8bef9SDimitry Andric if (Op0 && Op1) { 3325e8d8bef9SDimitry Andric unsigned Lanes = FVTy->getNumElements(); 3326e8d8bef9SDimitry Andric uint64_t Base = Op0->getZExtValue(); 3327e8d8bef9SDimitry Andric uint64_t Limit = Op1->getZExtValue(); 3328e8d8bef9SDimitry Andric 3329e8d8bef9SDimitry Andric SmallVector<Constant *, 16> NCs; 3330e8d8bef9SDimitry Andric for (unsigned i = 0; i < Lanes; i++) { 3331e8d8bef9SDimitry Andric if (Base + i < Limit) 3332e8d8bef9SDimitry Andric NCs.push_back(ConstantInt::getTrue(Ty)); 3333e8d8bef9SDimitry Andric else 3334e8d8bef9SDimitry Andric NCs.push_back(ConstantInt::getFalse(Ty)); 3335e8d8bef9SDimitry Andric } 3336e8d8bef9SDimitry Andric return ConstantVector::get(NCs); 3337e8d8bef9SDimitry Andric } 333861cfbce3SDimitry Andric return nullptr; 3339e8d8bef9SDimitry Andric } 3340e8d8bef9SDimitry Andric default: 3341e8d8bef9SDimitry Andric break; 3342e8d8bef9SDimitry Andric } 33430b57cec5SDimitry Andric 33445ffd83dbSDimitry Andric for (unsigned I = 0, E = FVTy->getNumElements(); I != E; ++I) { 33450b57cec5SDimitry Andric // Gather a column of constants. 33460b57cec5SDimitry Andric for (unsigned J = 0, JE = Operands.size(); J != JE; ++J) { 33470b57cec5SDimitry Andric // Some intrinsics use a scalar type for certain arguments. 334881ad6265SDimitry Andric if (isVectorIntrinsicWithScalarOpAtArg(IntrinsicID, J)) { 33490b57cec5SDimitry Andric Lane[J] = Operands[J]; 33500b57cec5SDimitry Andric continue; 33510b57cec5SDimitry Andric } 33520b57cec5SDimitry Andric 33530b57cec5SDimitry Andric Constant *Agg = Operands[J]->getAggregateElement(I); 33540b57cec5SDimitry Andric if (!Agg) 33550b57cec5SDimitry Andric return nullptr; 33560b57cec5SDimitry Andric 33570b57cec5SDimitry Andric Lane[J] = Agg; 33580b57cec5SDimitry Andric } 33590b57cec5SDimitry Andric 33600b57cec5SDimitry Andric // Use the regular scalar folding to simplify this column. 33610b57cec5SDimitry Andric Constant *Folded = 33620b57cec5SDimitry Andric ConstantFoldScalarCall(Name, IntrinsicID, Ty, Lane, TLI, Call); 33630b57cec5SDimitry Andric if (!Folded) 33640b57cec5SDimitry Andric return nullptr; 33650b57cec5SDimitry Andric Result[I] = Folded; 33660b57cec5SDimitry Andric } 33670b57cec5SDimitry Andric 33680b57cec5SDimitry Andric return ConstantVector::get(Result); 33690b57cec5SDimitry Andric } 33700b57cec5SDimitry Andric 3371fe6060f1SDimitry Andric static Constant *ConstantFoldScalableVectorCall( 3372fe6060f1SDimitry Andric StringRef Name, Intrinsic::ID IntrinsicID, ScalableVectorType *SVTy, 3373fe6060f1SDimitry Andric ArrayRef<Constant *> Operands, const DataLayout &DL, 3374fe6060f1SDimitry Andric const TargetLibraryInfo *TLI, const CallBase *Call) { 3375fe6060f1SDimitry Andric switch (IntrinsicID) { 3376fe6060f1SDimitry Andric case Intrinsic::aarch64_sve_convert_from_svbool: { 3377fe6060f1SDimitry Andric auto *Src = dyn_cast<Constant>(Operands[0]); 3378fe6060f1SDimitry Andric if (!Src || !Src->isNullValue()) 3379fe6060f1SDimitry Andric break; 3380fe6060f1SDimitry Andric 3381fe6060f1SDimitry Andric return ConstantInt::getFalse(SVTy); 3382fe6060f1SDimitry Andric } 3383fe6060f1SDimitry Andric default: 3384fe6060f1SDimitry Andric break; 3385fe6060f1SDimitry Andric } 3386fe6060f1SDimitry Andric return nullptr; 3387fe6060f1SDimitry Andric } 3388fe6060f1SDimitry Andric 338906c3fb27SDimitry Andric static std::pair<Constant *, Constant *> 339006c3fb27SDimitry Andric ConstantFoldScalarFrexpCall(Constant *Op, Type *IntTy) { 339106c3fb27SDimitry Andric if (isa<PoisonValue>(Op)) 339206c3fb27SDimitry Andric return {Op, PoisonValue::get(IntTy)}; 339306c3fb27SDimitry Andric 339406c3fb27SDimitry Andric auto *ConstFP = dyn_cast<ConstantFP>(Op); 339506c3fb27SDimitry Andric if (!ConstFP) 339606c3fb27SDimitry Andric return {}; 339706c3fb27SDimitry Andric 339806c3fb27SDimitry Andric const APFloat &U = ConstFP->getValueAPF(); 339906c3fb27SDimitry Andric int FrexpExp; 340006c3fb27SDimitry Andric APFloat FrexpMant = frexp(U, FrexpExp, APFloat::rmNearestTiesToEven); 340106c3fb27SDimitry Andric Constant *Result0 = ConstantFP::get(ConstFP->getType(), FrexpMant); 340206c3fb27SDimitry Andric 340306c3fb27SDimitry Andric // The exponent is an "unspecified value" for inf/nan. We use zero to avoid 340406c3fb27SDimitry Andric // using undef. 340506c3fb27SDimitry Andric Constant *Result1 = FrexpMant.isFinite() ? ConstantInt::get(IntTy, FrexpExp) 340606c3fb27SDimitry Andric : ConstantInt::getNullValue(IntTy); 340706c3fb27SDimitry Andric return {Result0, Result1}; 340806c3fb27SDimitry Andric } 340906c3fb27SDimitry Andric 341006c3fb27SDimitry Andric /// Handle intrinsics that return tuples, which may be tuples of vectors. 341106c3fb27SDimitry Andric static Constant * 341206c3fb27SDimitry Andric ConstantFoldStructCall(StringRef Name, Intrinsic::ID IntrinsicID, 341306c3fb27SDimitry Andric StructType *StTy, ArrayRef<Constant *> Operands, 341406c3fb27SDimitry Andric const DataLayout &DL, const TargetLibraryInfo *TLI, 341506c3fb27SDimitry Andric const CallBase *Call) { 341606c3fb27SDimitry Andric 341706c3fb27SDimitry Andric switch (IntrinsicID) { 341806c3fb27SDimitry Andric case Intrinsic::frexp: { 341906c3fb27SDimitry Andric Type *Ty0 = StTy->getContainedType(0); 342006c3fb27SDimitry Andric Type *Ty1 = StTy->getContainedType(1)->getScalarType(); 342106c3fb27SDimitry Andric 342206c3fb27SDimitry Andric if (auto *FVTy0 = dyn_cast<FixedVectorType>(Ty0)) { 342306c3fb27SDimitry Andric SmallVector<Constant *, 4> Results0(FVTy0->getNumElements()); 342406c3fb27SDimitry Andric SmallVector<Constant *, 4> Results1(FVTy0->getNumElements()); 342506c3fb27SDimitry Andric 342606c3fb27SDimitry Andric for (unsigned I = 0, E = FVTy0->getNumElements(); I != E; ++I) { 342706c3fb27SDimitry Andric Constant *Lane = Operands[0]->getAggregateElement(I); 342806c3fb27SDimitry Andric std::tie(Results0[I], Results1[I]) = 342906c3fb27SDimitry Andric ConstantFoldScalarFrexpCall(Lane, Ty1); 343006c3fb27SDimitry Andric if (!Results0[I]) 343106c3fb27SDimitry Andric return nullptr; 343206c3fb27SDimitry Andric } 343306c3fb27SDimitry Andric 343406c3fb27SDimitry Andric return ConstantStruct::get(StTy, ConstantVector::get(Results0), 343506c3fb27SDimitry Andric ConstantVector::get(Results1)); 343606c3fb27SDimitry Andric } 343706c3fb27SDimitry Andric 343806c3fb27SDimitry Andric auto [Result0, Result1] = ConstantFoldScalarFrexpCall(Operands[0], Ty1); 343906c3fb27SDimitry Andric if (!Result0) 344006c3fb27SDimitry Andric return nullptr; 344106c3fb27SDimitry Andric return ConstantStruct::get(StTy, Result0, Result1); 344206c3fb27SDimitry Andric } 344306c3fb27SDimitry Andric default: 344406c3fb27SDimitry Andric // TODO: Constant folding of vector intrinsics that fall through here does 344506c3fb27SDimitry Andric // not work (e.g. overflow intrinsics) 344606c3fb27SDimitry Andric return ConstantFoldScalarCall(Name, IntrinsicID, StTy, Operands, TLI, Call); 344706c3fb27SDimitry Andric } 344806c3fb27SDimitry Andric 344906c3fb27SDimitry Andric return nullptr; 345006c3fb27SDimitry Andric } 345106c3fb27SDimitry Andric 34520b57cec5SDimitry Andric } // end anonymous namespace 34530b57cec5SDimitry Andric 34540fca6ea1SDimitry Andric Constant *llvm::ConstantFoldBinaryIntrinsic(Intrinsic::ID ID, Constant *LHS, 34550fca6ea1SDimitry Andric Constant *RHS, Type *Ty, 34560fca6ea1SDimitry Andric Instruction *FMFSource) { 34570fca6ea1SDimitry Andric return ConstantFoldIntrinsicCall2(ID, Ty, {LHS, RHS}, 34580fca6ea1SDimitry Andric dyn_cast_if_present<CallBase>(FMFSource)); 34590fca6ea1SDimitry Andric } 34600fca6ea1SDimitry Andric 34610b57cec5SDimitry Andric Constant *llvm::ConstantFoldCall(const CallBase *Call, Function *F, 34620b57cec5SDimitry Andric ArrayRef<Constant *> Operands, 34630fca6ea1SDimitry Andric const TargetLibraryInfo *TLI, 34640fca6ea1SDimitry Andric bool AllowNonDeterministic) { 34655ffd83dbSDimitry Andric if (Call->isNoBuiltin()) 34660b57cec5SDimitry Andric return nullptr; 34670b57cec5SDimitry Andric if (!F->hasName()) 34680b57cec5SDimitry Andric return nullptr; 3469fe6060f1SDimitry Andric 3470fe6060f1SDimitry Andric // If this is not an intrinsic and not recognized as a library call, bail out. 347106c3fb27SDimitry Andric Intrinsic::ID IID = F->getIntrinsicID(); 347206c3fb27SDimitry Andric if (IID == Intrinsic::not_intrinsic) { 3473fe6060f1SDimitry Andric if (!TLI) 3474fe6060f1SDimitry Andric return nullptr; 3475fe6060f1SDimitry Andric LibFunc LibF; 3476fe6060f1SDimitry Andric if (!TLI->getLibFunc(*F, LibF)) 3477fe6060f1SDimitry Andric return nullptr; 3478fe6060f1SDimitry Andric } 3479fe6060f1SDimitry Andric 34800fca6ea1SDimitry Andric // Conservatively assume that floating-point libcalls may be 34810fca6ea1SDimitry Andric // non-deterministic. 34820b57cec5SDimitry Andric Type *Ty = F->getReturnType(); 34830fca6ea1SDimitry Andric if (!AllowNonDeterministic && Ty->isFPOrFPVectorTy()) 34840fca6ea1SDimitry Andric return nullptr; 34850fca6ea1SDimitry Andric 34860fca6ea1SDimitry Andric StringRef Name = F->getName(); 3487fe6060f1SDimitry Andric if (auto *FVTy = dyn_cast<FixedVectorType>(Ty)) 3488fe6060f1SDimitry Andric return ConstantFoldFixedVectorCall( 34890fca6ea1SDimitry Andric Name, IID, FVTy, Operands, F->getDataLayout(), TLI, Call); 34900b57cec5SDimitry Andric 3491fe6060f1SDimitry Andric if (auto *SVTy = dyn_cast<ScalableVectorType>(Ty)) 3492fe6060f1SDimitry Andric return ConstantFoldScalableVectorCall( 34930fca6ea1SDimitry Andric Name, IID, SVTy, Operands, F->getDataLayout(), TLI, Call); 349406c3fb27SDimitry Andric 349506c3fb27SDimitry Andric if (auto *StTy = dyn_cast<StructType>(Ty)) 349606c3fb27SDimitry Andric return ConstantFoldStructCall(Name, IID, StTy, Operands, 34970fca6ea1SDimitry Andric F->getDataLayout(), TLI, Call); 3498fe6060f1SDimitry Andric 3499fe6060f1SDimitry Andric // TODO: If this is a library function, we already discovered that above, 3500fe6060f1SDimitry Andric // so we should pass the LibFunc, not the name (and it might be better 3501fe6060f1SDimitry Andric // still to separate intrinsic handling from libcalls). 350206c3fb27SDimitry Andric return ConstantFoldScalarCall(Name, IID, Ty, Operands, TLI, Call); 35030b57cec5SDimitry Andric } 35040b57cec5SDimitry Andric 35050b57cec5SDimitry Andric bool llvm::isMathLibCallNoop(const CallBase *Call, 35060b57cec5SDimitry Andric const TargetLibraryInfo *TLI) { 35070b57cec5SDimitry Andric // FIXME: Refactor this code; this duplicates logic in LibCallsShrinkWrap 35080b57cec5SDimitry Andric // (and to some extent ConstantFoldScalarCall). 35090b57cec5SDimitry Andric if (Call->isNoBuiltin() || Call->isStrictFP()) 35100b57cec5SDimitry Andric return false; 35110b57cec5SDimitry Andric Function *F = Call->getCalledFunction(); 35120b57cec5SDimitry Andric if (!F) 35130b57cec5SDimitry Andric return false; 35140b57cec5SDimitry Andric 35150b57cec5SDimitry Andric LibFunc Func; 35160b57cec5SDimitry Andric if (!TLI || !TLI->getLibFunc(*F, Func)) 35170b57cec5SDimitry Andric return false; 35180b57cec5SDimitry Andric 3519349cc55cSDimitry Andric if (Call->arg_size() == 1) { 35200b57cec5SDimitry Andric if (ConstantFP *OpC = dyn_cast<ConstantFP>(Call->getArgOperand(0))) { 35210b57cec5SDimitry Andric const APFloat &Op = OpC->getValueAPF(); 35220b57cec5SDimitry Andric switch (Func) { 35230b57cec5SDimitry Andric case LibFunc_logl: 35240b57cec5SDimitry Andric case LibFunc_log: 35250b57cec5SDimitry Andric case LibFunc_logf: 35260b57cec5SDimitry Andric case LibFunc_log2l: 35270b57cec5SDimitry Andric case LibFunc_log2: 35280b57cec5SDimitry Andric case LibFunc_log2f: 35290b57cec5SDimitry Andric case LibFunc_log10l: 35300b57cec5SDimitry Andric case LibFunc_log10: 35310b57cec5SDimitry Andric case LibFunc_log10f: 35320b57cec5SDimitry Andric return Op.isNaN() || (!Op.isZero() && !Op.isNegative()); 35330b57cec5SDimitry Andric 35340b57cec5SDimitry Andric case LibFunc_expl: 35350b57cec5SDimitry Andric case LibFunc_exp: 35360b57cec5SDimitry Andric case LibFunc_expf: 35370b57cec5SDimitry Andric // FIXME: These boundaries are slightly conservative. 35380b57cec5SDimitry Andric if (OpC->getType()->isDoubleTy()) 35395ffd83dbSDimitry Andric return !(Op < APFloat(-745.0) || Op > APFloat(709.0)); 35400b57cec5SDimitry Andric if (OpC->getType()->isFloatTy()) 35415ffd83dbSDimitry Andric return !(Op < APFloat(-103.0f) || Op > APFloat(88.0f)); 35420b57cec5SDimitry Andric break; 35430b57cec5SDimitry Andric 35440b57cec5SDimitry Andric case LibFunc_exp2l: 35450b57cec5SDimitry Andric case LibFunc_exp2: 35460b57cec5SDimitry Andric case LibFunc_exp2f: 35470b57cec5SDimitry Andric // FIXME: These boundaries are slightly conservative. 35480b57cec5SDimitry Andric if (OpC->getType()->isDoubleTy()) 35495ffd83dbSDimitry Andric return !(Op < APFloat(-1074.0) || Op > APFloat(1023.0)); 35500b57cec5SDimitry Andric if (OpC->getType()->isFloatTy()) 35515ffd83dbSDimitry Andric return !(Op < APFloat(-149.0f) || Op > APFloat(127.0f)); 35520b57cec5SDimitry Andric break; 35530b57cec5SDimitry Andric 35540b57cec5SDimitry Andric case LibFunc_sinl: 35550b57cec5SDimitry Andric case LibFunc_sin: 35560b57cec5SDimitry Andric case LibFunc_sinf: 35570b57cec5SDimitry Andric case LibFunc_cosl: 35580b57cec5SDimitry Andric case LibFunc_cos: 35590b57cec5SDimitry Andric case LibFunc_cosf: 35600b57cec5SDimitry Andric return !Op.isInfinity(); 35610b57cec5SDimitry Andric 35620b57cec5SDimitry Andric case LibFunc_tanl: 35630b57cec5SDimitry Andric case LibFunc_tan: 35640b57cec5SDimitry Andric case LibFunc_tanf: { 35650b57cec5SDimitry Andric // FIXME: Stop using the host math library. 35660b57cec5SDimitry Andric // FIXME: The computation isn't done in the right precision. 35670b57cec5SDimitry Andric Type *Ty = OpC->getType(); 3568fe6060f1SDimitry Andric if (Ty->isDoubleTy() || Ty->isFloatTy() || Ty->isHalfTy()) 3569fe6060f1SDimitry Andric return ConstantFoldFP(tan, OpC->getValueAPF(), Ty) != nullptr; 35700b57cec5SDimitry Andric break; 35710b57cec5SDimitry Andric } 35720b57cec5SDimitry Andric 3573bdd1243dSDimitry Andric case LibFunc_atan: 3574bdd1243dSDimitry Andric case LibFunc_atanf: 3575bdd1243dSDimitry Andric case LibFunc_atanl: 3576bdd1243dSDimitry Andric // Per POSIX, this MAY fail if Op is denormal. We choose not failing. 3577bdd1243dSDimitry Andric return true; 3578bdd1243dSDimitry Andric 3579bdd1243dSDimitry Andric 35800b57cec5SDimitry Andric case LibFunc_asinl: 35810b57cec5SDimitry Andric case LibFunc_asin: 35820b57cec5SDimitry Andric case LibFunc_asinf: 35830b57cec5SDimitry Andric case LibFunc_acosl: 35840b57cec5SDimitry Andric case LibFunc_acos: 35850b57cec5SDimitry Andric case LibFunc_acosf: 35865ffd83dbSDimitry Andric return !(Op < APFloat(Op.getSemantics(), "-1") || 35875ffd83dbSDimitry Andric Op > APFloat(Op.getSemantics(), "1")); 35880b57cec5SDimitry Andric 35890b57cec5SDimitry Andric case LibFunc_sinh: 35900b57cec5SDimitry Andric case LibFunc_cosh: 35910b57cec5SDimitry Andric case LibFunc_sinhf: 35920b57cec5SDimitry Andric case LibFunc_coshf: 35930b57cec5SDimitry Andric case LibFunc_sinhl: 35940b57cec5SDimitry Andric case LibFunc_coshl: 35950b57cec5SDimitry Andric // FIXME: These boundaries are slightly conservative. 35960b57cec5SDimitry Andric if (OpC->getType()->isDoubleTy()) 35975ffd83dbSDimitry Andric return !(Op < APFloat(-710.0) || Op > APFloat(710.0)); 35980b57cec5SDimitry Andric if (OpC->getType()->isFloatTy()) 35995ffd83dbSDimitry Andric return !(Op < APFloat(-89.0f) || Op > APFloat(89.0f)); 36000b57cec5SDimitry Andric break; 36010b57cec5SDimitry Andric 36020b57cec5SDimitry Andric case LibFunc_sqrtl: 36030b57cec5SDimitry Andric case LibFunc_sqrt: 36040b57cec5SDimitry Andric case LibFunc_sqrtf: 36050b57cec5SDimitry Andric return Op.isNaN() || Op.isZero() || !Op.isNegative(); 36060b57cec5SDimitry Andric 36070b57cec5SDimitry Andric // FIXME: Add more functions: sqrt_finite, atanh, expm1, log1p, 36080b57cec5SDimitry Andric // maybe others? 36090b57cec5SDimitry Andric default: 36100b57cec5SDimitry Andric break; 36110b57cec5SDimitry Andric } 36120b57cec5SDimitry Andric } 36130b57cec5SDimitry Andric } 36140b57cec5SDimitry Andric 3615349cc55cSDimitry Andric if (Call->arg_size() == 2) { 36160b57cec5SDimitry Andric ConstantFP *Op0C = dyn_cast<ConstantFP>(Call->getArgOperand(0)); 36170b57cec5SDimitry Andric ConstantFP *Op1C = dyn_cast<ConstantFP>(Call->getArgOperand(1)); 36180b57cec5SDimitry Andric if (Op0C && Op1C) { 36190b57cec5SDimitry Andric const APFloat &Op0 = Op0C->getValueAPF(); 36200b57cec5SDimitry Andric const APFloat &Op1 = Op1C->getValueAPF(); 36210b57cec5SDimitry Andric 36220b57cec5SDimitry Andric switch (Func) { 36230b57cec5SDimitry Andric case LibFunc_powl: 36240b57cec5SDimitry Andric case LibFunc_pow: 36250b57cec5SDimitry Andric case LibFunc_powf: { 36260b57cec5SDimitry Andric // FIXME: Stop using the host math library. 36270b57cec5SDimitry Andric // FIXME: The computation isn't done in the right precision. 36280b57cec5SDimitry Andric Type *Ty = Op0C->getType(); 36290b57cec5SDimitry Andric if (Ty->isDoubleTy() || Ty->isFloatTy() || Ty->isHalfTy()) { 3630fe6060f1SDimitry Andric if (Ty == Op1C->getType()) 3631fe6060f1SDimitry Andric return ConstantFoldBinaryFP(pow, Op0, Op1, Ty) != nullptr; 36320b57cec5SDimitry Andric } 36330b57cec5SDimitry Andric break; 36340b57cec5SDimitry Andric } 36350b57cec5SDimitry Andric 36360b57cec5SDimitry Andric case LibFunc_fmodl: 36370b57cec5SDimitry Andric case LibFunc_fmod: 36380b57cec5SDimitry Andric case LibFunc_fmodf: 36395ffd83dbSDimitry Andric case LibFunc_remainderl: 36405ffd83dbSDimitry Andric case LibFunc_remainder: 36415ffd83dbSDimitry Andric case LibFunc_remainderf: 36420b57cec5SDimitry Andric return Op0.isNaN() || Op1.isNaN() || 36430b57cec5SDimitry Andric (!Op0.isInfinity() && !Op1.isZero()); 36440b57cec5SDimitry Andric 3645bdd1243dSDimitry Andric case LibFunc_atan2: 3646bdd1243dSDimitry Andric case LibFunc_atan2f: 3647bdd1243dSDimitry Andric case LibFunc_atan2l: 3648bdd1243dSDimitry Andric // Although IEEE-754 says atan2(+/-0.0, +/-0.0) are well-defined, and 3649bdd1243dSDimitry Andric // GLIBC and MSVC do not appear to raise an error on those, we 3650bdd1243dSDimitry Andric // cannot rely on that behavior. POSIX and C11 say that a domain error 3651bdd1243dSDimitry Andric // may occur, so allow for that possibility. 3652bdd1243dSDimitry Andric return !Op0.isZero() || !Op1.isZero(); 3653bdd1243dSDimitry Andric 36540b57cec5SDimitry Andric default: 36550b57cec5SDimitry Andric break; 36560b57cec5SDimitry Andric } 36570b57cec5SDimitry Andric } 36580b57cec5SDimitry Andric } 36590b57cec5SDimitry Andric 36600b57cec5SDimitry Andric return false; 36610b57cec5SDimitry Andric } 36625ffd83dbSDimitry Andric 36635ffd83dbSDimitry Andric void TargetFolder::anchor() {} 3664