brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.2 KiB · 1322c62 Raw
259 lines · cpp
1//===- HexagonGenExtract.cpp ----------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "Hexagon.h"10#include "llvm/ADT/APInt.h"11#include "llvm/ADT/GraphTraits.h"12#include "llvm/IR/BasicBlock.h"13#include "llvm/IR/CFG.h"14#include "llvm/IR/Constants.h"15#include "llvm/IR/Dominators.h"16#include "llvm/IR/Function.h"17#include "llvm/IR/IRBuilder.h"18#include "llvm/IR/Instruction.h"19#include "llvm/IR/Instructions.h"20#include "llvm/IR/Intrinsics.h"21#include "llvm/IR/IntrinsicsHexagon.h"22#include "llvm/IR/PatternMatch.h"23#include "llvm/IR/Type.h"24#include "llvm/IR/Value.h"25#include "llvm/InitializePasses.h"26#include "llvm/Pass.h"27#include "llvm/Support/CommandLine.h"28#include <algorithm>29#include <cstdint>30#include <iterator>31 32using namespace llvm;33 34static cl::opt<unsigned> ExtractCutoff("extract-cutoff", cl::init(~0U),35  cl::Hidden, cl::desc("Cutoff for generating \"extract\""36  " instructions"));37 38// This prevents generating extract instructions that have the offset of 0.39// One of the reasons for "extract" is to put a sequence of bits in a regis-40// ter, starting at offset 0 (so that these bits can then be used by an41// "insert"). If the bits are already at offset 0, it is better not to gene-42// rate "extract", since logical bit operations can be merged into compound43// instructions (as opposed to "extract").44static cl::opt<bool> NoSR0("extract-nosr0", cl::init(true), cl::Hidden,45  cl::desc("No extract instruction with offset 0"));46 47namespace {48 49  class HexagonGenExtract : public FunctionPass {50  public:51    static char ID;52 53    HexagonGenExtract() : FunctionPass(ID) {}54 55    StringRef getPassName() const override {56      return "Hexagon generate \"extract\" instructions";57    }58 59    bool runOnFunction(Function &F) override;60 61    void getAnalysisUsage(AnalysisUsage &AU) const override {62      AU.addRequired<DominatorTreeWrapperPass>();63      AU.addPreserved<DominatorTreeWrapperPass>();64      FunctionPass::getAnalysisUsage(AU);65    }66 67  private:68    bool visitBlock(BasicBlock *B);69    bool convert(Instruction *In);70 71    unsigned ExtractCount = 0;72    DominatorTree *DT;73  };74 75} // end anonymous namespace76 77char HexagonGenExtract::ID = 0;78 79INITIALIZE_PASS_BEGIN(HexagonGenExtract, "hextract", "Hexagon generate "80  "\"extract\" instructions", false, false)81INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)82INITIALIZE_PASS_END(HexagonGenExtract, "hextract", "Hexagon generate "83  "\"extract\" instructions", false, false)84 85bool HexagonGenExtract::convert(Instruction *In) {86  using namespace PatternMatch;87 88  Value *BF = nullptr;89  ConstantInt *CSL = nullptr, *CSR = nullptr, *CM = nullptr;90  BasicBlock *BB = In->getParent();91  LLVMContext &Ctx = BB->getContext();92  bool LogicalSR;93 94  // (and (shl (lshr x, #sr), #sl), #m)95  LogicalSR = true;96  bool Match = match(In, m_And(m_Shl(m_LShr(m_Value(BF), m_ConstantInt(CSR)),97                               m_ConstantInt(CSL)),98                         m_ConstantInt(CM)));99 100  if (!Match) {101    // (and (shl (ashr x, #sr), #sl), #m)102    LogicalSR = false;103    Match = match(In, m_And(m_Shl(m_AShr(m_Value(BF), m_ConstantInt(CSR)),104                            m_ConstantInt(CSL)),105                      m_ConstantInt(CM)));106  }107  if (!Match) {108    // (and (shl x, #sl), #m)109    LogicalSR = true;110    CSR = ConstantInt::get(Type::getInt32Ty(Ctx), 0);111    Match = match(In, m_And(m_Shl(m_Value(BF), m_ConstantInt(CSL)),112                      m_ConstantInt(CM)));113    if (Match && NoSR0)114      return false;115  }116  if (!Match) {117    // (and (lshr x, #sr), #m)118    LogicalSR = true;119    CSL = ConstantInt::get(Type::getInt32Ty(Ctx), 0);120    Match = match(In, m_And(m_LShr(m_Value(BF), m_ConstantInt(CSR)),121                            m_ConstantInt(CM)));122  }123  if (!Match) {124    // (and (ashr x, #sr), #m)125    LogicalSR = false;126    CSL = ConstantInt::get(Type::getInt32Ty(Ctx), 0);127    Match = match(In, m_And(m_AShr(m_Value(BF), m_ConstantInt(CSR)),128                            m_ConstantInt(CM)));129  }130  if (!Match) {131    CM = nullptr;132    // (shl (lshr x, #sr), #sl)133    LogicalSR = true;134    Match = match(In, m_Shl(m_LShr(m_Value(BF), m_ConstantInt(CSR)),135                            m_ConstantInt(CSL)));136  }137  if (!Match) {138    CM = nullptr;139    // (shl (ashr x, #sr), #sl)140    LogicalSR = false;141    Match = match(In, m_Shl(m_AShr(m_Value(BF), m_ConstantInt(CSR)),142                            m_ConstantInt(CSL)));143  }144  if (!Match)145    return false;146 147  Type *Ty = BF->getType();148  if (!Ty->isIntegerTy())149    return false;150  unsigned BW = Ty->getPrimitiveSizeInBits();151  if (BW != 32 && BW != 64)152    return false;153 154  uint32_t SR = CSR->getZExtValue();155  uint32_t SL = CSL->getZExtValue();156 157  if (!CM) {158    // If there was no and, and the shift left did not remove all potential159    // sign bits created by the shift right, then extractu cannot reproduce160    // this value.161    if (!LogicalSR && (SR > SL))162      return false;163    APInt A = APInt(BW, ~0ULL, true).lshr(SR).shl(SL);164    CM = ConstantInt::get(Ctx, A);165  }166 167  // CM is the shifted-left mask. Shift it back right to remove the zero168  // bits on least-significant positions.169  APInt M = CM->getValue().lshr(SL);170  uint32_t T = M.countr_one();171 172  // During the shifts some of the bits will be lost. Calculate how many173  // of the original value will remain after shift right and then left.174  uint32_t U = BW - std::max(SL, SR);175  // The width of the extracted field is the minimum of the original bits176  // that remain after the shifts and the number of contiguous 1s in the mask.177  uint32_t W = std::min(U, T);178  if (W == 0 || W == 1)179    return false;180 181  // Check if the extracted bits are contained within the mask that it is182  // and-ed with. The extract operation will copy these bits, and so the183  // mask cannot any holes in it that would clear any of the bits of the184  // extracted field.185  if (!LogicalSR) {186    // If the shift right was arithmetic, it could have included some 1 bits.187    // It is still ok to generate extract, but only if the mask eliminates188    // those bits (i.e. M does not have any bits set beyond U).189    APInt C = APInt::getHighBitsSet(BW, BW-U);190    if (M.intersects(C) || !M.isMask(W))191      return false;192  } else {193    // Check if M starts with a contiguous sequence of W times 1 bits. Get194    // the low U bits of M (which eliminates the 0 bits shifted in on the195    // left), and check if the result is APInt's "mask":196    if (!M.getLoBits(U).isMask(W))197      return false;198  }199 200  IRBuilder<> IRB(In);201  Intrinsic::ID IntId = (BW == 32) ? Intrinsic::hexagon_S2_extractu202                                   : Intrinsic::hexagon_S2_extractup;203  Value *NewIn =204      IRB.CreateIntrinsic(IntId, {BF, IRB.getInt32(W), IRB.getInt32(SR)});205  if (SL != 0)206    NewIn = IRB.CreateShl(NewIn, SL, CSL->getName());207  In->replaceAllUsesWith(NewIn);208  return true;209}210 211bool HexagonGenExtract::visitBlock(BasicBlock *B) {212  bool Changed = false;213 214  // Depth-first, bottom-up traversal.215  for (auto *DTN : children<DomTreeNode*>(DT->getNode(B)))216    Changed |= visitBlock(DTN->getBlock());217 218  // Allow limiting the number of generated extracts for debugging purposes.219  bool HasCutoff = ExtractCutoff.getPosition();220  unsigned Cutoff = ExtractCutoff;221 222  BasicBlock::iterator I = std::prev(B->end()), NextI, Begin = B->begin();223  while (true) {224    if (HasCutoff && (ExtractCount >= Cutoff))225      return Changed;226    bool Last = (I == Begin);227    if (!Last)228      NextI = std::prev(I);229    Instruction *In = &*I;230    bool Done = convert(In);231    if (HasCutoff && Done)232      ExtractCount++;233    Changed |= Done;234    if (Last)235      break;236    I = NextI;237  }238  return Changed;239}240 241bool HexagonGenExtract::runOnFunction(Function &F) {242  if (skipFunction(F))243    return false;244 245  DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();246  bool Changed;247 248  // Traverse the function bottom-up, to see super-expressions before their249  // sub-expressions.250  BasicBlock *Entry = GraphTraits<Function*>::getEntryNode(&F);251  Changed = visitBlock(Entry);252 253  return Changed;254}255 256FunctionPass *llvm::createHexagonGenExtract() {257  return new HexagonGenExtract();258}259