ExpandLargeDivRem.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. //===--- ExpandLargeDivRem.cpp - Expand large div/rem ---------------------===//
  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 pass expands div/rem instructions with a bitwidth above a threshold
  10. // into a call to auto-generated functions.
  11. // This is useful for targets like x86_64 that cannot lower divisions
  12. // with more than 128 bits or targets like x86_32 that cannot lower divisions
  13. // with more than 64 bits.
  14. //
  15. //===----------------------------------------------------------------------===//
  16. #include "llvm/ADT/SmallVector.h"
  17. #include "llvm/ADT/StringExtras.h"
  18. #include "llvm/Analysis/GlobalsModRef.h"
  19. #include "llvm/CodeGen/Passes.h"
  20. #include "llvm/CodeGen/TargetLowering.h"
  21. #include "llvm/CodeGen/TargetPassConfig.h"
  22. #include "llvm/CodeGen/TargetSubtargetInfo.h"
  23. #include "llvm/IR/IRBuilder.h"
  24. #include "llvm/IR/InstIterator.h"
  25. #include "llvm/IR/PassManager.h"
  26. #include "llvm/InitializePasses.h"
  27. #include "llvm/Pass.h"
  28. #include "llvm/Support/CommandLine.h"
  29. #include "llvm/Target/TargetMachine.h"
  30. #include "llvm/Transforms/Utils/IntegerDivision.h"
  31. using namespace llvm;
  32. static cl::opt<unsigned>
  33. ExpandDivRemBits("expand-div-rem-bits", cl::Hidden,
  34. cl::init(llvm::IntegerType::MAX_INT_BITS),
  35. cl::desc("div and rem instructions on integers with "
  36. "more than <N> bits are expanded."));
  37. static bool isConstantPowerOfTwo(llvm::Value *V, bool SignedOp) {
  38. auto *C = dyn_cast<ConstantInt>(V);
  39. if (!C)
  40. return false;
  41. APInt Val = C->getValue();
  42. if (SignedOp && Val.isNegative())
  43. Val = -Val;
  44. return Val.isPowerOf2();
  45. }
  46. static bool isSigned(unsigned int Opcode) {
  47. return Opcode == Instruction::SDiv || Opcode == Instruction::SRem;
  48. }
  49. static bool runImpl(Function &F, const TargetLowering &TLI) {
  50. SmallVector<BinaryOperator *, 4> Replace;
  51. bool Modified = false;
  52. unsigned MaxLegalDivRemBitWidth = TLI.getMaxDivRemBitWidthSupported();
  53. if (ExpandDivRemBits != llvm::IntegerType::MAX_INT_BITS)
  54. MaxLegalDivRemBitWidth = ExpandDivRemBits;
  55. if (MaxLegalDivRemBitWidth >= llvm::IntegerType::MAX_INT_BITS)
  56. return false;
  57. for (auto &I : instructions(F)) {
  58. switch (I.getOpcode()) {
  59. case Instruction::UDiv:
  60. case Instruction::SDiv:
  61. case Instruction::URem:
  62. case Instruction::SRem: {
  63. // TODO: This doesn't handle vectors.
  64. auto *IntTy = dyn_cast<IntegerType>(I.getType());
  65. if (!IntTy || IntTy->getIntegerBitWidth() <= MaxLegalDivRemBitWidth)
  66. continue;
  67. // The backend has peephole optimizations for powers of two.
  68. if (isConstantPowerOfTwo(I.getOperand(1), isSigned(I.getOpcode())))
  69. continue;
  70. Replace.push_back(&cast<BinaryOperator>(I));
  71. Modified = true;
  72. break;
  73. }
  74. default:
  75. break;
  76. }
  77. }
  78. if (Replace.empty())
  79. return false;
  80. while (!Replace.empty()) {
  81. BinaryOperator *I = Replace.pop_back_val();
  82. if (I->getOpcode() == Instruction::UDiv ||
  83. I->getOpcode() == Instruction::SDiv) {
  84. expandDivision(I);
  85. } else {
  86. expandRemainder(I);
  87. }
  88. }
  89. return Modified;
  90. }
  91. namespace {
  92. class ExpandLargeDivRemLegacyPass : public FunctionPass {
  93. public:
  94. static char ID;
  95. ExpandLargeDivRemLegacyPass() : FunctionPass(ID) {
  96. initializeExpandLargeDivRemLegacyPassPass(*PassRegistry::getPassRegistry());
  97. }
  98. bool runOnFunction(Function &F) override {
  99. auto *TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
  100. auto *TLI = TM->getSubtargetImpl(F)->getTargetLowering();
  101. return runImpl(F, *TLI);
  102. }
  103. void getAnalysisUsage(AnalysisUsage &AU) const override {
  104. AU.addRequired<TargetPassConfig>();
  105. AU.addPreserved<AAResultsWrapperPass>();
  106. AU.addPreserved<GlobalsAAWrapperPass>();
  107. }
  108. };
  109. } // namespace
  110. char ExpandLargeDivRemLegacyPass::ID = 0;
  111. INITIALIZE_PASS_BEGIN(ExpandLargeDivRemLegacyPass, "expand-large-div-rem",
  112. "Expand large div/rem", false, false)
  113. INITIALIZE_PASS_END(ExpandLargeDivRemLegacyPass, "expand-large-div-rem",
  114. "Expand large div/rem", false, false)
  115. FunctionPass *llvm::createExpandLargeDivRemPass() {
  116. return new ExpandLargeDivRemLegacyPass();
  117. }