xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonMask.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- HexagonMask.cpp - replace const ext tfri with mask ------===//
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 //===----------------------------------------------------------------------===//
10 
11 #include "Hexagon.h"
12 #include "HexagonSubtarget.h"
13 #include "llvm/ADT/Statistic.h"
14 #include "llvm/CodeGen/MachineFunction.h"
15 #include "llvm/CodeGen/MachineFunctionPass.h"
16 #include "llvm/CodeGen/MachineInstrBuilder.h"
17 #include "llvm/CodeGen/Passes.h"
18 #include "llvm/IR/Function.h"
19 #include "llvm/Support/MathExtras.h"
20 #include "llvm/Target/TargetMachine.h"
21 
22 #define DEBUG_TYPE "mask"
23 
24 using namespace llvm;
25 
26 namespace {
27 class HexagonMask : public MachineFunctionPass {
28 public:
29   static char ID;
HexagonMask()30   HexagonMask() : MachineFunctionPass(ID) {}
31 
getPassName() const32   StringRef getPassName() const override {
33     return "Hexagon replace const ext tfri with mask";
34   }
35   bool runOnMachineFunction(MachineFunction &MF) override;
36 
37 private:
38   const HexagonInstrInfo *HII;
39   void replaceConstExtTransferImmWithMask(MachineFunction &MF);
40 };
41 } // end anonymous namespace
42 
43 char HexagonMask::ID = 0;
44 
replaceConstExtTransferImmWithMask(MachineFunction & MF)45 void HexagonMask::replaceConstExtTransferImmWithMask(MachineFunction &MF) {
46   for (auto &MBB : MF) {
47     for (auto &MI : llvm::make_early_inc_range(MBB)) {
48       if (MI.getOpcode() != Hexagon::A2_tfrsi)
49         continue;
50 
51       const MachineOperand &Op0 = MI.getOperand(0);
52       const MachineOperand &Op1 = MI.getOperand(1);
53       if (!Op1.isImm())
54         continue;
55       int32_t V = Op1.getImm();
56       if (isInt<16>(V))
57         continue;
58 
59       unsigned Idx, Len;
60       if (!isShiftedMask_32(V, Idx, Len))
61         continue;
62       if (!isUInt<5>(Idx) || !isUInt<5>(Len))
63         continue;
64 
65       BuildMI(MBB, MI, MI.getDebugLoc(), HII->get(Hexagon::S2_mask),
66               Op0.getReg())
67           .addImm(Len)
68           .addImm(Idx);
69       MBB.erase(MI);
70     }
71   }
72 }
73 
runOnMachineFunction(MachineFunction & MF)74 bool HexagonMask::runOnMachineFunction(MachineFunction &MF) {
75   auto &HST = MF.getSubtarget<HexagonSubtarget>();
76   HII = HST.getInstrInfo();
77   const Function &F = MF.getFunction();
78 
79   if (!F.hasFnAttribute(Attribute::OptimizeForSize))
80     return false;
81   // Mask instruction is available only from v66
82   if (!HST.hasV66Ops())
83     return false;
84   // The mask instruction available in v66 can be used to generate values in
85   // registers using 2 immediates Eg. to form 0x07fffffc in R0, you would write
86   // "R0 = mask(#25,#2)" Since it is a single-word instruction, it takes less
87   // code size than a constant-extended transfer at Os
88   replaceConstExtTransferImmWithMask(MF);
89 
90   return true;
91 }
92 
93 //===----------------------------------------------------------------------===//
94 //                         Public Constructor Functions
95 //===----------------------------------------------------------------------===//
96 
97 INITIALIZE_PASS(HexagonMask, "hexagon-mask", "Hexagon mask", false, false)
98 
createHexagonMask()99 FunctionPass *llvm::createHexagonMask() { return new HexagonMask(); }
100