BypassSlowDivision.h 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- llvm/Transforms/Utils/BypassSlowDivision.h ---------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file contains an optimization for div and rem on architectures that
  15. // execute short instructions significantly faster than longer instructions.
  16. // For example, on Intel Atom 32-bit divides are slow enough that during
  17. // runtime it is profitable to check the value of the operands, and if they are
  18. // positive and less than 256 use an unsigned 8-bit divide.
  19. //
  20. //===----------------------------------------------------------------------===//
  21. #ifndef LLVM_TRANSFORMS_UTILS_BYPASSSLOWDIVISION_H
  22. #define LLVM_TRANSFORMS_UTILS_BYPASSSLOWDIVISION_H
  23. #include "llvm/ADT/DenseMap.h"
  24. #include "llvm/ADT/DenseMapInfo.h"
  25. #include "llvm/IR/ValueHandle.h"
  26. #include <cstdint>
  27. namespace llvm {
  28. class BasicBlock;
  29. class Value;
  30. struct DivRemMapKey {
  31. bool SignedOp;
  32. AssertingVH<Value> Dividend;
  33. AssertingVH<Value> Divisor;
  34. DivRemMapKey() = default;
  35. DivRemMapKey(bool InSignedOp, Value *InDividend, Value *InDivisor)
  36. : SignedOp(InSignedOp), Dividend(InDividend), Divisor(InDivisor) {}
  37. };
  38. template <> struct DenseMapInfo<DivRemMapKey> {
  39. static bool isEqual(const DivRemMapKey &Val1, const DivRemMapKey &Val2) {
  40. return Val1.SignedOp == Val2.SignedOp && Val1.Dividend == Val2.Dividend &&
  41. Val1.Divisor == Val2.Divisor;
  42. }
  43. static DivRemMapKey getEmptyKey() {
  44. return DivRemMapKey(false, nullptr, nullptr);
  45. }
  46. static DivRemMapKey getTombstoneKey() {
  47. return DivRemMapKey(true, nullptr, nullptr);
  48. }
  49. static unsigned getHashValue(const DivRemMapKey &Val) {
  50. return (unsigned)(reinterpret_cast<uintptr_t>(
  51. static_cast<Value *>(Val.Dividend)) ^
  52. reinterpret_cast<uintptr_t>(
  53. static_cast<Value *>(Val.Divisor))) ^
  54. (unsigned)Val.SignedOp;
  55. }
  56. };
  57. /// This optimization identifies DIV instructions in a BB that can be
  58. /// profitably bypassed and carried out with a shorter, faster divide.
  59. ///
  60. /// This optimization may add basic blocks immediately after BB; for obvious
  61. /// reasons, you shouldn't pass those blocks to bypassSlowDivision.
  62. bool bypassSlowDivision(
  63. BasicBlock *BB, const DenseMap<unsigned int, unsigned int> &BypassWidth);
  64. } // end namespace llvm
  65. #endif // LLVM_TRANSFORMS_UTILS_BYPASSSLOWDIVISION_H
  66. #ifdef __GNUC__
  67. #pragma GCC diagnostic pop
  68. #endif