Skip to content

Commit

Permalink
Add hardware loop code generation (#17)
Browse files Browse the repository at this point in the history
* [COREV] Track Hwlp Basic Blocks in MachineFunctionInfo

Signed-off-by: Serkan Muhcu <serkan.muhcu@student.uni-tuebingen.de>

* [COREV] Add hardware loop code generation

Signed-off-by: Serkan Muhcu <serkan.muhcu@student.uni-tuebingen.de>

* [COREV] Add hwlp codegen tests

Signed-off-by: Serkan Muhcu <serkan.muhcu@student.uni-tuebingen.de>

* [COREV] Remove braces around return statements

Signed-off-by: Serkan Muhcu <serkan.muhcu@student.uni-tuebingen.de>
  • Loading branch information
serkm authored and Charlie Keaney committed Nov 2, 2022
1 parent 552b61f commit 6c12852
Show file tree
Hide file tree
Showing 18 changed files with 1,020 additions and 6 deletions.
2 changes: 2 additions & 0 deletions llvm/lib/Target/RISCV/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ add_llvm_target(RISCVCodeGen
RISCVCallLowering.cpp
RISCVCodeGenPrepare.cpp
RISCVMakeCompressible.cpp
RISCVCoreVHwlpBlocks.cpp
RISCVExpandAtomicPseudoInsts.cpp
RISCVExpandCoreVHwlpPseudoInsts.cpp
RISCVExpandPseudoInsts.cpp
RISCVFrameLowering.cpp
RISCVGatherScatterLowering.cpp
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/RISCV/RISCV.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ void initializeRISCVInsertVSETVLIPass(PassRegistry &);
FunctionPass *createRISCVRedundantCopyEliminationPass();
void initializeRISCVRedundantCopyEliminationPass(PassRegistry &);

FunctionPass *createRISCVCoreVHwlpBlocksPass();
void initializeRISCVCoreVHwlpBlocksPass(PassRegistry &);

FunctionPass *createRISCVExpandCoreVHwlpPseudoPass();
void initializeRISCVExpandCoreVHwlpPseudoPass(PassRegistry &);

InstructionSelector *createRISCVInstructionSelector(const RISCVTargetMachine &,
RISCVSubtarget &,
RISCVRegisterBankInfo &);
Expand Down
39 changes: 37 additions & 2 deletions llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "MCTargetDesc/RISCVTargetStreamer.h"
#include "RISCV.h"
#include "RISCVTargetMachine.h"
#include "RISCVMachineFunctionInfo.h"
#include "TargetInfo/RISCVTargetInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/BinaryFormat/ELF.h"
Expand Down Expand Up @@ -81,6 +82,9 @@ class RISCVAsmPrinter : public AsmPrinter {
void emitStartOfAsmFile(Module &M) override;
void emitEndOfAsmFile(Module &M) override;

void emitBasicBlockStart(const MachineBasicBlock &MBB) override;
void emitBasicBlockEnd(const MachineBasicBlock &MBB) override;

private:
void emitAttributes();
};
Expand Down Expand Up @@ -115,8 +119,16 @@ void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) {
return;
}

if (!lowerRISCVMachineInstrToMCInst(MI, TmpInst, *this))
EmitToStreamer(*OutStreamer, TmpInst);
if (!lowerRISCVMachineInstrToMCInst(MI, TmpInst, *this)) {

auto *MBB = MI->getParent();
auto *RVFI = MI->getMF()->getInfo<RISCVMachineFunctionInfo>();

if (RVFI->isHwlpBasicBlock(MBB))
AsmPrinter::EmitToStreamer(*OutStreamer, TmpInst);
else
EmitToStreamer(*OutStreamer, TmpInst);
}
}

bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
Expand Down Expand Up @@ -225,6 +237,29 @@ void RISCVAsmPrinter::emitAttributes() {
RTS.emitTargetAttributes(*MCSTI);
}

void RISCVAsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {
AsmPrinter::emitBasicBlockStart(MBB);

auto *RVFI = MF->getInfo<RISCVMachineFunctionInfo>();
RISCVTargetStreamer &RTS =
static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
if (RVFI->isHwlpBasicBlock(&MBB)) {
RTS.emitDirectiveOptionPush();
RTS.emitDirectiveOptionNoRVC();
}
}

void RISCVAsmPrinter::emitBasicBlockEnd(const MachineBasicBlock &MBB) {
auto *RVFI = MF->getInfo<RISCVMachineFunctionInfo>();
RISCVTargetStreamer &RTS =
static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
if (RVFI->isHwlpBasicBlock(&MBB)) {
RTS.emitDirectiveOptionPop();
}

AsmPrinter::emitBasicBlockEnd(MBB);
}

// Force static initialization.
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter() {
RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target());
Expand Down
135 changes: 135 additions & 0 deletions llvm/lib/Target/RISCV/RISCVCoreVHwlpBlocks.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
//===-- RISCVCoreVHwlpBlocks.cpp - Prepare hwlp basic blocks --------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file contains a pass that finds the basic blocks inside hardware loops,
// stores them in RISCVMachineFunctionInfo and reorders them to eliminate branch
// instructions.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "RISCV.h"
#include "RISCVSubtarget.h"
#include "RISCVMachineFunctionInfo.h"
using namespace llvm;

#define COREV_HWLP_BLOCKS_NAME "Core-V prepare hardware loop basic blocks pass"

#define DEBUG_TYPE "corev-hwlp-blocks"

namespace {
class RISCVCoreVHwlpBlocks : public MachineFunctionPass {

private:
bool ProcessLoop(MachineLoop *ML, MachineFunction &MF);

public:
static char ID;
RISCVCoreVHwlpBlocks() : MachineFunctionPass(ID) { }

bool runOnMachineFunction(MachineFunction &MF) override;

StringRef getPassName() const override {
return COREV_HWLP_BLOCKS_NAME;
}

void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<MachineLoopInfo>();
MachineFunctionPass::getAnalysisUsage(AU);
}
};
}

char RISCVCoreVHwlpBlocks::ID = 0;

bool RISCVCoreVHwlpBlocks::runOnMachineFunction(MachineFunction &MF) {
if (!MF.getSubtarget<RISCVSubtarget>().hasExtXCoreVHwlp()) {
return false;
}

MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>();

bool Changed = false;
for (auto &ML : MLI) {
Changed |= ProcessLoop(ML, MF);
}
return Changed;
}

bool RISCVCoreVHwlpBlocks::ProcessLoop(MachineLoop *ML, MachineFunction &MF) {

bool hwlp = false;
MachineBasicBlock *Preheader = ML->getLoopPreheader();
MachineBasicBlock *Latch = ML->getLoopLatch();
if (Latch && Preheader) {
for (auto &MI : *Preheader) {
if (MI.getOpcode() == RISCV::HwlpSetup ||
MI.getOpcode() == RISCV::HwlpSetupImm) {
hwlp = true;
break;
}
}
}
if (!hwlp) {
bool Changed = false;
for (auto Inner : *ML) {
Changed |= ProcessLoop(Inner, MF);
}
return Changed;
}

auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();

MachineBasicBlock *BB = Preheader;

while (BB != Latch) {
assert(BB->succ_size() <= 2 && "Too many basic block successors");

MachineBasicBlock *Next = *BB->succ_begin();

if (BB->succ_size() == 2) {
hwlp = false;
for (auto &MI : BB->terminators()) {
if (MI.getOpcode() == RISCV::HwlpBranch) {
hwlp = true;
if (Next == MI.getOperand(2).getMBB()) {
Next = *BB->succ_rbegin();
}
break;
}
}
assert(hwlp && "Conditional branch inside hwlp is not allowed");
}

if (!BB->isLayoutSuccessor(Next)) {
MachineBasicBlock *OldPred = Next->getPrevNode();
MachineBasicBlock *OldSucc1 = Next->getNextNode();
MachineBasicBlock *OldSucc2 = BB->getNextNode();
Next->moveAfter(BB);
OldPred->updateTerminator(Next);
Next->updateTerminator(OldSucc1);
BB->updateTerminator(OldSucc2);
}

RVFI->pushHwlpBasicBlock(Next);

BB = Next;

}

return true;
}

INITIALIZE_PASS(RISCVCoreVHwlpBlocks, DEBUG_TYPE, COREV_HWLP_BLOCKS_NAME,
false, false)

FunctionPass *llvm::createRISCVCoreVHwlpBlocksPass() {
return new RISCVCoreVHwlpBlocks();
}
Loading

0 comments on commit 6c12852

Please sign in to comment.