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; 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 37 private: 38 const HexagonInstrInfo *HII; 39 void replaceConstExtTransferImmWithMask(MachineFunction &MF); 40 }; 41 } // end anonymous namespace 42 43 char HexagonMask::ID = 0; 44 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 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 99 FunctionPass *llvm::createHexagonMask() { return new HexagonMask(); } 100