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