Skip to content

Commit 69c8d12

Browse files
committed
[RISCV] Add intrinsics for vsetvli instruction
This patch adds two IR intrinsics for vsetvli instruction. One to set the vector length to a user specified value and one to set it to vlmax. The vlmax uses the X0 source register encoding. Clang builtins will follow in a separate patch Differential Revision: https://reviews.llvm.org/D92973
1 parent 9c978dd commit 69c8d12

File tree

6 files changed

+168
-1
lines changed

6 files changed

+168
-1
lines changed

llvm/include/llvm/IR/IntrinsicsRISCV.td

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,21 @@ class RISCVVIntrinsic {
7979
}
8080

8181
let TargetPrefix = "riscv" in {
82+
// We use anyint here but we only support XLen.
83+
def int_riscv_vsetvli : Intrinsic<[llvm_anyint_ty],
84+
/* AVL */ [LLVMMatchType<0>,
85+
/* VSEW */ LLVMMatchType<0>,
86+
/* VLMUL */ LLVMMatchType<0>],
87+
[IntrNoMem, IntrHasSideEffects,
88+
ImmArg<ArgIndex<1>>,
89+
ImmArg<ArgIndex<2>>]>;
90+
def int_riscv_vsetvlimax : Intrinsic<[llvm_anyint_ty],
91+
/* VSEW */ [LLVMMatchType<0>,
92+
/* VLMUL */ LLVMMatchType<0>],
93+
[IntrNoMem, IntrHasSideEffects,
94+
ImmArg<ArgIndex<0>>,
95+
ImmArg<ArgIndex<1>>]>;
96+
8297
// For unit stride load
8398
// Input: (pointer, vl)
8499
class RISCVUSLoad

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "MCTargetDesc/RISCVMCTargetDesc.h"
1515
#include "Utils/RISCVMatInt.h"
1616
#include "llvm/CodeGen/MachineFrameInfo.h"
17+
#include "llvm/IR/IntrinsicsRISCV.h"
1718
#include "llvm/Support/Alignment.h"
1819
#include "llvm/Support/Debug.h"
1920
#include "llvm/Support/MathExtras.h"
@@ -141,6 +142,70 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
141142
}
142143
break;
143144
}
145+
case ISD::INTRINSIC_W_CHAIN: {
146+
unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
147+
switch (IntNo) {
148+
// By default we do not custom select any intrinsic.
149+
default:
150+
break;
151+
152+
case Intrinsic::riscv_vsetvli: {
153+
if (!Subtarget->hasStdExtV())
154+
break;
155+
156+
assert(Node->getNumOperands() == 5);
157+
158+
RISCVVSEW VSEW =
159+
static_cast<RISCVVSEW>(Node->getConstantOperandVal(3) & 0x7);
160+
RISCVVLMUL VLMul =
161+
static_cast<RISCVVLMUL>(Node->getConstantOperandVal(4) & 0x7);
162+
163+
unsigned VTypeI = RISCVVType::encodeVTYPE(
164+
VLMul, VSEW, /*TailAgnostic*/ true, /*MaskAgnostic*/ false);
165+
SDValue VTypeIOp = CurDAG->getTargetConstant(VTypeI, DL, XLenVT);
166+
167+
SDValue VLOperand = Node->getOperand(2);
168+
if (auto *C = dyn_cast<ConstantSDNode>(VLOperand)) {
169+
if (C->isNullValue()) {
170+
VLOperand = SDValue(
171+
CurDAG->getMachineNode(RISCV::ADDI, DL, XLenVT,
172+
CurDAG->getRegister(RISCV::X0, XLenVT),
173+
CurDAG->getTargetConstant(0, DL, XLenVT)),
174+
0);
175+
}
176+
}
177+
178+
ReplaceNode(Node,
179+
CurDAG->getMachineNode(RISCV::PseudoVSETVLI, DL, XLenVT,
180+
MVT::Other, VLOperand, VTypeIOp,
181+
/* Chain */ Node->getOperand(0)));
182+
return;
183+
}
184+
case Intrinsic::riscv_vsetvlimax: {
185+
if (!Subtarget->hasStdExtV())
186+
break;
187+
188+
assert(Node->getNumOperands() == 4);
189+
190+
RISCVVSEW VSEW =
191+
static_cast<RISCVVSEW>(Node->getConstantOperandVal(2) & 0x7);
192+
RISCVVLMUL VLMul =
193+
static_cast<RISCVVLMUL>(Node->getConstantOperandVal(3) & 0x7);
194+
195+
unsigned VTypeI = RISCVVType::encodeVTYPE(
196+
VLMul, VSEW, /*TailAgnostic*/ true, /*MaskAgnostic*/ false);
197+
SDValue VTypeIOp = CurDAG->getTargetConstant(VTypeI, DL, XLenVT);
198+
199+
SDValue VLOperand = CurDAG->getRegister(RISCV::X0, XLenVT);
200+
ReplaceNode(Node,
201+
CurDAG->getMachineNode(RISCV::PseudoVSETVLI, DL, XLenVT,
202+
MVT::Other, VLOperand, VTypeIOp,
203+
/* Chain */ Node->getOperand(0)));
204+
return;
205+
}
206+
}
207+
break;
208+
}
144209
}
145210

146211
// Select the default instruction.

llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ void RISCVVType::printVType(unsigned VType, raw_ostream &OS) {
109109
OS << "e" << Sew;
110110

111111
switch (VLMUL) {
112+
case RISCVVLMUL::LMUL_RESERVED:
113+
llvm_unreachable("Unexpected LMUL value!");
112114
case RISCVVLMUL::LMUL_1:
113115
case RISCVVLMUL::LMUL_2:
114116
case RISCVVLMUL::LMUL_4:

llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,8 @@ enum class RISCVVLMUL {
346346
LMUL_2,
347347
LMUL_4,
348348
LMUL_8,
349-
LMUL_F8 = 5,
349+
LMUL_RESERVED,
350+
LMUL_F8,
350351
LMUL_F4,
351352
LMUL_F2
352353
};
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc -mtriple=riscv32 -mattr=+experimental-v -verify-machineinstrs < %s | FileCheck %s
3+
4+
declare i32 @llvm.riscv.vsetvli.i32(i32, i32, i32)
5+
declare i32 @llvm.riscv.vsetvlimax.i32(i32, i32)
6+
7+
define void @test_vsetvli_e64mf8(i32 %avl) nounwind {
8+
; CHECK-LABEL: test_vsetvli_e64mf8:
9+
; CHECK: # %bb.0:
10+
; CHECK-NEXT: vsetvli a0, a0, e64,mf8,ta,mu
11+
; CHECK-NEXT: ret
12+
call i32 @llvm.riscv.vsetvli.i32(i32 %avl, i32 3, i32 5)
13+
ret void
14+
}
15+
16+
define void @test_vsetvli_e8mf2_zero_avl() nounwind {
17+
; CHECK-LABEL: test_vsetvli_e8mf2_zero_avl:
18+
; CHECK: # %bb.0:
19+
; CHECK-NEXT: mv a0, zero
20+
; CHECK-NEXT: vsetvli a0, a0, e8,mf2,ta,mu
21+
; CHECK-NEXT: ret
22+
call i32 @llvm.riscv.vsetvli.i32(i32 0, i32 0, i32 7)
23+
ret void
24+
}
25+
26+
define void @test_vsetvlimax_e64m8() nounwind {
27+
; CHECK-LABEL: test_vsetvlimax_e64m8:
28+
; CHECK: # %bb.0:
29+
; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu
30+
; CHECK-NEXT: ret
31+
call i32 @llvm.riscv.vsetvlimax.i32(i32 3, i32 3)
32+
ret void
33+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc -mtriple=riscv64 -mattr=+experimental-v -verify-machineinstrs < %s | FileCheck %s
3+
4+
declare i64 @llvm.riscv.vsetvli.i64(i64, i64, i64)
5+
declare i64 @llvm.riscv.vsetvlimax.i64(i64, i64)
6+
7+
define void @test_vsetvli_e8m1(i64 %avl) nounwind {
8+
; CHECK-LABEL: test_vsetvli_e8m1:
9+
; CHECK: # %bb.0:
10+
; CHECK-NEXT: vsetvli a0, a0, e8,m1,ta,mu
11+
; CHECK-NEXT: ret
12+
call i64 @llvm.riscv.vsetvli.i64(i64 %avl, i64 0, i64 0)
13+
ret void
14+
}
15+
16+
define void @test_vsetvli_e16mf4(i64 %avl) nounwind {
17+
; CHECK-LABEL: test_vsetvli_e16mf4:
18+
; CHECK: # %bb.0:
19+
; CHECK-NEXT: vsetvli a0, a0, e16,mf4,ta,mu
20+
; CHECK-NEXT: ret
21+
call i64 @llvm.riscv.vsetvli.i64(i64 %avl, i64 1, i64 6)
22+
ret void
23+
}
24+
25+
define void @test_vsetvli_e32mf8_zero_avl() nounwind {
26+
; CHECK-LABEL: test_vsetvli_e32mf8_zero_avl:
27+
; CHECK: # %bb.0:
28+
; CHECK-NEXT: mv a0, zero
29+
; CHECK-NEXT: vsetvli a0, a0, e16,mf4,ta,mu
30+
; CHECK-NEXT: ret
31+
call i64 @llvm.riscv.vsetvli.i64(i64 0, i64 1, i64 6)
32+
ret void
33+
}
34+
35+
define void @test_vsetvlimax_e32m2() nounwind {
36+
; CHECK-LABEL: test_vsetvlimax_e32m2:
37+
; CHECK: # %bb.0:
38+
; CHECK-NEXT: vsetvli a0, zero, e32,m2,ta,mu
39+
; CHECK-NEXT: ret
40+
call i64 @llvm.riscv.vsetvlimax.i64(i64 2, i64 1)
41+
ret void
42+
}
43+
44+
define void @test_vsetvlimax_e64m4() nounwind {
45+
; CHECK-LABEL: test_vsetvlimax_e64m4:
46+
; CHECK: # %bb.0:
47+
; CHECK-NEXT: vsetvli a0, zero, e64,m4,ta,mu
48+
; CHECK-NEXT: ret
49+
call i64 @llvm.riscv.vsetvlimax.i64(i64 3, i64 2)
50+
ret void
51+
}

0 commit comments

Comments
 (0)