//===-- HexagonMask.cpp - replace const ext tfri with mask ------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // //===----------------------------------------------------------------------===// #include "Hexagon.h" #include "HexagonSubtarget.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/Passes.h" #include "llvm/IR/Function.h" #include "llvm/Support/MathExtras.h" #include "llvm/Target/TargetMachine.h" #define DEBUG_TYPE "mask" using namespace llvm; namespace { class HexagonMask : public MachineFunctionPass { public: static char ID; HexagonMask() : MachineFunctionPass(ID) {} StringRef getPassName() const override { return "Hexagon replace const ext tfri with mask"; } bool runOnMachineFunction(MachineFunction &MF) override; private: const HexagonInstrInfo *HII; void replaceConstExtTransferImmWithMask(MachineFunction &MF); }; } // end anonymous namespace char HexagonMask::ID = 0; void HexagonMask::replaceConstExtTransferImmWithMask(MachineFunction &MF) { for (auto &MBB : MF) { for (auto &MI : llvm::make_early_inc_range(MBB)) { if (MI.getOpcode() != Hexagon::A2_tfrsi) continue; const MachineOperand &Op0 = MI.getOperand(0); const MachineOperand &Op1 = MI.getOperand(1); if (!Op1.isImm()) continue; int32_t V = Op1.getImm(); if (isInt<16>(V)) continue; unsigned Idx, Len; if (!isShiftedMask_32(V, Idx, Len)) continue; if (!isUInt<5>(Idx) || !isUInt<5>(Len)) continue; BuildMI(MBB, MI, MI.getDebugLoc(), HII->get(Hexagon::S2_mask), Op0.getReg()) .addImm(Len) .addImm(Idx); MBB.erase(MI); } } } bool HexagonMask::runOnMachineFunction(MachineFunction &MF) { auto &HST = MF.getSubtarget(); HII = HST.getInstrInfo(); const Function &F = MF.getFunction(); if (!F.hasFnAttribute(Attribute::OptimizeForSize)) return false; // Mask instruction is available only from v66 if (!HST.hasV66Ops()) return false; // The mask instruction available in v66 can be used to generate values in // registers using 2 immediates Eg. to form 0x07fffffc in R0, you would write // "R0 = mask(#25,#2)" Since it is a single-word instruction, it takes less // code size than a constant-extended transfer at Os replaceConstExtTransferImmWithMask(MF); return true; } //===----------------------------------------------------------------------===// // Public Constructor Functions //===----------------------------------------------------------------------===// INITIALIZE_PASS(HexagonMask, "hexagon-mask", "Hexagon mask", false, false) FunctionPass *llvm::createHexagonMask() { return new HexagonMask(); }