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
24using namespace llvm;
25
26namespace {
27class HexagonMask : public MachineFunctionPass {
28public:
29 static char ID;
30 HexagonMask() : MachineFunctionPass(ID) {}
31
32 StringRef getPassName() const override {
33 return "Hexagon replace const ext tfri with mask";
34 }
35 bool runOnMachineFunction(MachineFunction &MF) override;
36
37private:
38 const HexagonInstrInfo *HII;
39 void replaceConstExtTransferImmWithMask(MachineFunction &MF);
40};
41} // end anonymous namespace
42
43char HexagonMask::ID = 0;
44
45void HexagonMask::replaceConstExtTransferImmWithMask(MachineFunction &MF) {
46 for (auto &MBB : MF) {
47 for (auto &MI : llvm::make_early_inc_range(Range&: MBB)) {
48 if (MI.getOpcode() != Hexagon::A2_tfrsi)
49 continue;
50
51 const MachineOperand &Op0 = MI.getOperand(i: 0);
52 const MachineOperand &Op1 = MI.getOperand(i: 1);
53 if (!Op1.isImm())
54 continue;
55 int32_t V = Op1.getImm();
56 if (isInt<16>(x: V))
57 continue;
58
59 unsigned Idx, Len;
60 if (!isShiftedMask_32(Value: V, MaskIdx&: Idx, MaskLen&: Len))
61 continue;
62 if (!isUInt<5>(x: Idx) || !isUInt<5>(x: Len))
63 continue;
64
65 BuildMI(BB&: MBB, I&: MI, MIMD: MI.getDebugLoc(), MCID: HII->get(Opcode: Hexagon::S2_mask),
66 DestReg: Op0.getReg())
67 .addImm(Val: Len)
68 .addImm(Val: Idx);
69 MBB.erase(I: MI);
70 }
71 }
72}
73
74bool 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(Kind: 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
97INITIALIZE_PASS(HexagonMask, "hexagon-mask", "Hexagon mask", false, false)
98
99FunctionPass *llvm::createHexagonMask() { return new HexagonMask(); }
100