From 025e2ea89794c1a3e98bac2c0a5182ad1e1d4378 Mon Sep 17 00:00:00 2001 From: quic-asaravan Date: Thu, 16 May 2024 01:17:49 -0700 Subject: [PATCH] [HEXAGON] Utilize new mask instruction Co-authored-by: Harsha Jagasia Co-authored-by: Krzysztof Parzyszek --- llvm/lib/Target/Hexagon/CMakeLists.txt | 1 + llvm/lib/Target/Hexagon/HexagonMask.cpp | 110 ++++++++++++++++++ .../Target/Hexagon/HexagonTargetMachine.cpp | 11 ++ llvm/test/CodeGen/Hexagon/mask.ll | 17 +++ 4 files changed, 139 insertions(+) create mode 100644 llvm/lib/Target/Hexagon/HexagonMask.cpp create mode 100644 llvm/test/CodeGen/Hexagon/mask.ll diff --git a/llvm/lib/Target/Hexagon/CMakeLists.txt b/llvm/lib/Target/Hexagon/CMakeLists.txt index 9e4ca08aea40d..e8ec93dd5ee63 100644 --- a/llvm/lib/Target/Hexagon/CMakeLists.txt +++ b/llvm/lib/Target/Hexagon/CMakeLists.txt @@ -48,6 +48,7 @@ add_llvm_target(HexagonCodeGen HexagonLoopIdiomRecognition.cpp HexagonMachineFunctionInfo.cpp HexagonMachineScheduler.cpp + HexagonMask.cpp HexagonMCInstLower.cpp HexagonNewValueJump.cpp HexagonOptAddrMode.cpp diff --git a/llvm/lib/Target/Hexagon/HexagonMask.cpp b/llvm/lib/Target/Hexagon/HexagonMask.cpp new file mode 100644 index 0000000000000..ac9abfa6c1233 --- /dev/null +++ b/llvm/lib/Target/Hexagon/HexagonMask.cpp @@ -0,0 +1,110 @@ +//===-- 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 +// +//===----------------------------------------------------------------------===// +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mask" + +#include "HexagonMachineFunctionInfo.h" +#include "HexagonSubtarget.h" +#include "HexagonTargetMachine.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/Twine.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Target/TargetMachine.h" + +using namespace llvm; + +namespace llvm { +FunctionPass *createHexagonMask(); +void initializeHexagonMaskPass(PassRegistry &); + +class HexagonMask : public MachineFunctionPass { +public: + static char ID; + HexagonMask() : MachineFunctionPass(ID) { + PassRegistry &Registry = *PassRegistry::getPassRegistry(); + initializeHexagonMaskPass(Registry); + } + + 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); +}; + +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; + // 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; +} + +} // namespace llvm + +//===----------------------------------------------------------------------===// +// Public Constructor Functions +//===----------------------------------------------------------------------===// + +INITIALIZE_PASS(HexagonMask, "hexagon-mask", "Hexagon mask", false, false) + +FunctionPass *llvm::createHexagonMask() { return new HexagonMask(); } diff --git a/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp b/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp index b362285d4f16e..803b9b81045c6 100644 --- a/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp +++ b/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp @@ -59,6 +59,10 @@ static cl::opt DisableHCP("disable-hcp", cl::Hidden, cl::desc("Disable Hexagon constant propagation")); +static cl::opt DisableHexagonMask( + "disable-mask", cl::Hidden, + cl::desc("Disable Hexagon specific Mask generation pass")); + static cl::opt DisableStoreWidening("disable-store-widen", cl::Hidden, cl::init(false), cl::desc("Disable store widening")); @@ -180,6 +184,8 @@ void initializeHexagonGenMuxPass(PassRegistry &); void initializeHexagonHardwareLoopsPass(PassRegistry &); void initializeHexagonLoopIdiomRecognizeLegacyPassPass(PassRegistry &); void initializeHexagonLoopAlignPass(PassRegistry &); +void initializeHexagonMaskPass(PassRegistry &); +void initializeHexagonMergeActivateWeightPass(PassRegistry &); void initializeHexagonNewValueJumpPass(PassRegistry &); void initializeHexagonOptAddrModePass(PassRegistry &); void initializeHexagonPacketizerPass(PassRegistry &); @@ -213,6 +219,8 @@ FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM, CodeGenOptLevel OptLevel); FunctionPass *createHexagonLoopAlign(); FunctionPass *createHexagonLoopRescheduling(); +FunctionPass *createHexagonMask(); +FunctionPass *createHexagonMergeActivateWeight(); FunctionPass *createHexagonNewValueJump(); FunctionPass *createHexagonOptAddrMode(); FunctionPass *createHexagonOptimizeSZextends(); @@ -474,10 +482,13 @@ void HexagonPassConfig::addPostRegAlloc() { } void HexagonPassConfig::addPreSched2() { + bool NoOpt = (getOptLevel() == CodeGenOptLevel::None); addPass(createHexagonCopyToCombine()); if (getOptLevel() != CodeGenOptLevel::None) addPass(&IfConverterID); addPass(createHexagonSplitConst32AndConst64()); + if (!NoOpt && !DisableHexagonMask) + addPass(createHexagonMask()); } void HexagonPassConfig::addPreEmitPass() { diff --git a/llvm/test/CodeGen/Hexagon/mask.ll b/llvm/test/CodeGen/Hexagon/mask.ll new file mode 100644 index 0000000000000..698d1ac26d248 --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/mask.ll @@ -0,0 +1,17 @@ +; RUN: llc -mtriple=hexagon -mcpu=hexagonv73 < %s | FileCheck %s + +target triple = "hexagon" + +; CHECK-LABEL: test1: +; CHECK: r0 = mask(#25,#2) +; Function Attrs: optsize +define i32 @test1() #1 { +entry: + %0 = call i32 @llvm.hexagon.A2.tfr(i32 134217724) + ret i32 %0 +} + +declare i32 @llvm.hexagon.A2.tfr(i32) #0 + +attributes #0 = { nounwind readnone } +attributes #1 = { optsize }