Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 14 | pmbaty | 1 | //===-- llvm/Operator.h - Operator utility subclass -------------*- C++ -*-===// | 
| 2 | // | ||
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| 4 | // See https://llvm.org/LICENSE.txt for license information. | ||
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| 6 | // | ||
| 7 | //===----------------------------------------------------------------------===// | ||
| 8 | // | ||
| 9 | // This file defines various classes for working with Instructions and | ||
| 10 | // ConstantExprs. | ||
| 11 | // | ||
| 12 | //===----------------------------------------------------------------------===// | ||
| 13 | |||
| 14 | #ifndef LLVM_IR_OPERATOR_H | ||
| 15 | #define LLVM_IR_OPERATOR_H | ||
| 16 | |||
| 17 | #include "llvm/ADT/MapVector.h" | ||
| 18 | #include "llvm/IR/Constants.h" | ||
| 19 | #include "llvm/IR/FMF.h" | ||
| 20 | #include "llvm/IR/Instruction.h" | ||
| 21 | #include "llvm/IR/Type.h" | ||
| 22 | #include "llvm/IR/Value.h" | ||
| 23 | #include "llvm/Support/Casting.h" | ||
| 24 | #include <cstddef> | ||
| 25 | #include <optional> | ||
| 26 | |||
| 27 | namespace llvm { | ||
| 28 | |||
| 29 | /// This is a utility class that provides an abstraction for the common | ||
| 30 | /// functionality between Instructions and ConstantExprs. | ||
| 31 | class Operator : public User { | ||
| 32 | public: | ||
| 33 |   // The Operator class is intended to be used as a utility, and is never itself | ||
| 34 |   // instantiated. | ||
| 35 | Operator() = delete; | ||
| 36 | ~Operator() = delete; | ||
| 37 | |||
| 38 | void *operator new(size_t s) = delete; | ||
| 39 | |||
| 40 |   /// Return the opcode for this Instruction or ConstantExpr. | ||
| 41 | unsigned getOpcode() const { | ||
| 42 | if (const Instruction *I = dyn_cast<Instruction>(this)) | ||
| 43 | return I->getOpcode(); | ||
| 44 | return cast<ConstantExpr>(this)->getOpcode(); | ||
| 45 |   } | ||
| 46 | |||
| 47 |   /// If V is an Instruction or ConstantExpr, return its opcode. | ||
| 48 |   /// Otherwise return UserOp1. | ||
| 49 | static unsigned getOpcode(const Value *V) { | ||
| 50 | if (const Instruction *I = dyn_cast<Instruction>(V)) | ||
| 51 | return I->getOpcode(); | ||
| 52 | if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) | ||
| 53 | return CE->getOpcode(); | ||
| 54 | return Instruction::UserOp1; | ||
| 55 |   } | ||
| 56 | |||
| 57 | static bool classof(const Instruction *) { return true; } | ||
| 58 | static bool classof(const ConstantExpr *) { return true; } | ||
| 59 | static bool classof(const Value *V) { | ||
| 60 | return isa<Instruction>(V) || isa<ConstantExpr>(V); | ||
| 61 |   } | ||
| 62 | |||
| 63 |   /// Return true if this operator has flags which may cause this operator | ||
| 64 |   /// to evaluate to poison despite having non-poison inputs. | ||
| 65 | bool hasPoisonGeneratingFlags() const; | ||
| 66 | |||
| 67 |   /// Return true if this operator has poison-generating flags or metadata. | ||
| 68 |   /// The latter is only possible for instructions. | ||
| 69 | bool hasPoisonGeneratingFlagsOrMetadata() const; | ||
| 70 | }; | ||
| 71 | |||
| 72 | /// Utility class for integer operators which may exhibit overflow - Add, Sub, | ||
| 73 | /// Mul, and Shl. It does not include SDiv, despite that operator having the | ||
| 74 | /// potential for overflow. | ||
| 75 | class OverflowingBinaryOperator : public Operator { | ||
| 76 | public: | ||
| 77 | enum { | ||
| 78 | AnyWrap = 0, | ||
| 79 | NoUnsignedWrap = (1 << 0), | ||
| 80 | NoSignedWrap = (1 << 1) | ||
| 81 | }; | ||
| 82 | |||
| 83 | private: | ||
| 84 | friend class Instruction; | ||
| 85 | friend class ConstantExpr; | ||
| 86 | |||
| 87 | void setHasNoUnsignedWrap(bool B) { | ||
| 88 |     SubclassOptionalData = | ||
| 89 | (SubclassOptionalData & ~NoUnsignedWrap) | (B * NoUnsignedWrap); | ||
| 90 |   } | ||
| 91 | void setHasNoSignedWrap(bool B) { | ||
| 92 |     SubclassOptionalData = | ||
| 93 | (SubclassOptionalData & ~NoSignedWrap) | (B * NoSignedWrap); | ||
| 94 |   } | ||
| 95 | |||
| 96 | public: | ||
| 97 |   /// Test whether this operation is known to never | ||
| 98 |   /// undergo unsigned overflow, aka the nuw property. | ||
| 99 | bool hasNoUnsignedWrap() const { | ||
| 100 | return SubclassOptionalData & NoUnsignedWrap; | ||
| 101 |   } | ||
| 102 | |||
| 103 |   /// Test whether this operation is known to never | ||
| 104 |   /// undergo signed overflow, aka the nsw property. | ||
| 105 | bool hasNoSignedWrap() const { | ||
| 106 | return (SubclassOptionalData & NoSignedWrap) != 0; | ||
| 107 |   } | ||
| 108 | |||
| 109 | static bool classof(const Instruction *I) { | ||
| 110 | return I->getOpcode() == Instruction::Add || | ||
| 111 | I->getOpcode() == Instruction::Sub || | ||
| 112 | I->getOpcode() == Instruction::Mul || | ||
| 113 | I->getOpcode() == Instruction::Shl; | ||
| 114 |   } | ||
| 115 | static bool classof(const ConstantExpr *CE) { | ||
| 116 | return CE->getOpcode() == Instruction::Add || | ||
| 117 | CE->getOpcode() == Instruction::Sub || | ||
| 118 | CE->getOpcode() == Instruction::Mul || | ||
| 119 | CE->getOpcode() == Instruction::Shl; | ||
| 120 |   } | ||
| 121 | static bool classof(const Value *V) { | ||
| 122 | return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || | ||
| 123 | (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); | ||
| 124 |   } | ||
| 125 | }; | ||
| 126 | |||
| 127 | /// A udiv or sdiv instruction, which can be marked as "exact", | ||
| 128 | /// indicating that no bits are destroyed. | ||
| 129 | class PossiblyExactOperator : public Operator { | ||
| 130 | public: | ||
| 131 | enum { | ||
| 132 | IsExact = (1 << 0) | ||
| 133 | }; | ||
| 134 | |||
| 135 | private: | ||
| 136 | friend class Instruction; | ||
| 137 | friend class ConstantExpr; | ||
| 138 | |||
| 139 | void setIsExact(bool B) { | ||
| 140 | SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact); | ||
| 141 |   } | ||
| 142 | |||
| 143 | public: | ||
| 144 |   /// Test whether this division is known to be exact, with zero remainder. | ||
| 145 | bool isExact() const { | ||
| 146 | return SubclassOptionalData & IsExact; | ||
| 147 |   } | ||
| 148 | |||
| 149 | static bool isPossiblyExactOpcode(unsigned OpC) { | ||
| 150 | return OpC == Instruction::SDiv || | ||
| 151 | OpC == Instruction::UDiv || | ||
| 152 | OpC == Instruction::AShr || | ||
| 153 | OpC == Instruction::LShr; | ||
| 154 |   } | ||
| 155 | |||
| 156 | static bool classof(const ConstantExpr *CE) { | ||
| 157 | return isPossiblyExactOpcode(CE->getOpcode()); | ||
| 158 |   } | ||
| 159 | static bool classof(const Instruction *I) { | ||
| 160 | return isPossiblyExactOpcode(I->getOpcode()); | ||
| 161 |   } | ||
| 162 | static bool classof(const Value *V) { | ||
| 163 | return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || | ||
| 164 | (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); | ||
| 165 |   } | ||
| 166 | }; | ||
| 167 | |||
| 168 | /// Utility class for floating point operations which can have | ||
| 169 | /// information about relaxed accuracy requirements attached to them. | ||
| 170 | class FPMathOperator : public Operator { | ||
| 171 | private: | ||
| 172 | friend class Instruction; | ||
| 173 | |||
| 174 |   /// 'Fast' means all bits are set. | ||
| 175 | void setFast(bool B) { | ||
| 176 | setHasAllowReassoc(B); | ||
| 177 | setHasNoNaNs(B); | ||
| 178 | setHasNoInfs(B); | ||
| 179 | setHasNoSignedZeros(B); | ||
| 180 | setHasAllowReciprocal(B); | ||
| 181 | setHasAllowContract(B); | ||
| 182 | setHasApproxFunc(B); | ||
| 183 |   } | ||
| 184 | |||
| 185 | void setHasAllowReassoc(bool B) { | ||
| 186 |     SubclassOptionalData = | ||
| 187 | (SubclassOptionalData & ~FastMathFlags::AllowReassoc) | | ||
| 188 | (B * FastMathFlags::AllowReassoc); | ||
| 189 |   } | ||
| 190 | |||
| 191 | void setHasNoNaNs(bool B) { | ||
| 192 |     SubclassOptionalData = | ||
| 193 | (SubclassOptionalData & ~FastMathFlags::NoNaNs) | | ||
| 194 | (B * FastMathFlags::NoNaNs); | ||
| 195 |   } | ||
| 196 | |||
| 197 | void setHasNoInfs(bool B) { | ||
| 198 |     SubclassOptionalData = | ||
| 199 | (SubclassOptionalData & ~FastMathFlags::NoInfs) | | ||
| 200 | (B * FastMathFlags::NoInfs); | ||
| 201 |   } | ||
| 202 | |||
| 203 | void setHasNoSignedZeros(bool B) { | ||
| 204 |     SubclassOptionalData = | ||
| 205 | (SubclassOptionalData & ~FastMathFlags::NoSignedZeros) | | ||
| 206 | (B * FastMathFlags::NoSignedZeros); | ||
| 207 |   } | ||
| 208 | |||
| 209 | void setHasAllowReciprocal(bool B) { | ||
| 210 |     SubclassOptionalData = | ||
| 211 | (SubclassOptionalData & ~FastMathFlags::AllowReciprocal) | | ||
| 212 | (B * FastMathFlags::AllowReciprocal); | ||
| 213 |   } | ||
| 214 | |||
| 215 | void setHasAllowContract(bool B) { | ||
| 216 |     SubclassOptionalData = | ||
| 217 | (SubclassOptionalData & ~FastMathFlags::AllowContract) | | ||
| 218 | (B * FastMathFlags::AllowContract); | ||
| 219 |   } | ||
| 220 | |||
| 221 | void setHasApproxFunc(bool B) { | ||
| 222 |     SubclassOptionalData = | ||
| 223 | (SubclassOptionalData & ~FastMathFlags::ApproxFunc) | | ||
| 224 | (B * FastMathFlags::ApproxFunc); | ||
| 225 |   } | ||
| 226 | |||
| 227 |   /// Convenience function for setting multiple fast-math flags. | ||
| 228 |   /// FMF is a mask of the bits to set. | ||
| 229 | void setFastMathFlags(FastMathFlags FMF) { | ||
| 230 | SubclassOptionalData |= FMF.Flags; | ||
| 231 |   } | ||
| 232 | |||
| 233 |   /// Convenience function for copying all fast-math flags. | ||
| 234 |   /// All values in FMF are transferred to this operator. | ||
| 235 | void copyFastMathFlags(FastMathFlags FMF) { | ||
| 236 | SubclassOptionalData = FMF.Flags; | ||
| 237 |   } | ||
| 238 | |||
| 239 | public: | ||
| 240 |   /// Test if this operation allows all non-strict floating-point transforms. | ||
| 241 | bool isFast() const { | ||
| 242 | return ((SubclassOptionalData & FastMathFlags::AllowReassoc) != 0 && | ||
| 243 | (SubclassOptionalData & FastMathFlags::NoNaNs) != 0 && | ||
| 244 | (SubclassOptionalData & FastMathFlags::NoInfs) != 0 && | ||
| 245 | (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0 && | ||
| 246 | (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0 && | ||
| 247 | (SubclassOptionalData & FastMathFlags::AllowContract) != 0 && | ||
| 248 | (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0); | ||
| 249 |   } | ||
| 250 | |||
| 251 |   /// Test if this operation may be simplified with reassociative transforms. | ||
| 252 | bool hasAllowReassoc() const { | ||
| 253 | return (SubclassOptionalData & FastMathFlags::AllowReassoc) != 0; | ||
| 254 |   } | ||
| 255 | |||
| 256 |   /// Test if this operation's arguments and results are assumed not-NaN. | ||
| 257 | bool hasNoNaNs() const { | ||
| 258 | return (SubclassOptionalData & FastMathFlags::NoNaNs) != 0; | ||
| 259 |   } | ||
| 260 | |||
| 261 |   /// Test if this operation's arguments and results are assumed not-infinite. | ||
| 262 | bool hasNoInfs() const { | ||
| 263 | return (SubclassOptionalData & FastMathFlags::NoInfs) != 0; | ||
| 264 |   } | ||
| 265 | |||
| 266 |   /// Test if this operation can ignore the sign of zero. | ||
| 267 | bool hasNoSignedZeros() const { | ||
| 268 | return (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0; | ||
| 269 |   } | ||
| 270 | |||
| 271 |   /// Test if this operation can use reciprocal multiply instead of division. | ||
| 272 | bool hasAllowReciprocal() const { | ||
| 273 | return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0; | ||
| 274 |   } | ||
| 275 | |||
| 276 |   /// Test if this operation can be floating-point contracted (FMA). | ||
| 277 | bool hasAllowContract() const { | ||
| 278 | return (SubclassOptionalData & FastMathFlags::AllowContract) != 0; | ||
| 279 |   } | ||
| 280 | |||
| 281 |   /// Test if this operation allows approximations of math library functions or | ||
| 282 |   /// intrinsics. | ||
| 283 | bool hasApproxFunc() const { | ||
| 284 | return (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0; | ||
| 285 |   } | ||
| 286 | |||
| 287 |   /// Convenience function for getting all the fast-math flags | ||
| 288 | FastMathFlags getFastMathFlags() const { | ||
| 289 | return FastMathFlags(SubclassOptionalData); | ||
| 290 |   } | ||
| 291 | |||
| 292 |   /// Get the maximum error permitted by this operation in ULPs. An accuracy of | ||
| 293 |   /// 0.0 means that the operation should be performed with the default | ||
| 294 |   /// precision. | ||
| 295 | float getFPAccuracy() const; | ||
| 296 | |||
| 297 | static bool classof(const Value *V) { | ||
| 298 | unsigned Opcode; | ||
| 299 | if (auto *I = dyn_cast<Instruction>(V)) | ||
| 300 | Opcode = I->getOpcode(); | ||
| 301 | else if (auto *CE = dyn_cast<ConstantExpr>(V)) | ||
| 302 | Opcode = CE->getOpcode(); | ||
| 303 |     else | ||
| 304 | return false; | ||
| 305 | |||
| 306 | switch (Opcode) { | ||
| 307 | case Instruction::FNeg: | ||
| 308 | case Instruction::FAdd: | ||
| 309 | case Instruction::FSub: | ||
| 310 | case Instruction::FMul: | ||
| 311 | case Instruction::FDiv: | ||
| 312 | case Instruction::FRem: | ||
| 313 |     // FIXME: To clean up and correct the semantics of fast-math-flags, FCmp | ||
| 314 |     //        should not be treated as a math op, but the other opcodes should. | ||
| 315 |     //        This would make things consistent with Select/PHI (FP value type | ||
| 316 |     //        determines whether they are math ops and, therefore, capable of | ||
| 317 |     //        having fast-math-flags). | ||
| 318 | case Instruction::FCmp: | ||
| 319 | return true; | ||
| 320 | case Instruction::PHI: | ||
| 321 | case Instruction::Select: | ||
| 322 | case Instruction::Call: { | ||
| 323 | Type *Ty = V->getType(); | ||
| 324 | while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) | ||
| 325 | Ty = ArrTy->getElementType(); | ||
| 326 | return Ty->isFPOrFPVectorTy(); | ||
| 327 |     } | ||
| 328 | default: | ||
| 329 | return false; | ||
| 330 |     } | ||
| 331 |   } | ||
| 332 | }; | ||
| 333 | |||
| 334 | /// A helper template for defining operators for individual opcodes. | ||
| 335 | template<typename SuperClass, unsigned Opc> | ||
| 336 | class ConcreteOperator : public SuperClass { | ||
| 337 | public: | ||
| 338 | static bool classof(const Instruction *I) { | ||
| 339 | return I->getOpcode() == Opc; | ||
| 340 |   } | ||
| 341 | static bool classof(const ConstantExpr *CE) { | ||
| 342 | return CE->getOpcode() == Opc; | ||
| 343 |   } | ||
| 344 | static bool classof(const Value *V) { | ||
| 345 | return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || | ||
| 346 | (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); | ||
| 347 |   } | ||
| 348 | }; | ||
| 349 | |||
| 350 | class AddOperator | ||
| 351 | : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Add> { | ||
| 352 | }; | ||
| 353 | class SubOperator | ||
| 354 | : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Sub> { | ||
| 355 | }; | ||
| 356 | class MulOperator | ||
| 357 | : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Mul> { | ||
| 358 | }; | ||
| 359 | class ShlOperator | ||
| 360 | : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Shl> { | ||
| 361 | }; | ||
| 362 | |||
| 363 | class SDivOperator | ||
| 364 | : public ConcreteOperator<PossiblyExactOperator, Instruction::SDiv> { | ||
| 365 | }; | ||
| 366 | class UDivOperator | ||
| 367 | : public ConcreteOperator<PossiblyExactOperator, Instruction::UDiv> { | ||
| 368 | }; | ||
| 369 | class AShrOperator | ||
| 370 | : public ConcreteOperator<PossiblyExactOperator, Instruction::AShr> { | ||
| 371 | }; | ||
| 372 | class LShrOperator | ||
| 373 | : public ConcreteOperator<PossiblyExactOperator, Instruction::LShr> { | ||
| 374 | }; | ||
| 375 | |||
| 376 | class ZExtOperator : public ConcreteOperator<Operator, Instruction::ZExt> {}; | ||
| 377 | |||
| 378 | class GEPOperator | ||
| 379 | : public ConcreteOperator<Operator, Instruction::GetElementPtr> { | ||
| 380 | friend class GetElementPtrInst; | ||
| 381 | friend class ConstantExpr; | ||
| 382 | |||
| 383 | enum { | ||
| 384 | IsInBounds = (1 << 0), | ||
| 385 |     // InRangeIndex: bits 1-6 | ||
| 386 | }; | ||
| 387 | |||
| 388 | void setIsInBounds(bool B) { | ||
| 389 |     SubclassOptionalData = | ||
| 390 | (SubclassOptionalData & ~IsInBounds) | (B * IsInBounds); | ||
| 391 |   } | ||
| 392 | |||
| 393 | public: | ||
| 394 |   /// Test whether this is an inbounds GEP, as defined by LangRef.html. | ||
| 395 | bool isInBounds() const { | ||
| 396 | return SubclassOptionalData & IsInBounds; | ||
| 397 |   } | ||
| 398 | |||
| 399 |   /// Returns the offset of the index with an inrange attachment, or | ||
| 400 |   /// std::nullopt if none. | ||
| 401 | std::optional<unsigned> getInRangeIndex() const { | ||
| 402 | if (SubclassOptionalData >> 1 == 0) | ||
| 403 | return std::nullopt; | ||
| 404 | return (SubclassOptionalData >> 1) - 1; | ||
| 405 |   } | ||
| 406 | |||
| 407 | inline op_iterator idx_begin() { return op_begin()+1; } | ||
| 408 | inline const_op_iterator idx_begin() const { return op_begin()+1; } | ||
| 409 | inline op_iterator idx_end() { return op_end(); } | ||
| 410 | inline const_op_iterator idx_end() const { return op_end(); } | ||
| 411 | |||
| 412 | inline iterator_range<op_iterator> indices() { | ||
| 413 | return make_range(idx_begin(), idx_end()); | ||
| 414 |   } | ||
| 415 | |||
| 416 | inline iterator_range<const_op_iterator> indices() const { | ||
| 417 | return make_range(idx_begin(), idx_end()); | ||
| 418 |   } | ||
| 419 | |||
| 420 | Value *getPointerOperand() { | ||
| 421 | return getOperand(0); | ||
| 422 |   } | ||
| 423 | const Value *getPointerOperand() const { | ||
| 424 | return getOperand(0); | ||
| 425 |   } | ||
| 426 | static unsigned getPointerOperandIndex() { | ||
| 427 | return 0U; // get index for modifying correct operand | ||
| 428 |   } | ||
| 429 | |||
| 430 |   /// Method to return the pointer operand as a PointerType. | ||
| 431 | Type *getPointerOperandType() const { | ||
| 432 | return getPointerOperand()->getType(); | ||
| 433 |   } | ||
| 434 | |||
| 435 | Type *getSourceElementType() const; | ||
| 436 | Type *getResultElementType() const; | ||
| 437 | |||
| 438 |   /// Method to return the address space of the pointer operand. | ||
| 439 | unsigned getPointerAddressSpace() const { | ||
| 440 | return getPointerOperandType()->getPointerAddressSpace(); | ||
| 441 |   } | ||
| 442 | |||
| 443 | unsigned getNumIndices() const { // Note: always non-negative | ||
| 444 | return getNumOperands() - 1; | ||
| 445 |   } | ||
| 446 | |||
| 447 | bool hasIndices() const { | ||
| 448 | return getNumOperands() > 1; | ||
| 449 |   } | ||
| 450 | |||
| 451 |   /// Return true if all of the indices of this GEP are zeros. | ||
| 452 |   /// If so, the result pointer and the first operand have the same | ||
| 453 |   /// value, just potentially different types. | ||
| 454 | bool hasAllZeroIndices() const { | ||
| 455 | for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { | ||
| 456 | if (ConstantInt *C = dyn_cast<ConstantInt>(I)) | ||
| 457 | if (C->isZero()) | ||
| 458 | continue; | ||
| 459 | return false; | ||
| 460 |     } | ||
| 461 | return true; | ||
| 462 |   } | ||
| 463 | |||
| 464 |   /// Return true if all of the indices of this GEP are constant integers. | ||
| 465 |   /// If so, the result pointer and the first operand have | ||
| 466 |   /// a constant offset between them. | ||
| 467 | bool hasAllConstantIndices() const { | ||
| 468 | for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { | ||
| 469 | if (!isa<ConstantInt>(I)) | ||
| 470 | return false; | ||
| 471 |     } | ||
| 472 | return true; | ||
| 473 |   } | ||
| 474 | |||
| 475 | unsigned countNonConstantIndices() const { | ||
| 476 | return count_if(indices(), [](const Use& use) { | ||
| 477 | return !isa<ConstantInt>(*use); | ||
| 478 | }); | ||
| 479 |   } | ||
| 480 | |||
| 481 |   /// Compute the maximum alignment that this GEP is garranteed to preserve. | ||
| 482 | Align getMaxPreservedAlignment(const DataLayout &DL) const; | ||
| 483 | |||
| 484 |   /// Accumulate the constant address offset of this GEP if possible. | ||
| 485 |   /// | ||
| 486 |   /// This routine accepts an APInt into which it will try to accumulate the | ||
| 487 |   /// constant offset of this GEP. | ||
| 488 |   /// | ||
| 489 |   /// If \p ExternalAnalysis is provided it will be used to calculate a offset | ||
| 490 |   /// when a operand of GEP is not constant. | ||
| 491 |   /// For example, for a value \p ExternalAnalysis might try to calculate a | ||
| 492 |   /// lower bound. If \p ExternalAnalysis is successful, it should return true. | ||
| 493 |   /// | ||
| 494 |   /// If the \p ExternalAnalysis returns false or the value returned by \p | ||
| 495 |   /// ExternalAnalysis results in a overflow/underflow, this routine returns | ||
| 496 |   /// false and the value of the offset APInt is undefined (it is *not* | ||
| 497 |   /// preserved!). | ||
| 498 |   /// | ||
| 499 |   /// The APInt passed into this routine must be at exactly as wide as the | ||
| 500 |   /// IntPtr type for the address space of the base GEP pointer. | ||
| 501 | bool accumulateConstantOffset( | ||
| 502 | const DataLayout &DL, APInt &Offset, | ||
| 503 | function_ref<bool(Value &, APInt &)> ExternalAnalysis = nullptr) const; | ||
| 504 | |||
| 505 | static bool accumulateConstantOffset( | ||
| 506 | Type *SourceType, ArrayRef<const Value *> Index, const DataLayout &DL, | ||
| 507 |       APInt &Offset, | ||
| 508 | function_ref<bool(Value &, APInt &)> ExternalAnalysis = nullptr); | ||
| 509 | |||
| 510 |   /// Collect the offset of this GEP as a map of Values to their associated | ||
| 511 |   /// APInt multipliers, as well as a total Constant Offset. | ||
| 512 | bool collectOffset(const DataLayout &DL, unsigned BitWidth, | ||
| 513 | MapVector<Value *, APInt> &VariableOffsets, | ||
| 514 | APInt &ConstantOffset) const; | ||
| 515 | }; | ||
| 516 | |||
| 517 | class PtrToIntOperator | ||
| 518 | : public ConcreteOperator<Operator, Instruction::PtrToInt> { | ||
| 519 | friend class PtrToInt; | ||
| 520 | friend class ConstantExpr; | ||
| 521 | |||
| 522 | public: | ||
| 523 | Value *getPointerOperand() { | ||
| 524 | return getOperand(0); | ||
| 525 |   } | ||
| 526 | const Value *getPointerOperand() const { | ||
| 527 | return getOperand(0); | ||
| 528 |   } | ||
| 529 | |||
| 530 | static unsigned getPointerOperandIndex() { | ||
| 531 | return 0U; // get index for modifying correct operand | ||
| 532 |   } | ||
| 533 | |||
| 534 |   /// Method to return the pointer operand as a PointerType. | ||
| 535 | Type *getPointerOperandType() const { | ||
| 536 | return getPointerOperand()->getType(); | ||
| 537 |   } | ||
| 538 | |||
| 539 |   /// Method to return the address space of the pointer operand. | ||
| 540 | unsigned getPointerAddressSpace() const { | ||
| 541 | return cast<PointerType>(getPointerOperandType())->getAddressSpace(); | ||
| 542 |   } | ||
| 543 | }; | ||
| 544 | |||
| 545 | class BitCastOperator | ||
| 546 | : public ConcreteOperator<Operator, Instruction::BitCast> { | ||
| 547 | friend class BitCastInst; | ||
| 548 | friend class ConstantExpr; | ||
| 549 | |||
| 550 | public: | ||
| 551 | Type *getSrcTy() const { | ||
| 552 | return getOperand(0)->getType(); | ||
| 553 |   } | ||
| 554 | |||
| 555 | Type *getDestTy() const { | ||
| 556 | return getType(); | ||
| 557 |   } | ||
| 558 | }; | ||
| 559 | |||
| 560 | class AddrSpaceCastOperator | ||
| 561 | : public ConcreteOperator<Operator, Instruction::AddrSpaceCast> { | ||
| 562 | friend class AddrSpaceCastInst; | ||
| 563 | friend class ConstantExpr; | ||
| 564 | |||
| 565 | public: | ||
| 566 | Value *getPointerOperand() { return getOperand(0); } | ||
| 567 | |||
| 568 | const Value *getPointerOperand() const { return getOperand(0); } | ||
| 569 | |||
| 570 | unsigned getSrcAddressSpace() const { | ||
| 571 | return getPointerOperand()->getType()->getPointerAddressSpace(); | ||
| 572 |   } | ||
| 573 | |||
| 574 | unsigned getDestAddressSpace() const { | ||
| 575 | return getType()->getPointerAddressSpace(); | ||
| 576 |   } | ||
| 577 | }; | ||
| 578 | |||
| 579 | } // end namespace llvm | ||
| 580 | |||
| 581 | #endif // LLVM_IR_OPERATOR_H |