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