Skip to content

Commit

Permalink
Func: implement Chapter8_2
Browse files Browse the repository at this point in the history
  • Loading branch information
msyksphinz committed Dec 26, 2018
1 parent 37c3879 commit 2c62c96
Show file tree
Hide file tree
Showing 19 changed files with 830 additions and 3 deletions.
3 changes: 3 additions & 0 deletions lib/Target/Cpu0/CMakeLists.txt
Expand Up @@ -24,7 +24,10 @@ add_llvm_target(Cpu0CodeGen
Cpu0AnalyzeImmediate.cpp
Cpu0AsmPrinter.cpp
Cpu0MCInstLower.cpp
Cpu0DelaySlotFiller.cpp
Cpu0DelUselessJMP.cpp
Cpu0FrameLowering.cpp
Cpu0LongBranch.cpp
Cpu0InstrInfo.cpp
Cpu0ISelLowering.cpp
Cpu0MachineFunction.cpp
Expand Down
4 changes: 4 additions & 0 deletions lib/Target/Cpu0/Cpu0.h
Expand Up @@ -23,6 +23,10 @@ namespace llvm {
class Cpu0TargetMachine;
class FunctionPass;

FunctionPass *createCpu0DelaySlotFillerPass(Cpu0TargetMachine &TM);
FunctionPass *createCpu0DelJmpPass(Cpu0TargetMachine &TM);
FunctionPass *createCpu0LongBranchPass(Cpu0TargetMachine &TM);

} // end namespace llvm;

#endif
Expand Down
7 changes: 6 additions & 1 deletion lib/Target/Cpu0/Cpu0AsmPrinter.cpp
Expand Up @@ -67,7 +67,7 @@ void Cpu0AsmPrinter::EmitInstruction(const MachineInstr *MI) {

do {

if (I->isPseudo())
if (I->isPseudo() && !isLongBranchPseudo(I->getOpcode()))
llvm_unreachable("Pseudo opcode found in EmitInstruction()");

MCInst TmpInst0;
Expand Down Expand Up @@ -268,6 +268,11 @@ void Cpu0AsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
OS << "PrintDebugValueComment()";
}

bool Cpu0AsmPrinter::isLongBranchPseudo(int Opcode) const {
return (Opcode == Cpu0::LONG_BRANCH_LUi
|| Opcode == Cpu0::LONG_BRANCH_ADDiu);
}

// Force static initialization.
extern "C" void LLVMInitializeCpu0AsmPrinter() {
RegisterAsmPrinter<Cpu0AsmPrinter> X(TheCpu0Target);
Expand Down
2 changes: 2 additions & 0 deletions lib/Target/Cpu0/Cpu0AsmPrinter.h
Expand Up @@ -41,6 +41,8 @@ class LLVM_LIBRARY_VISIBILITY Cpu0AsmPrinter : public AsmPrinter {
// lowerOperand - Convert a MachineOperand into the equivalent MCOperand.
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp);

bool isLongBranchPseudo(int Opcode) const;

public:

const Cpu0Subtarget *Subtarget;
Expand Down
77 changes: 77 additions & 0 deletions lib/Target/Cpu0/Cpu0CondMov.td
@@ -0,0 +1,77 @@
//===-- Cpu0CondMov.td - Describe Cpu0 Conditional Moves --*- tablegen -*--===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the Conditional Moves implementation.
//
//===----------------------------------------------------------------------===//

// Conditional moves:
// These instructions are expanded in
// Cpu0ISelLowering::EmitInstrWithCustomInserter if target does not have
// conditional move instructions.
// cond:int, data:int
class CondMovIntInt<RegisterClass CRC, RegisterClass DRC, bits<8> op,
string instr_asm> :
FA<op, (outs DRC:$ra), (ins DRC:$rb, CRC:$rc, DRC:$F),
!strconcat(instr_asm, "\t$ra, $rb, $rc"), [], IIAlu> {
let shamt = 0;
let Constraints = "$F = $ra";
}

// select patterns
multiclass MovzPats0Slt<RegisterClass CRC, RegisterClass DRC,
Instruction MOVZInst, Instruction SLTOp,
Instruction SLTuOp, Instruction SLTiOp,
Instruction SLTiuOp> {
def : Pat<(select (i32 (setge CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F),
(MOVZInst DRC:$T, (SLTOp CRC:$lhs, CRC:$rhs), DRC:$F)>;
def : Pat<(select (i32 (setuge CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F),
(MOVZInst DRC:$T, (SLTuOp CRC:$lhs, CRC:$rhs), DRC:$F)>;
def : Pat<(select (i32 (setge CRC:$lhs, immSExt16:$rhs)), DRC:$T, DRC:$F),
(MOVZInst DRC:$T, (SLTiOp CRC:$lhs, immSExt16:$rhs), DRC:$F)>;
def : Pat<(select (i32 (setuge CRC:$lh, immSExt16:$rh)), DRC:$T, DRC:$F),
(MOVZInst DRC:$T, (SLTiuOp CRC:$lh, immSExt16:$rh), DRC:$F)>;
def : Pat<(select (i32 (setle CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F),
(MOVZInst DRC:$T, (SLTOp CRC:$rhs, CRC:$lhs), DRC:$F)>;
def : Pat<(select (i32 (setule CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F),
(MOVZInst DRC:$T, (SLTuOp CRC:$rhs, CRC:$lhs), DRC:$F)>;
}

multiclass MovzPats1<RegisterClass CRC, RegisterClass DRC,
Instruction MOVZInst, Instruction XOROp> {
def : Pat<(select (i32 (seteq CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F),
(MOVZInst DRC:$T, (XOROp CRC:$lhs, CRC:$rhs), DRC:$F)>;
def : Pat<(select (i32 (seteq CRC:$lhs, 0)), DRC:$T, DRC:$F),
(MOVZInst DRC:$T, CRC:$lhs, DRC:$F)>;
}

multiclass MovnPats<RegisterClass CRC, RegisterClass DRC, Instruction MOVNInst,
Instruction XOROp> {
def : Pat<(select (i32 (setne CRC:$lhs, CRC:$rhs)), DRC:$T, DRC:$F),
(MOVNInst DRC:$T, (XOROp CRC:$lhs, CRC:$rhs), DRC:$F)>;
def : Pat<(select CRC:$cond, DRC:$T, DRC:$F),
(MOVNInst DRC:$T, CRC:$cond, DRC:$F)>;
def : Pat<(select (i32 (setne CRC:$lhs, 0)),DRC:$T, DRC:$F),
(MOVNInst DRC:$T, CRC:$lhs, DRC:$F)>;
}

// Instantiation of instructions.
def MOVZ_I_I : CondMovIntInt<CPURegs, CPURegs, 0x0a, "movz">;

def MOVN_I_I : CondMovIntInt<CPURegs, CPURegs, 0x0b, "movn">;

// Instantiation of conditional move patterns.
let Predicates = [HasSlt] in {
defm : MovzPats0Slt<CPURegs, CPURegs, MOVZ_I_I, SLT, SLTu, SLTi, SLTiu>;
}

defm : MovzPats1<CPURegs, CPURegs, MOVZ_I_I, XOR>;

defm : MovnPats<CPURegs, CPURegs, MOVN_I_I, XOR>;

96 changes: 96 additions & 0 deletions lib/Target/Cpu0/Cpu0DelUselessJMP.cpp
@@ -0,0 +1,96 @@
//===-- Cpu0DelUselessJMP.cpp - Cpu0 DelJmp -------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Simple pass to fills delay slots with useful instructions.
//
//===----------------------------------------------------------------------===//

#include "Cpu0.h"

#include "Cpu0TargetMachine.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"

using namespace llvm;

#define DEBUG_TYPE "del-jmp"

STATISTIC(NumDelJmp, "Number of useless jmp deleted");

static cl::opt<bool> EnableDelJmp(
"enable-cpu0-del-useless-jmp",
cl::init(true),
cl::desc("Delete useless jmp instructions: jmp 0."),
cl::Hidden);

namespace {
struct DelJmp : public MachineFunctionPass {
static char ID;
DelJmp(TargetMachine &tm)
: MachineFunctionPass(ID) { }

virtual StringRef getPassName() const {
return "Cpu0 Del Useless jmp";
}

bool runOnMachineBasicBlock(MachineBasicBlock &MBB, MachineBasicBlock &MBBN);
bool runOnMachineFunction(MachineFunction &F) {
bool Changed = false;
if (EnableDelJmp) {
MachineFunction::iterator FJ = F.begin();
if (FJ != F.end())
FJ++;
if (FJ == F.end())
return Changed;
for (MachineFunction::iterator FI = F.begin(), FE = F.end();
FJ != FE; ++FI, ++FJ)
// In STL style, F.end() is the dummy BasicBlock() like '\0' in
// C string.
// FJ is the next BasicBlock of FI; When FI range from F.begin() to
// the PreviousBasicBlock of F.end() call runOnMachineBasicBlock().
Changed |= runOnMachineBasicBlock(*FI, *FJ);
}
return Changed;
}

};
char DelJmp::ID = 0;
} // end of anonymous namespace

bool DelJmp::
runOnMachineBasicBlock(MachineBasicBlock &MBB, MachineBasicBlock &MBBN) {
bool Changed = false;

MachineBasicBlock::iterator I = MBB.end();
if (I != MBB.begin())
I--; // set I to the last instruction
else
return Changed;

if (I->getOpcode() == Cpu0::JMP && I->getOperand(0).getMBB() == &MBBN) {
// I is the instruction of "jmp #offset=0", as follows,
// jmp $BB0_3
// $BB0_3:
// ld $4, 28($sp)
++NumDelJmp;
MBB.erase(I); // delete the "JMP 0" instruction
Changed = true; // Notify LLVM kernel Changed
}
return Changed;

}

/// createCpu0DelJmpPass - Returns a pass that DelJmp in Cpu0 MachineFunctions
FunctionPass *llvm::createCpu0DelJmpPass(Cpu0TargetMachine &tm) {
return new DelJmp(tm);
}
96 changes: 96 additions & 0 deletions lib/Target/Cpu0/Cpu0DelaySlotFiller.cpp
@@ -0,0 +1,96 @@
//===-- Cpu0DelaySlotFiller.cpp - Cpu0 Delay Slot Filler ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Simple pass to fill delay slots with useful instructions.
//
//===----------------------------------------------------------------------===//

#include "Cpu0.h"

#include "Cpu0InstrInfo.h"
#include "Cpu0TargetMachine.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"

using namespace llvm;

#define DEBUG_TYPE "delay-slot-filler"

STATISTIC(FilledSlots, "Number of delay slots filled");

namespace {
typedef MachineBasicBlock::iterator Iter;
typedef MachineBasicBlock::reverse_iterator ReverseIter;

class Filler : public MachineFunctionPass {
public:
Filler(TargetMachine &tm)
: MachineFunctionPass(ID) { }

StringRef getPassName() const override {
return "Cpu0 Delay Slot Filler";
}

bool runOnMachineFunction(MachineFunction &F) override {
bool Changed = false;
for (MachineFunction::iterator FI = F.begin(), FE = F.end();
FI != FE; ++FI)
Changed |= runOnMachineBasicBlock(*FI);
return Changed;
}
private:
bool runOnMachineBasicBlock(MachineBasicBlock &MBB);

static char ID;
};
char Filler::ID = 0;
} // end of anonymous namespace

static bool hasUnoccupiedSlot(const MachineInstr *MI) {
return MI->hasDelaySlot() && !MI->isBundledWithSucc();
}

/// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
/// We assume there is only one delay slot per delayed instruction.
bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
bool Changed = false;
const Cpu0Subtarget &STI = MBB.getParent()->getSubtarget<Cpu0Subtarget>();
const Cpu0InstrInfo *TII = STI.getInstrInfo();

for (Iter I = MBB.begin(); I != MBB.end(); ++I) {
if (!hasUnoccupiedSlot(&*I))
continue;

++FilledSlots;
Changed = true;

// Bundle the NOP to the instruction with the delay slot.
BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Cpu0::NOP));
MIBundleBuilder(MBB, I, std::next(I, 2));
}

return Changed;
}

/// createCpu0DelaySlotFillerPass - Returns a pass that fills in delay
/// slots in Cpu0 MachineFunctions
FunctionPass *llvm::createCpu0DelaySlotFillerPass(Cpu0TargetMachine &tm) {
return new Filler(tm);
}
10 changes: 10 additions & 0 deletions lib/Target/Cpu0/Cpu0ISelLowering.cpp
Expand Up @@ -114,6 +114,7 @@ Cpu0TargetLowering::Cpu0TargetLowering(const Cpu0TargetMachine &TM,
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
setOperationAction(ISD::SELECT, MVT::i32, Custom);
setOperationAction(ISD::BRCOND, MVT::Other, Custom);

// Handle i64 shl
Expand All @@ -129,6 +130,8 @@ Cpu0TargetLowering::Cpu0TargetLowering(const Cpu0TargetMachine &TM,
// Operations not directly supported by Cpu0.
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
setOperationAction(ISD::BR_CC, MVT::i32, Expand);
setOperationAction(ISD::SELECT_CC, MVT::i32, Expand);
setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
setOperationAction(ISD::CTPOP, MVT::i32, Expand);
setOperationAction(ISD::CTTZ, MVT::i32, Expand);
setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand);
Expand Down Expand Up @@ -222,6 +225,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const
case ISD::GlobalAddress: return lowerGlobalAddress(Op, DAG);
case ISD::BlockAddress: return lowerBlockAddress(Op, DAG);
case ISD::JumpTable: return lowerJumpTable(Op, DAG);
case ISD::SELECT: return lowerSELECT(Op, DAG);
}
return SDValue();
}
Expand All @@ -239,6 +243,12 @@ lowerBRCOND(SDValue Op, SelectionDAG &DAG) const
return Op;
}

SDValue Cpu0TargetLowering::
lowerSELECT(SDValue Op, SelectionDAG &DAG) const
{
return Op;
}

SDValue Cpu0TargetLowering::lowerGlobalAddress(SDValue Op,
SelectionDAG &DAG) const {
//@lowerGlobalAddress }
Expand Down
1 change: 1 addition & 0 deletions lib/Target/Cpu0/Cpu0ISelLowering.h
Expand Up @@ -258,6 +258,7 @@ namespace llvm {
SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const;

SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG& DAG) const;
SDValue lowerShiftRightParts(SDValue Op, SelectionDAG& DAG,
Expand Down
2 changes: 2 additions & 0 deletions lib/Target/Cpu0/Cpu0InstrInfo.h
Expand Up @@ -45,6 +45,8 @@ class Cpu0InstrInfo : public Cpu0GenInstrInfo {
/// Return the number of bytes of code the specified instruction may be.
unsigned GetInstSizeInBytes(const MachineInstr &MI) const;

virtual unsigned getOppositeBranchOpc(unsigned Opc) const = 0;

void storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
unsigned SrcReg, bool isKill, int FrameIndex,
Expand Down

0 comments on commit 2c62c96

Please sign in to comment.