100 lines
3.0 KiB
C++
100 lines
3.0 KiB
C++
//===-- 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<HexagonSubtarget>();
|
|
HII = HST.getInstrInfo();
|
|
const Function &F = MF.getFunction();
|
|
|
|
if (!F.hasOptSize())
|
|
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(); }
|