194 lines
6.6 KiB
C++
194 lines
6.6 KiB
C++
//===-- VentusLegalizeLoad.cpp - vlw12 instruction legalization ----------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Legalize vlw12.v instruction, in vararg function codegen, the vararg start
|
|
// index will be stored in stack, in ventus, this index will be store in private
|
|
// stack, some code example will be as below
|
|
// addi sp, sp, 4 | addi sp, sp, -64
|
|
// addi tp, tp, 80 | addi s0, sp, 32
|
|
// vsw.v v7, -80(v8) | sw a7, 28(s0)
|
|
// vsw.v v6, -76(v8) | sw a6, 24(s0)
|
|
// vsw.v v5, -72(v8) | sw a5, 20(s0)
|
|
// vsw.v v4, -68(v8) | sw a4, 16(s0)
|
|
// vsw.v v3, -64(v8) | sw a3, 12(s0)
|
|
// vsw.v v2, -60(v8) | sw a2, 8(s0)
|
|
// vsw.v v1, -56(v8) | sw a1, 4(s0)
|
|
// vsw.v v0, -48(v8) | sw a0, -16(s0)
|
|
// addi t0, tp, -56 | addi a0, s0, 4
|
|
// vmv.v.x v0, t0 | sw a0, -20(s0)
|
|
// vsw.v v0, -44(v8)
|
|
//
|
|
// left hand code is generated by ventus, right hand code is generated by
|
|
// standard riscv, when load from -44(v8), vlw.v v0, -44(v8), if need to
|
|
// load from v0, in right now ventus, the codegen will be like this vlw12.v v0,
|
|
// 0(v0), but it is actually illegal, it should be vlw.v v0, 0(v0)
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "MCTargetDesc/RISCVMCTargetDesc.h"
|
|
#include "RISCV.h"
|
|
#include "RISCVFrameLowering.h"
|
|
#include "RISCVISelLowering.h"
|
|
#include "RISCVInstrInfo.h"
|
|
#include "RISCVSubtarget.h"
|
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
#include "llvm/CodeGen/MachineOperand.h"
|
|
#include "llvm/CodeGen/Register.h"
|
|
#include "llvm/IR/DebugLoc.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include <cassert>
|
|
|
|
#define VENTUS_LOAD_LEGALIZATION "Ventus load instruction legalization pass"
|
|
#define DEBUG_TYPE "vlw12-legalize"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
|
|
class VentusLegalizeLoad : public MachineFunctionPass {
|
|
public:
|
|
const RISCVInstrInfo *TII;
|
|
static char ID;
|
|
const RISCVRegisterInfo *MRI;
|
|
const RISCVTargetLowering *RTI;
|
|
const MachineRegisterInfo *MR;
|
|
|
|
VentusLegalizeLoad() : MachineFunctionPass(ID) {
|
|
initializeVentusLegalizeLoadPass(*PassRegistry::getPassRegistry());
|
|
}
|
|
|
|
bool runOnMachineFunction(MachineFunction &MF) override;
|
|
|
|
StringRef getPassName() const override { return VENTUS_LOAD_LEGALIZATION; }
|
|
|
|
private:
|
|
bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
|
|
|
|
bool checkVLWDependency(MachineBasicBlock &MBB, MachineInstr &MI);
|
|
|
|
bool checkInstructionUse(MachineBasicBlock &MBB, MachineInstr &MI);
|
|
|
|
// Check whether machine instruction is local memory load instruction or not
|
|
bool isLocalMemLoadInstr(MachineInstr &MI) {
|
|
switch (MI.getOpcode()) {
|
|
case RISCV::VLWI12:
|
|
case RISCV::VLBI12:
|
|
case RISCV::VLBUI12:
|
|
case RISCV::VLHI12:
|
|
case RISCV::VLHUI12:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
unsigned getRelativePrivateMemLoadInstr(MachineInstr &MI) {
|
|
assert(isLocalMemLoadInstr(MI) && "Illegal instruction.");
|
|
switch (MI.getOpcode()) {
|
|
case RISCV::VLWI12:
|
|
return RISCV::VLW;
|
|
case RISCV::VLBI12:
|
|
return RISCV::VLB;
|
|
case RISCV::VLBUI12:
|
|
return RISCV::VLBU;
|
|
case RISCV::VLHI12:
|
|
return RISCV::VLH;
|
|
case RISCV::VLHUI12:
|
|
return RISCV::VLHU;
|
|
default:
|
|
llvm_unreachable("Unexpected instruction.");
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
bool VentusLegalizeLoad::runOnMachineFunction(MachineFunction &MF) {
|
|
bool IsChanged = false;
|
|
TII = static_cast<const RISCVInstrInfo *>(MF.getSubtarget().getInstrInfo());
|
|
MRI = MF.getSubtarget<RISCVSubtarget>().getRegisterInfo();
|
|
RTI = MF.getSubtarget<RISCVSubtarget>().getTargetLowering();
|
|
MR = &MF.getRegInfo();
|
|
for (auto &MBB : MF)
|
|
IsChanged |= runOnMachineBasicBlock(MBB);
|
|
return IsChanged;
|
|
}
|
|
|
|
bool VentusLegalizeLoad::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
|
|
bool IsMBBChanged = false;
|
|
// Right now we only legalize vlw12.v instruction, and we need to analyze its
|
|
// operand def-use chain
|
|
for (auto &MI : MBB) {
|
|
if (MI.getOpcode() == RISCV::VLW)
|
|
IsMBBChanged |= checkVLWDependency(MBB, MI);
|
|
}
|
|
return IsMBBChanged;
|
|
}
|
|
|
|
bool VentusLegalizeLoad::checkVLWDependency(MachineBasicBlock &MBB,
|
|
MachineInstr &MI) {
|
|
bool IsChanged = false;
|
|
|
|
int StoreFrameIndex = RTI->getVastartStoreFrameIndex();
|
|
MachineOperand LoadBaseOperand = MI.getOperand(1);
|
|
if (LoadBaseOperand.isFI() && LoadBaseOperand.getIndex() == StoreFrameIndex)
|
|
// Check base operand has data dependency with vastart frame or not
|
|
{
|
|
Register VastartFrameRegister = MI.getOperand(0).getReg();
|
|
auto UseList = MR->use_instructions(VastartFrameRegister);
|
|
for (auto &Use : UseList) {
|
|
// Other operation on vastart frame register
|
|
IsChanged |= checkInstructionUse(MBB, Use);
|
|
}
|
|
}
|
|
|
|
return IsChanged;
|
|
}
|
|
|
|
bool VentusLegalizeLoad::checkInstructionUse(MachineBasicBlock &MBB, MachineInstr &MI) {
|
|
bool IsChanged = false;
|
|
if (isLocalMemLoadInstr(MI)) {
|
|
// Here need to change vlw12 to vlw
|
|
LLVM_DEBUG(dbgs() << "Instruction to be changed: \n");
|
|
LLVM_DEBUG(MI.dump());
|
|
MI.setDesc(TII->get(getRelativePrivateMemLoadInstr(MI)));
|
|
LLVM_DEBUG(dbgs() << "Instruction after changed: \n");
|
|
LLVM_DEBUG(MI.dump());
|
|
auto UseList = MR->use_instructions(MI.getOperand(0).getReg());
|
|
// Recursive check
|
|
// vlw.v v0, -28(v8) // vararg start frame
|
|
// vlw.v v0, 0(v0) // should be checked too
|
|
for (auto &Use : UseList) {
|
|
checkInstructionUse(MBB, Use);
|
|
}
|
|
return IsChanged = true;
|
|
}
|
|
if (MI.getOpcode() == RISCV::VSW)
|
|
return IsChanged;
|
|
for (auto &Use : MR->use_instructions(MI.getOperand(0).getReg())) {
|
|
IsChanged |= checkInstructionUse(MBB, Use);
|
|
}
|
|
return IsChanged;
|
|
}
|
|
|
|
char VentusLegalizeLoad::ID = 0;
|
|
|
|
} // end of anonymous namespace
|
|
|
|
INITIALIZE_PASS(VentusLegalizeLoad, "Ventus load instruction legalization",
|
|
VENTUS_LOAD_LEGALIZATION, false, false)
|
|
|
|
namespace llvm {
|
|
FunctionPass *createVentusLegalizeLoadPass() {
|
|
return new VentusLegalizeLoad();
|
|
}
|
|
} // end of namespace llvm
|