Skip to content

Commit 5baef63

Browse files
committed
[RISCV] Initial infrastructure for code generation of the RISC-V V-extension
The companion RFC (http://lists.llvm.org/pipermail/llvm-dev/2020-October/145850.html) gives lots of details on the overall strategy, but we summarize it here: LLVM IR involving vector types is going to be selected using pseudo instructions (only MachineInstr). These pseudo instructions contain dummy operands to represent the vector type being operated and the vector length for the operation. These two dummy operands, as set by instruction selection, will be used by the custom inserter to prepend every operation with an appropriate vsetvli instruction that ensures the vector architecture is properly configured for the operation. Not in this patch: later passes will remove the redundant vsetvli instructions. Register classes of tuples of vector registers are used to represent vector register groups (LMUL > 1). Those pseudos are eventually lowered into the actual instructions when emitting the MCInsts. About the patch: Because there is a bit of initial infrastructure required, this is the minimal patch that allows us to select instructions for 3 LLVM IR instructions: load, add and store vectors of integers. LLVM IR operations have "whole-vector" semantics (as in they generate values for all the elements). Later patches will extend the information represented in TableGen. Authored-by: Roger Ferrer Ibanez <[email protected]> Co-Authored-by: Evandro Menezes <[email protected]> Co-Authored-by: Craig Topper <[email protected]> Differential Revision: https://reviews.llvm.org/D89449
1 parent e460654 commit 5baef63

16 files changed

+1308
-38
lines changed

llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class RISCVExpandPseudo : public MachineFunctionPass {
5959
bool expandLoadTLSGDAddress(MachineBasicBlock &MBB,
6060
MachineBasicBlock::iterator MBBI,
6161
MachineBasicBlock::iterator &NextMBBI);
62+
bool expandVSetVL(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI);
6263
};
6364

6465
char RISCVExpandPseudo::ID = 0;
@@ -99,6 +100,8 @@ bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,
99100
return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI);
100101
case RISCV::PseudoLA_TLS_GD:
101102
return expandLoadTLSGDAddress(MBB, MBBI, NextMBBI);
103+
case RISCV::PseudoVSETVLI:
104+
return expandVSetVL(MBB, MBBI);
102105
}
103106

104107
return false;
@@ -188,6 +191,28 @@ bool RISCVExpandPseudo::expandLoadTLSGDAddress(
188191
RISCV::ADDI);
189192
}
190193

194+
bool RISCVExpandPseudo::expandVSetVL(MachineBasicBlock &MBB,
195+
MachineBasicBlock::iterator MBBI) {
196+
assert(MBBI->getNumOperands() == 5 && "Unexpected instruction format");
197+
198+
DebugLoc DL = MBBI->getDebugLoc();
199+
200+
assert(MBBI->getOpcode() == RISCV::PseudoVSETVLI &&
201+
"Unexpected pseudo instruction");
202+
const MCInstrDesc &Desc = TII->get(RISCV::VSETVLI);
203+
assert(Desc.getNumOperands() == 3 && "Unexpected instruction format");
204+
205+
Register DstReg = MBBI->getOperand(0).getReg();
206+
bool DstIsDead = MBBI->getOperand(0).isDead();
207+
BuildMI(MBB, MBBI, DL, Desc)
208+
.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
209+
.add(MBBI->getOperand(1)) // VL
210+
.add(MBBI->getOperand(2)); // VType
211+
212+
MBBI->eraseFromParent(); // The pseudo instruction is gone now.
213+
return true;
214+
}
215+
191216
} // end of anonymous namespace
192217

193218
INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,53 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
8989
if (Subtarget.hasStdExtD())
9090
addRegisterClass(MVT::f64, &RISCV::FPR64RegClass);
9191

92+
if (Subtarget.hasStdExtV()) {
93+
addRegisterClass(RISCVVMVTs::vbool64_t, &RISCV::VRRegClass);
94+
addRegisterClass(RISCVVMVTs::vbool32_t, &RISCV::VRRegClass);
95+
addRegisterClass(RISCVVMVTs::vbool16_t, &RISCV::VRRegClass);
96+
addRegisterClass(RISCVVMVTs::vbool8_t, &RISCV::VRRegClass);
97+
addRegisterClass(RISCVVMVTs::vbool4_t, &RISCV::VRRegClass);
98+
addRegisterClass(RISCVVMVTs::vbool2_t, &RISCV::VRRegClass);
99+
addRegisterClass(RISCVVMVTs::vbool1_t, &RISCV::VRRegClass);
100+
101+
addRegisterClass(RISCVVMVTs::vint8mf8_t, &RISCV::VRRegClass);
102+
addRegisterClass(RISCVVMVTs::vint8mf4_t, &RISCV::VRRegClass);
103+
addRegisterClass(RISCVVMVTs::vint8mf2_t, &RISCV::VRRegClass);
104+
addRegisterClass(RISCVVMVTs::vint8m1_t, &RISCV::VRRegClass);
105+
addRegisterClass(RISCVVMVTs::vint8m2_t, &RISCV::VRM2RegClass);
106+
addRegisterClass(RISCVVMVTs::vint8m4_t, &RISCV::VRM4RegClass);
107+
addRegisterClass(RISCVVMVTs::vint8m8_t, &RISCV::VRM8RegClass);
108+
109+
addRegisterClass(RISCVVMVTs::vint16mf4_t, &RISCV::VRRegClass);
110+
addRegisterClass(RISCVVMVTs::vint16mf2_t, &RISCV::VRRegClass);
111+
addRegisterClass(RISCVVMVTs::vint16m1_t, &RISCV::VRRegClass);
112+
addRegisterClass(RISCVVMVTs::vint16m2_t, &RISCV::VRM2RegClass);
113+
addRegisterClass(RISCVVMVTs::vint16m4_t, &RISCV::VRM4RegClass);
114+
addRegisterClass(RISCVVMVTs::vint16m8_t, &RISCV::VRM8RegClass);
115+
116+
addRegisterClass(RISCVVMVTs::vint32mf2_t, &RISCV::VRRegClass);
117+
addRegisterClass(RISCVVMVTs::vint32m1_t, &RISCV::VRRegClass);
118+
addRegisterClass(RISCVVMVTs::vint32m2_t, &RISCV::VRM2RegClass);
119+
addRegisterClass(RISCVVMVTs::vint32m4_t, &RISCV::VRM4RegClass);
120+
addRegisterClass(RISCVVMVTs::vint32m8_t, &RISCV::VRM8RegClass);
121+
122+
addRegisterClass(RISCVVMVTs::vint64m1_t, &RISCV::VRRegClass);
123+
addRegisterClass(RISCVVMVTs::vint64m2_t, &RISCV::VRM2RegClass);
124+
addRegisterClass(RISCVVMVTs::vint64m4_t, &RISCV::VRM4RegClass);
125+
addRegisterClass(RISCVVMVTs::vint64m8_t, &RISCV::VRM8RegClass);
126+
127+
addRegisterClass(RISCVVMVTs::vfloat32mf2_t, &RISCV::VRRegClass);
128+
addRegisterClass(RISCVVMVTs::vfloat32m1_t, &RISCV::VRRegClass);
129+
addRegisterClass(RISCVVMVTs::vfloat32m2_t, &RISCV::VRM2RegClass);
130+
addRegisterClass(RISCVVMVTs::vfloat32m4_t, &RISCV::VRM4RegClass);
131+
addRegisterClass(RISCVVMVTs::vfloat32m8_t, &RISCV::VRM8RegClass);
132+
133+
addRegisterClass(RISCVVMVTs::vfloat64m1_t, &RISCV::VRRegClass);
134+
addRegisterClass(RISCVVMVTs::vfloat64m2_t, &RISCV::VRM2RegClass);
135+
addRegisterClass(RISCVVMVTs::vfloat64m4_t, &RISCV::VRM4RegClass);
136+
addRegisterClass(RISCVVMVTs::vfloat64m8_t, &RISCV::VRM8RegClass);
137+
}
138+
92139
// Compute derived properties from the register classes.
93140
computeRegisterProperties(STI.getRegisterInfo());
94141

@@ -284,6 +331,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
284331

285332
setBooleanContents(ZeroOrOneBooleanContent);
286333

334+
if (Subtarget.hasStdExtV())
335+
setBooleanVectorContents(ZeroOrOneBooleanContent);
336+
287337
// Function alignments.
288338
const Align FunctionAlignment(Subtarget.hasStdExtC() ? 2 : 4);
289339
setMinFunctionAlignment(FunctionAlignment);
@@ -1856,9 +1906,95 @@ static MachineBasicBlock *emitSelectPseudo(MachineInstr &MI,
18561906
return TailMBB;
18571907
}
18581908

1909+
static MachineBasicBlock *addVSetVL(MachineInstr &MI, MachineBasicBlock *BB,
1910+
int VLIndex, unsigned SEWIndex,
1911+
unsigned VLMul) {
1912+
MachineFunction &MF = *BB->getParent();
1913+
DebugLoc DL = MI.getDebugLoc();
1914+
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
1915+
1916+
unsigned SEW = MI.getOperand(SEWIndex).getImm();
1917+
RISCVVLengthMultiplier::LengthMultiplier Multiplier;
1918+
1919+
switch (VLMul) {
1920+
default:
1921+
llvm_unreachable("Unexpected LMUL for instruction");
1922+
case 0:
1923+
case 1:
1924+
case 2:
1925+
case 3:
1926+
case 5:
1927+
case 6:
1928+
case 7:
1929+
Multiplier = static_cast<RISCVVLengthMultiplier::LengthMultiplier>(VLMul);
1930+
break;
1931+
}
1932+
1933+
RISCVVStandardElementWidth::StandardElementWidth ElementWidth;
1934+
switch (SEW) {
1935+
default:
1936+
llvm_unreachable("Unexpected SEW for instruction");
1937+
case 8:
1938+
ElementWidth = RISCVVStandardElementWidth::ElementWidth8;
1939+
break;
1940+
case 16:
1941+
ElementWidth = RISCVVStandardElementWidth::ElementWidth16;
1942+
break;
1943+
case 32:
1944+
ElementWidth = RISCVVStandardElementWidth::ElementWidth32;
1945+
break;
1946+
case 64:
1947+
ElementWidth = RISCVVStandardElementWidth::ElementWidth64;
1948+
break;
1949+
}
1950+
1951+
MachineRegisterInfo &MRI = MF.getRegInfo();
1952+
1953+
// VL and VTYPE are alive here.
1954+
MachineInstrBuilder MIB = BuildMI(*BB, MI, DL, TII.get(RISCV::PseudoVSETVLI));
1955+
1956+
if (VLIndex >= 0) {
1957+
// Set VL (rs1 != X0).
1958+
unsigned DestReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
1959+
MIB.addReg(DestReg, RegState::Define | RegState::Dead)
1960+
.addReg(MI.getOperand(VLIndex).getReg());
1961+
} else
1962+
// With no VL operator in the pseudo, do not modify VL (rd = X0, rs1 = X0).
1963+
MIB.addReg(RISCV::X0, RegState::Dead)
1964+
.addReg(RISCV::X0, RegState::Kill);
1965+
1966+
// For simplicity we reuse the vtype representation here.
1967+
// Bits | Name | Description
1968+
// -----+------------+------------------------------------------------
1969+
// 5 | vlmul[2] | Fractional lmul?
1970+
// 4:2 | vsew[2:0] | Standard element width (SEW) setting
1971+
// 1:0 | vlmul[1:0] | Vector register group multiplier (LMUL) setting
1972+
MIB.addImm(((Multiplier & 0x4) << 3) | ((ElementWidth & 0x3) << 2) |
1973+
(Multiplier & 0x3));
1974+
1975+
// Remove (now) redundant operands from pseudo
1976+
MI.getOperand(SEWIndex).setImm(-1);
1977+
if (VLIndex >= 0) {
1978+
MI.getOperand(VLIndex).setReg(RISCV::NoRegister);
1979+
MI.getOperand(VLIndex).setIsKill(false);
1980+
}
1981+
1982+
return BB;
1983+
}
1984+
18591985
MachineBasicBlock *
18601986
RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
18611987
MachineBasicBlock *BB) const {
1988+
1989+
if (const RISCVVPseudosTable::PseudoInfo *RVV =
1990+
RISCVVPseudosTable::getPseudoInfo(MI.getOpcode())) {
1991+
int VLIndex = RVV->getVLIndex();
1992+
int SEWIndex = RVV->getSEWIndex();
1993+
1994+
assert(SEWIndex >= 0 && "SEWIndex must be >= 0");
1995+
return addVSetVL(MI, BB, VLIndex, SEWIndex, RVV->VLMul);
1996+
}
1997+
18621998
switch (MI.getOpcode()) {
18631999
default:
18642000
llvm_unreachable("Unexpected instr type to insert");

llvm/lib/Target/RISCV/RISCVInstrInfoV.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,3 +1127,5 @@ let Predicates = [HasStdExtZvamo, HasStdExtA, IsRV64] in {
11271127
defm VAMOMINUEI64 : VAMO<AMOOPVamoMinu, LSWidth64, "vamominuei64.v">;
11281128
defm VAMOMAXUEI64 : VAMO<AMOOPVamoMaxu, LSWidth64, "vamomaxuei64.v">;
11291129
} // Predicates = [HasStdExtZvamo, HasStdExtA, IsRV64]
1130+
1131+
include "RISCVInstrInfoVPseudos.td"

0 commit comments

Comments
 (0)