Eugene Zelenko | 5288921 | 2017-08-01 21:20:10 +0000 | [diff] [blame] | 1 | //===- HexagonTargetTransformInfo.cpp - Hexagon specific TTI pass ---------===// |
Krzysztof Parzyszek | 73e66f3 | 2015-08-05 18:35:37 +0000 | [diff] [blame] | 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | /// \file |
| 9 | /// This file implements a TargetTransformInfo analysis pass specific to the |
| 10 | /// Hexagon target machine. It uses the target's detailed information to provide |
| 11 | /// more precise answers to certain TTI queries, while letting the target |
| 12 | /// independent and default TTI implementations handle the rest. |
| 13 | /// |
| 14 | //===----------------------------------------------------------------------===// |
| 15 | |
| 16 | #include "HexagonTargetTransformInfo.h" |
Eugene Zelenko | 5288921 | 2017-08-01 21:20:10 +0000 | [diff] [blame] | 17 | #include "HexagonSubtarget.h" |
| 18 | #include "llvm/Analysis/TargetTransformInfo.h" |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 19 | #include "llvm/CodeGen/ValueTypes.h" |
Eugene Zelenko | 5288921 | 2017-08-01 21:20:10 +0000 | [diff] [blame] | 20 | #include "llvm/IR/InstrTypes.h" |
Krzysztof Parzyszek | db019ae | 2016-08-19 14:22:07 +0000 | [diff] [blame] | 21 | #include "llvm/IR/Instructions.h" |
Eugene Zelenko | 5288921 | 2017-08-01 21:20:10 +0000 | [diff] [blame] | 22 | #include "llvm/IR/User.h" |
| 23 | #include "llvm/Support/Casting.h" |
| 24 | #include "llvm/Support/CommandLine.h" |
Ikhlas Ajbar | 1376d93 | 2018-04-03 22:55:09 +0000 | [diff] [blame] | 25 | #include "llvm/Transforms/Utils/UnrollLoop.h" |
Krzysztof Parzyszek | 73e66f3 | 2015-08-05 18:35:37 +0000 | [diff] [blame] | 26 | |
| 27 | using namespace llvm; |
| 28 | |
| 29 | #define DEBUG_TYPE "hexagontti" |
| 30 | |
Alina Sbirlea | bdb16f0 | 2018-10-27 04:51:12 +0000 | [diff] [blame] | 31 | static cl::opt<bool> HexagonAutoHVX("hexagon-autohvx", cl::init(false), |
Krzysztof Parzyszek | 0a15d24 | 2018-03-27 17:07:52 +0000 | [diff] [blame] | 32 | cl::Hidden, cl::desc("Enable loop vectorizer for HVX")); |
| 33 | |
Sumanth Gundapaneni | d2dd79b | 2017-06-30 20:54:24 +0000 | [diff] [blame] | 34 | static cl::opt<bool> EmitLookupTables("hexagon-emit-lookup-tables", |
| 35 | cl::init(true), cl::Hidden, |
| 36 | cl::desc("Control lookup table emission on Hexagon target")); |
| 37 | |
Krzysztof Parzyszek | bea23d0 | 2018-06-12 15:12:50 +0000 | [diff] [blame] | 38 | // Constant "cost factor" to make floating point operations more expensive |
| 39 | // in terms of vectorization cost. This isn't the best way, but it should |
| 40 | // do. Ultimately, the cost should use cycles. |
| 41 | static const unsigned FloatFactor = 4; |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 42 | |
| 43 | bool HexagonTTIImpl::useHVX() const { |
| 44 | return ST.useHVXOps() && HexagonAutoHVX; |
| 45 | } |
| 46 | |
| 47 | bool HexagonTTIImpl::isTypeForHVX(Type *VecTy) const { |
| 48 | assert(VecTy->isVectorTy()); |
| 49 | // Avoid types like <2 x i32*>. |
| 50 | if (!cast<VectorType>(VecTy)->getElementType()->isIntegerTy()) |
| 51 | return false; |
| 52 | EVT VecVT = EVT::getEVT(VecTy); |
| 53 | if (!VecVT.isSimple() || VecVT.getSizeInBits() <= 64) |
| 54 | return false; |
| 55 | if (ST.isHVXVectorType(VecVT.getSimpleVT())) |
| 56 | return true; |
Craig Topper | 0b5f816 | 2018-11-05 23:26:13 +0000 | [diff] [blame] | 57 | auto Action = TLI.getPreferredVectorAction(VecVT.getSimpleVT()); |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 58 | return Action == TargetLoweringBase::TypeWidenVector; |
| 59 | } |
| 60 | |
Krzysztof Parzyszek | bea23d0 | 2018-06-12 15:12:50 +0000 | [diff] [blame] | 61 | unsigned HexagonTTIImpl::getTypeNumElements(Type *Ty) const { |
| 62 | if (Ty->isVectorTy()) |
| 63 | return Ty->getVectorNumElements(); |
| 64 | assert((Ty->isIntegerTy() || Ty->isFloatingPointTy()) && |
| 65 | "Expecting scalar type"); |
| 66 | return 1; |
| 67 | } |
| 68 | |
Krzysztof Parzyszek | 73e66f3 | 2015-08-05 18:35:37 +0000 | [diff] [blame] | 69 | TargetTransformInfo::PopcntSupportKind |
| 70 | HexagonTTIImpl::getPopcntSupport(unsigned IntTyWidthInBit) const { |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 71 | // Return fast hardware support as every input < 64 bits will be promoted |
Krzysztof Parzyszek | 73e66f3 | 2015-08-05 18:35:37 +0000 | [diff] [blame] | 72 | // to 64 bits. |
| 73 | return TargetTransformInfo::PSK_FastHardware; |
| 74 | } |
| 75 | |
| 76 | // The Hexagon target can unroll loops with run-time trip counts. |
Geoff Berry | 66d9bdb | 2017-06-28 15:53:17 +0000 | [diff] [blame] | 77 | void HexagonTTIImpl::getUnrollingPreferences(Loop *L, ScalarEvolution &SE, |
Krzysztof Parzyszek | 73e66f3 | 2015-08-05 18:35:37 +0000 | [diff] [blame] | 78 | TTI::UnrollingPreferences &UP) { |
| 79 | UP.Runtime = UP.Partial = true; |
Ikhlas Ajbar | b7322e8 | 2018-04-03 03:39:43 +0000 | [diff] [blame] | 80 | // Only try to peel innermost loops with small runtime trip counts. |
Ikhlas Ajbar | 1376d93 | 2018-04-03 22:55:09 +0000 | [diff] [blame] | 81 | if (L && L->empty() && canPeel(L) && |
Ikhlas Ajbar | b7322e8 | 2018-04-03 03:39:43 +0000 | [diff] [blame] | 82 | SE.getSmallConstantTripCount(L) == 0 && |
| 83 | SE.getSmallConstantMaxTripCount(L) > 0 && |
| 84 | SE.getSmallConstantMaxTripCount(L) <= 5) { |
| 85 | UP.PeelCount = 2; |
| 86 | } |
Krzysztof Parzyszek | 73e66f3 | 2015-08-05 18:35:37 +0000 | [diff] [blame] | 87 | } |
| 88 | |
Krzysztof Parzyszek | 56f0fc4 | 2018-03-26 15:32:03 +0000 | [diff] [blame] | 89 | bool HexagonTTIImpl::shouldFavorPostInc() const { |
| 90 | return true; |
| 91 | } |
| 92 | |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 93 | /// --- Vector TTI begin --- |
| 94 | |
Krzysztof Parzyszek | 0a15d24 | 2018-03-27 17:07:52 +0000 | [diff] [blame] | 95 | unsigned HexagonTTIImpl::getNumberOfRegisters(bool Vector) const { |
| 96 | if (Vector) |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 97 | return useHVX() ? 32 : 0; |
Krzysztof Parzyszek | 0a15d24 | 2018-03-27 17:07:52 +0000 | [diff] [blame] | 98 | return 32; |
| 99 | } |
| 100 | |
| 101 | unsigned HexagonTTIImpl::getMaxInterleaveFactor(unsigned VF) { |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 102 | return useHVX() ? 2 : 0; |
Krzysztof Parzyszek | 0a15d24 | 2018-03-27 17:07:52 +0000 | [diff] [blame] | 103 | } |
| 104 | |
| 105 | unsigned HexagonTTIImpl::getRegisterBitWidth(bool Vector) const { |
| 106 | return Vector ? getMinVectorRegisterBitWidth() : 32; |
| 107 | } |
| 108 | |
| 109 | unsigned HexagonTTIImpl::getMinVectorRegisterBitWidth() const { |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 110 | return useHVX() ? ST.getVectorLength()*8 : 0; |
Krzysztof Parzyszek | 0a15d24 | 2018-03-27 17:07:52 +0000 | [diff] [blame] | 111 | } |
| 112 | |
Krzysztof Parzyszek | dfed941 | 2018-04-13 20:16:32 +0000 | [diff] [blame] | 113 | unsigned HexagonTTIImpl::getMinimumVF(unsigned ElemWidth) const { |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 114 | return (8 * ST.getVectorLength()) / ElemWidth; |
| 115 | } |
| 116 | |
| 117 | unsigned HexagonTTIImpl::getScalarizationOverhead(Type *Ty, bool Insert, |
| 118 | bool Extract) { |
| 119 | return BaseT::getScalarizationOverhead(Ty, Insert, Extract); |
| 120 | } |
| 121 | |
| 122 | unsigned HexagonTTIImpl::getOperandsScalarizationOverhead( |
| 123 | ArrayRef<const Value*> Args, unsigned VF) { |
| 124 | return BaseT::getOperandsScalarizationOverhead(Args, VF); |
| 125 | } |
| 126 | |
| 127 | unsigned HexagonTTIImpl::getCallInstrCost(Function *F, Type *RetTy, |
| 128 | ArrayRef<Type*> Tys) { |
| 129 | return BaseT::getCallInstrCost(F, RetTy, Tys); |
| 130 | } |
| 131 | |
| 132 | unsigned HexagonTTIImpl::getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, |
| 133 | ArrayRef<Value*> Args, FastMathFlags FMF, unsigned VF) { |
| 134 | return BaseT::getIntrinsicInstrCost(ID, RetTy, Args, FMF, VF); |
| 135 | } |
| 136 | |
| 137 | unsigned HexagonTTIImpl::getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, |
| 138 | ArrayRef<Type*> Tys, FastMathFlags FMF, |
| 139 | unsigned ScalarizationCostPassed) { |
| 140 | if (ID == Intrinsic::bswap) { |
| 141 | std::pair<int, MVT> LT = TLI.getTypeLegalizationCost(DL, RetTy); |
| 142 | return LT.first + 2; |
| 143 | } |
| 144 | return BaseT::getIntrinsicInstrCost(ID, RetTy, Tys, FMF, |
| 145 | ScalarizationCostPassed); |
| 146 | } |
| 147 | |
| 148 | unsigned HexagonTTIImpl::getAddressComputationCost(Type *Tp, |
| 149 | ScalarEvolution *SE, const SCEV *S) { |
| 150 | return 0; |
Krzysztof Parzyszek | dfed941 | 2018-04-13 20:16:32 +0000 | [diff] [blame] | 151 | } |
| 152 | |
Krzysztof Parzyszek | 0a15d24 | 2018-03-27 17:07:52 +0000 | [diff] [blame] | 153 | unsigned HexagonTTIImpl::getMemoryOpCost(unsigned Opcode, Type *Src, |
| 154 | unsigned Alignment, unsigned AddressSpace, const Instruction *I) { |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 155 | assert(Opcode == Instruction::Load || Opcode == Instruction::Store); |
| 156 | if (Opcode == Instruction::Store) |
| 157 | return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace, I); |
| 158 | |
| 159 | if (Src->isVectorTy()) { |
Krzysztof Parzyszek | 0a15d24 | 2018-03-27 17:07:52 +0000 | [diff] [blame] | 160 | VectorType *VecTy = cast<VectorType>(Src); |
| 161 | unsigned VecWidth = VecTy->getBitWidth(); |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 162 | if (useHVX() && isTypeForHVX(VecTy)) { |
| 163 | unsigned RegWidth = getRegisterBitWidth(true); |
| 164 | Alignment = std::min(Alignment, RegWidth/8); |
| 165 | // Cost of HVX loads. |
| 166 | if (VecWidth % RegWidth == 0) |
| 167 | return VecWidth / RegWidth; |
| 168 | // Cost of constructing HVX vector from scalar loads. |
Krzysztof Parzyszek | 0a15d24 | 2018-03-27 17:07:52 +0000 | [diff] [blame] | 169 | unsigned AlignWidth = 8 * std::max(1u, Alignment); |
| 170 | unsigned NumLoads = alignTo(VecWidth, AlignWidth) / AlignWidth; |
| 171 | return 3*NumLoads; |
| 172 | } |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 173 | |
| 174 | // Non-HVX vectors. |
| 175 | // Add extra cost for floating point types. |
Krzysztof Parzyszek | bea23d0 | 2018-06-12 15:12:50 +0000 | [diff] [blame] | 176 | unsigned Cost = VecTy->getElementType()->isFloatingPointTy() ? FloatFactor |
| 177 | : 1; |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 178 | Alignment = std::min(Alignment, 8u); |
| 179 | unsigned AlignWidth = 8 * std::max(1u, Alignment); |
| 180 | unsigned NumLoads = alignTo(VecWidth, AlignWidth) / AlignWidth; |
| 181 | if (Alignment == 4 || Alignment == 8) |
| 182 | return Cost * NumLoads; |
| 183 | // Loads of less than 32 bits will need extra inserts to compose a vector. |
| 184 | unsigned LogA = Log2_32(Alignment); |
| 185 | return (3 - LogA) * Cost * NumLoads; |
Krzysztof Parzyszek | 0a15d24 | 2018-03-27 17:07:52 +0000 | [diff] [blame] | 186 | } |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 187 | |
Krzysztof Parzyszek | 0a15d24 | 2018-03-27 17:07:52 +0000 | [diff] [blame] | 188 | return BaseT::getMemoryOpCost(Opcode, Src, Alignment, AddressSpace, I); |
Krzysztof Parzyszek | 73e66f3 | 2015-08-05 18:35:37 +0000 | [diff] [blame] | 189 | } |
Krzysztof Parzyszek | d3d0a4b | 2016-07-22 14:22:43 +0000 | [diff] [blame] | 190 | |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 191 | unsigned HexagonTTIImpl::getMaskedMemoryOpCost(unsigned Opcode, |
| 192 | Type *Src, unsigned Alignment, unsigned AddressSpace) { |
| 193 | return BaseT::getMaskedMemoryOpCost(Opcode, Src, Alignment, AddressSpace); |
| 194 | } |
| 195 | |
| 196 | unsigned HexagonTTIImpl::getShuffleCost(TTI::ShuffleKind Kind, Type *Tp, |
| 197 | int Index, Type *SubTp) { |
| 198 | return 1; |
| 199 | } |
| 200 | |
| 201 | unsigned HexagonTTIImpl::getGatherScatterOpCost(unsigned Opcode, Type *DataTy, |
| 202 | Value *Ptr, bool VariableMask, unsigned Alignment) { |
| 203 | return BaseT::getGatherScatterOpCost(Opcode, DataTy, Ptr, VariableMask, |
| 204 | Alignment); |
| 205 | } |
| 206 | |
| 207 | unsigned HexagonTTIImpl::getInterleavedMemoryOpCost(unsigned Opcode, |
| 208 | Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices, |
Dorit Nuzman | 34da6dd | 2018-10-31 09:57:56 +0000 | [diff] [blame] | 209 | unsigned Alignment, unsigned AddressSpace, bool UseMaskForCond, |
| 210 | bool UseMaskForGaps) { |
| 211 | if (Indices.size() != Factor || UseMaskForCond || UseMaskForGaps) |
Krzysztof Parzyszek | 2ff9aa1 | 2018-08-22 20:15:04 +0000 | [diff] [blame] | 212 | return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices, |
Dorit Nuzman | 34da6dd | 2018-10-31 09:57:56 +0000 | [diff] [blame] | 213 | Alignment, AddressSpace, |
| 214 | UseMaskForCond, UseMaskForGaps); |
Krzysztof Parzyszek | 2ff9aa1 | 2018-08-22 20:15:04 +0000 | [diff] [blame] | 215 | return getMemoryOpCost(Opcode, VecTy, Alignment, AddressSpace, nullptr); |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 216 | } |
| 217 | |
| 218 | unsigned HexagonTTIImpl::getCmpSelInstrCost(unsigned Opcode, Type *ValTy, |
| 219 | Type *CondTy, const Instruction *I) { |
| 220 | if (ValTy->isVectorTy()) { |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 221 | std::pair<int, MVT> LT = TLI.getTypeLegalizationCost(DL, ValTy); |
| 222 | if (Opcode == Instruction::FCmp) |
Krzysztof Parzyszek | bea23d0 | 2018-06-12 15:12:50 +0000 | [diff] [blame] | 223 | return LT.first + FloatFactor * getTypeNumElements(ValTy); |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 224 | } |
| 225 | return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, I); |
| 226 | } |
| 227 | |
| 228 | unsigned HexagonTTIImpl::getArithmeticInstrCost(unsigned Opcode, Type *Ty, |
| 229 | TTI::OperandValueKind Opd1Info, TTI::OperandValueKind Opd2Info, |
| 230 | TTI::OperandValueProperties Opd1PropInfo, |
| 231 | TTI::OperandValueProperties Opd2PropInfo, ArrayRef<const Value*> Args) { |
Krzysztof Parzyszek | bea23d0 | 2018-06-12 15:12:50 +0000 | [diff] [blame] | 232 | if (Ty->isVectorTy()) { |
| 233 | std::pair<int, MVT> LT = TLI.getTypeLegalizationCost(DL, Ty); |
| 234 | if (LT.second.isFloatingPoint()) |
| 235 | return LT.first + FloatFactor * getTypeNumElements(Ty); |
| 236 | } |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 237 | return BaseT::getArithmeticInstrCost(Opcode, Ty, Opd1Info, Opd2Info, |
| 238 | Opd1PropInfo, Opd2PropInfo, Args); |
| 239 | } |
| 240 | |
Krzysztof Parzyszek | bea23d0 | 2018-06-12 15:12:50 +0000 | [diff] [blame] | 241 | unsigned HexagonTTIImpl::getCastInstrCost(unsigned Opcode, Type *DstTy, |
| 242 | Type *SrcTy, const Instruction *I) { |
| 243 | if (SrcTy->isFPOrFPVectorTy() || DstTy->isFPOrFPVectorTy()) { |
| 244 | unsigned SrcN = SrcTy->isFPOrFPVectorTy() ? getTypeNumElements(SrcTy) : 0; |
| 245 | unsigned DstN = DstTy->isFPOrFPVectorTy() ? getTypeNumElements(DstTy) : 0; |
| 246 | |
| 247 | std::pair<int, MVT> SrcLT = TLI.getTypeLegalizationCost(DL, SrcTy); |
| 248 | std::pair<int, MVT> DstLT = TLI.getTypeLegalizationCost(DL, DstTy); |
| 249 | return std::max(SrcLT.first, DstLT.first) + FloatFactor * (SrcN + DstN); |
| 250 | } |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 251 | return 1; |
| 252 | } |
| 253 | |
| 254 | unsigned HexagonTTIImpl::getVectorInstrCost(unsigned Opcode, Type *Val, |
| 255 | unsigned Index) { |
| 256 | Type *ElemTy = Val->isVectorTy() ? cast<VectorType>(Val)->getElementType() |
| 257 | : Val; |
| 258 | if (Opcode == Instruction::InsertElement) { |
| 259 | // Need two rotations for non-zero index. |
| 260 | unsigned Cost = (Index != 0) ? 2 : 0; |
| 261 | if (ElemTy->isIntegerTy(32)) |
| 262 | return Cost; |
| 263 | // If it's not a 32-bit value, there will need to be an extract. |
| 264 | return Cost + getVectorInstrCost(Instruction::ExtractElement, Val, Index); |
| 265 | } |
| 266 | |
| 267 | if (Opcode == Instruction::ExtractElement) |
| 268 | return 2; |
| 269 | |
| 270 | return 1; |
| 271 | } |
| 272 | |
| 273 | /// --- Vector TTI end --- |
| 274 | |
Krzysztof Parzyszek | d3d0a4b | 2016-07-22 14:22:43 +0000 | [diff] [blame] | 275 | unsigned HexagonTTIImpl::getPrefetchDistance() const { |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 276 | return ST.getL1PrefetchDistance(); |
Krzysztof Parzyszek | d3d0a4b | 2016-07-22 14:22:43 +0000 | [diff] [blame] | 277 | } |
| 278 | |
| 279 | unsigned HexagonTTIImpl::getCacheLineSize() const { |
Krzysztof Parzyszek | 4bdf1aa | 2018-04-13 20:46:50 +0000 | [diff] [blame] | 280 | return ST.getL1CacheLineSize(); |
Krzysztof Parzyszek | d3d0a4b | 2016-07-22 14:22:43 +0000 | [diff] [blame] | 281 | } |
Krzysztof Parzyszek | db019ae | 2016-08-19 14:22:07 +0000 | [diff] [blame] | 282 | |
Evgeny Astigeevich | 70ed78e | 2017-06-29 13:42:12 +0000 | [diff] [blame] | 283 | int HexagonTTIImpl::getUserCost(const User *U, |
| 284 | ArrayRef<const Value *> Operands) { |
Krzysztof Parzyszek | 0a15d24 | 2018-03-27 17:07:52 +0000 | [diff] [blame] | 285 | auto isCastFoldedIntoLoad = [this](const CastInst *CI) -> bool { |
Krzysztof Parzyszek | db019ae | 2016-08-19 14:22:07 +0000 | [diff] [blame] | 286 | if (!CI->isIntegerCast()) |
| 287 | return false; |
Krzysztof Parzyszek | 0a15d24 | 2018-03-27 17:07:52 +0000 | [diff] [blame] | 288 | // Only extensions from an integer type shorter than 32-bit to i32 |
| 289 | // can be folded into the load. |
| 290 | const DataLayout &DL = getDataLayout(); |
| 291 | unsigned SBW = DL.getTypeSizeInBits(CI->getSrcTy()); |
| 292 | unsigned DBW = DL.getTypeSizeInBits(CI->getDestTy()); |
| 293 | if (DBW != 32 || SBW >= DBW) |
| 294 | return false; |
| 295 | |
Krzysztof Parzyszek | db019ae | 2016-08-19 14:22:07 +0000 | [diff] [blame] | 296 | const LoadInst *LI = dyn_cast<const LoadInst>(CI->getOperand(0)); |
| 297 | // Technically, this code could allow multiple uses of the load, and |
| 298 | // check if all the uses are the same extension operation, but this |
| 299 | // should be sufficient for most cases. |
Krzysztof Parzyszek | 0a15d24 | 2018-03-27 17:07:52 +0000 | [diff] [blame] | 300 | return LI && LI->hasOneUse(); |
Krzysztof Parzyszek | db019ae | 2016-08-19 14:22:07 +0000 | [diff] [blame] | 301 | }; |
| 302 | |
| 303 | if (const CastInst *CI = dyn_cast<const CastInst>(U)) |
| 304 | if (isCastFoldedIntoLoad(CI)) |
| 305 | return TargetTransformInfo::TCC_Free; |
Evgeny Astigeevich | 70ed78e | 2017-06-29 13:42:12 +0000 | [diff] [blame] | 306 | return BaseT::getUserCost(U, Operands); |
Krzysztof Parzyszek | db019ae | 2016-08-19 14:22:07 +0000 | [diff] [blame] | 307 | } |
Sumanth Gundapaneni | d2dd79b | 2017-06-30 20:54:24 +0000 | [diff] [blame] | 308 | |
| 309 | bool HexagonTTIImpl::shouldBuildLookupTables() const { |
Krzysztof Parzyszek | 56f0fc4 | 2018-03-26 15:32:03 +0000 | [diff] [blame] | 310 | return EmitLookupTables; |
Sumanth Gundapaneni | d2dd79b | 2017-06-30 20:54:24 +0000 | [diff] [blame] | 311 | } |