Skip to content

Commit c2ec455

Browse files
committed
[LoongArch] Add intrinsics for ibar, break and syscall
Diagnostics for intrinsic input parameters have also been added. Differential Revision: https://reviews.llvm.org/D138094
1 parent fd6d660 commit c2ec455

File tree

13 files changed

+264
-35
lines changed

13 files changed

+264
-35
lines changed

clang/include/clang/Basic/BuiltinsLoongArch.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
// TODO: Support more builtins.
1919
// TODO: Added feature constraints.
2020
TARGET_BUILTIN(__builtin_loongarch_dbar, "vIUi", "nc", "")
21+
TARGET_BUILTIN(__builtin_loongarch_ibar, "vIUi", "nc", "")
22+
TARGET_BUILTIN(__builtin_loongarch_break, "vIUi", "nc", "")
23+
TARGET_BUILTIN(__builtin_loongarch_syscall, "vIUi", "nc", "")
2124

2225
TARGET_BUILTIN(__builtin_loongarch_crc_w_d_w, "iLii", "nc", "64bit")
2326

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19663,6 +19663,15 @@ Value *CodeGenFunction::EmitLoongArchBuiltinExpr(unsigned BuiltinID,
1966319663
case LoongArch::BI__builtin_loongarch_crc_w_d_w:
1966419664
ID = Intrinsic::loongarch_crc_w_d_w;
1966519665
break;
19666+
case LoongArch::BI__builtin_loongarch_break:
19667+
ID = Intrinsic::loongarch_break;
19668+
break;
19669+
case LoongArch::BI__builtin_loongarch_ibar:
19670+
ID = Intrinsic::loongarch_ibar;
19671+
break;
19672+
case LoongArch::BI__builtin_loongarch_syscall:
19673+
ID = Intrinsic::loongarch_syscall;
19674+
break;
1966619675
// TODO: Support more Intrinsics.
1966719676
}
1966819677

clang/lib/Headers/larchintrin.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,14 @@ extern __inline int
2222
}
2323
#endif
2424

25+
#define __break(/*ui15*/ _1) __builtin_loongarch_break((_1))
26+
2527
#define __dbar(/*ui15*/ _1) __builtin_loongarch_dbar((_1))
2628

29+
#define __ibar(/*ui15*/ _1) __builtin_loongarch_ibar((_1))
30+
31+
#define __syscall(/*ui15*/ _1) __builtin_loongarch_syscall((_1))
32+
2733
#ifdef __cplusplus
2834
}
2935
#endif

clang/lib/Sema/SemaChecking.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3710,7 +3710,10 @@ bool Sema::CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI,
37103710
diag::err_loongarch_builtin_requires_la64)
37113711
<< TheCall->getSourceRange();
37123712
break;
3713+
case LoongArch::BI__builtin_loongarch_break:
37133714
case LoongArch::BI__builtin_loongarch_dbar:
3715+
case LoongArch::BI__builtin_loongarch_ibar:
3716+
case LoongArch::BI__builtin_loongarch_syscall:
37143717
// Check if immediate is in [0, 32767].
37153718
return SemaBuiltinConstantArgRange(TheCall, 0, 0, 32767);
37163719
}

clang/test/CodeGen/LoongArch/intrinsic-error.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,26 @@ int crc_w_d_w(long int a, int b) {
77
return __builtin_loongarch_crc_w_d_w(a, b); // expected-error {{this builtin requires target: loongarch64}}
88
}
99

10-
void dbar_out_of_hi_range() {
11-
return __builtin_loongarch_dbar(32768); // expected-error {{argument value 32768 is outside the valid range [0, 32767]}}
10+
void dbar(int a) {
11+
__builtin_loongarch_dbar(32768); // expected-error {{argument value 32768 is outside the valid range [0, 32767]}}
12+
__builtin_loongarch_dbar(-1); // expected-error {{argument value 4294967295 is outside the valid range [0, 32767]}}
13+
__builtin_loongarch_dbar(a); // expected-error {{argument to '__builtin_loongarch_dbar' must be a constant integer}}
1214
}
1315

14-
void dbar_out_of_lo_range() {
15-
return __builtin_loongarch_dbar(-1); // expected-error {{argument value 4294967295 is outside the valid range [0, 32767]}}
16+
void ibar(int a) {
17+
__builtin_loongarch_ibar(32769); // expected-error {{argument value 32769 is outside the valid range [0, 32767]}}
18+
__builtin_loongarch_ibar(-1); // expected-error {{argument value 4294967295 is outside the valid range [0, 32767]}}
19+
__builtin_loongarch_ibar(a); // expected-error {{argument to '__builtin_loongarch_ibar' must be a constant integer}}
20+
}
21+
22+
void loongarch_break(int a) {
23+
__builtin_loongarch_break(32769); // expected-error {{argument value 32769 is outside the valid range [0, 32767]}}
24+
__builtin_loongarch_break(-1); // expected-error {{argument value 4294967295 is outside the valid range [0, 32767]}}
25+
__builtin_loongarch_break(a); // expected-error {{argument to '__builtin_loongarch_break' must be a constant integer}}
26+
}
27+
28+
void syscall(int a) {
29+
__builtin_loongarch_syscall(32769); // expected-error {{argument value 32769 is outside the valid range [0, 32767]}}
30+
__builtin_loongarch_syscall(-1); // expected-error {{argument value 4294967295 is outside the valid range [0, 32767]}}
31+
__builtin_loongarch_syscall(a); // expected-error {{argument to '__builtin_loongarch_syscall' must be a constant integer}}
1632
}

clang/test/CodeGen/LoongArch/intrinsic.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,44 @@ void dbar() {
2020
return __builtin_loongarch_dbar(0);
2121
}
2222

23+
// LA32-LABEL: @ibar(
24+
// LA32-NEXT: entry:
25+
// LA32-NEXT: call void @llvm.loongarch.ibar(i32 0)
26+
// LA32-NEXT: ret void
27+
//
28+
// LA64-LABEL: @ibar(
29+
// LA64-NEXT: entry:
30+
// LA64-NEXT: call void @llvm.loongarch.ibar(i32 0)
31+
// LA64-NEXT: ret void
32+
//
33+
void ibar() {
34+
return __builtin_loongarch_ibar(0);
35+
}
36+
37+
// LA32-LABEL: @loongarch_break(
38+
// LA32-NEXT: entry:
39+
// LA32-NEXT: call void @llvm.loongarch.break(i32 1)
40+
// LA32-NEXT: ret void
41+
//
42+
// LA64-LABEL: @loongarch_break(
43+
// LA64-NEXT: entry:
44+
// LA64-NEXT: call void @llvm.loongarch.break(i32 1)
45+
// LA64-NEXT: ret void
46+
//
47+
void loongarch_break() {
48+
__builtin_loongarch_break(1);
49+
}
50+
51+
// LA32-LABEL: @syscall(
52+
// LA32-NEXT: entry:
53+
// LA32-NEXT: call void @llvm.loongarch.syscall(i32 1)
54+
// LA32-NEXT: ret void
55+
//
56+
// LA64-LABEL: @syscall(
57+
// LA64-NEXT: entry:
58+
// LA64-NEXT: call void @llvm.loongarch.syscall(i32 1)
59+
// LA64-NEXT: ret void
60+
//
61+
void syscall() {
62+
__builtin_loongarch_syscall(1);
63+
}

llvm/include/llvm/IR/IntrinsicsLoongArch.td

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ defm int_loongarch_masked_cmpxchg : MaskedAtomicRMWFiveOpIntrinsics;
4949
//===----------------------------------------------------------------------===//
5050
// LoongArch BASE
5151

52-
def int_loongarch_dbar : Intrinsic<[], [llvm_i32_ty]>;
52+
def int_loongarch_break : Intrinsic<[], [llvm_i32_ty], [ImmArg<ArgIndex<0>>]>;
53+
def int_loongarch_dbar : Intrinsic<[], [llvm_i32_ty], [ImmArg<ArgIndex<0>>]>;
54+
def int_loongarch_ibar : Intrinsic<[], [llvm_i32_ty], [ImmArg<ArgIndex<0>>]>;
55+
def int_loongarch_syscall : Intrinsic<[], [llvm_i32_ty], [ImmArg<ArgIndex<0>>]>;
56+
5357
def int_loongarch_crc_w_d_w : Intrinsic<[llvm_i32_ty],
5458
[llvm_i64_ty, llvm_i32_ty]>;
5559
} // TargetPrefix = "loongarch"

llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -578,35 +578,64 @@ LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op,
578578
}
579579
}
580580

581+
// Helper function that emits error message for intrinsics with void return
582+
// value.
583+
static SDValue emitIntrinsicErrorMessage(SDValue Op, StringRef Name,
584+
StringRef ErrorMsg,
585+
SelectionDAG &DAG) {
586+
587+
DAG.getContext()->emitError("argument to '" + Name + "' " + ErrorMsg);
588+
return Op.getOperand(0);
589+
}
590+
581591
SDValue LoongArchTargetLowering::lowerINTRINSIC_VOID(SDValue Op,
582592
SelectionDAG &DAG) const {
583593
SDLoc DL(Op);
584594
MVT GRLenVT = Subtarget.getGRLenVT();
595+
SDValue Op0 = Op.getOperand(0);
596+
SDValue Op2 = Op.getOperand(2);
597+
const StringRef ErrorMsgOOR = "out of range";
585598

586599
switch (Op.getConstantOperandVal(1)) {
587600
default:
588601
// TODO: Add more Intrinsics.
589602
return SDValue();
590603
case Intrinsic::loongarch_dbar: {
591-
SDValue Op0 = Op.getOperand(0);
592-
SDValue Op2 = Op.getOperand(2);
593-
if (!isa<ConstantSDNode>(Op2)) {
594-
DAG.getContext()->emitError("argument to '__builtin_loongarch_dbar' must "
595-
"be a constant integer");
596-
return Op.getOperand(0);
597-
}
598604
unsigned Imm = cast<ConstantSDNode>(Op2)->getZExtValue();
599-
if (!isUInt<15>(Imm)) {
600-
DAG.getContext()->emitError(
601-
"argument to '__builtin_loongarch_dbar' out of range");
602-
return Op0;
603-
}
605+
if (!isUInt<15>(Imm))
606+
return emitIntrinsicErrorMessage(Op, "__builtin_loongarch_dbar",
607+
ErrorMsgOOR, DAG);
604608

605-
if (GRLenVT == MVT::i32)
606-
return Op;
607609
return DAG.getNode(LoongArchISD::DBAR, DL, MVT::Other, Op0,
608610
DAG.getConstant(Imm, DL, GRLenVT));
609611
}
612+
case Intrinsic::loongarch_ibar: {
613+
unsigned Imm = cast<ConstantSDNode>(Op2)->getZExtValue();
614+
if (!isUInt<15>(Imm))
615+
return emitIntrinsicErrorMessage(Op, "__builtin_loongarch_ibar",
616+
ErrorMsgOOR, DAG);
617+
618+
return DAG.getNode(LoongArchISD::IBAR, DL, MVT::Other, Op0,
619+
DAG.getConstant(Imm, DL, GRLenVT));
620+
}
621+
case Intrinsic::loongarch_break: {
622+
unsigned Imm = cast<ConstantSDNode>(Op2)->getZExtValue();
623+
if (!isUInt<15>(Imm))
624+
return emitIntrinsicErrorMessage(Op, "__builtin_loongarch_break",
625+
ErrorMsgOOR, DAG);
626+
627+
return DAG.getNode(LoongArchISD::BREAK, DL, MVT::Other, Op0,
628+
DAG.getConstant(Imm, DL, GRLenVT));
629+
}
630+
case Intrinsic::loongarch_syscall: {
631+
unsigned Imm = cast<ConstantSDNode>(Op2)->getZExtValue();
632+
if (!isUInt<15>(Imm))
633+
return emitIntrinsicErrorMessage(Op, "__builtin_loongarch_syscall",
634+
ErrorMsgOOR, DAG);
635+
636+
return DAG.getNode(LoongArchISD::SYSCALL, DL, MVT::Other, Op0,
637+
DAG.getConstant(Imm, DL, GRLenVT));
638+
}
610639
}
611640
}
612641

@@ -1354,6 +1383,9 @@ const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const {
13541383
NODE_NAME_CASE(CLZ_W)
13551384
NODE_NAME_CASE(CTZ_W)
13561385
NODE_NAME_CASE(DBAR)
1386+
NODE_NAME_CASE(IBAR)
1387+
NODE_NAME_CASE(BREAK)
1388+
NODE_NAME_CASE(SYSCALL)
13571389
NODE_NAME_CASE(CRC_W_D_W)
13581390
}
13591391
#undef NODE_NAME_CASE

llvm/lib/Target/LoongArch/LoongArchISelLowering.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,10 @@ enum NodeType : unsigned {
6060
BITREV_W,
6161

6262
// Intrinsic operations
63+
BREAK,
6364
DBAR,
65+
IBAR,
66+
SYSCALL,
6467

6568
// CRC check operations
6669
CRC_W_D_W

llvm/lib/Target/LoongArch/LoongArchInstrInfo.td

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ def SDT_LoongArchBStrPick: SDTypeProfile<1, 3, [
3535
SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisInt<2>, SDTCisSameAs<2, 3>
3636
]>;
3737

38-
def SDT_LoongArchDBAR : SDTypeProfile<0, 1, [SDTCisVT<0, GRLenVT>]>;
38+
// "VI" means no output and an integer input.
39+
def SDT_LoongArchVI : SDTypeProfile<0, 1, [SDTCisVT<0, GRLenVT>]>;
3940

4041
// TODO: Add LoongArch specific DAG Nodes
4142
// Target-independent nodes, but with target-specific formats.
@@ -70,8 +71,14 @@ def loongarch_bitrev_4b : SDNode<"LoongArchISD::BITREV_4B", SDTUnaryOp>;
7071
def loongarch_bitrev_w : SDNode<"LoongArchISD::BITREV_W", SDTUnaryOp>;
7172
def loongarch_clzw : SDNode<"LoongArchISD::CLZ_W", SDTIntBitCountUnaryOp>;
7273
def loongarch_ctzw : SDNode<"LoongArchISD::CTZ_W", SDTIntBitCountUnaryOp>;
73-
def loongarch_dbar : SDNode<"LoongArchISD::DBAR", SDT_LoongArchDBAR,
74+
def loongarch_dbar : SDNode<"LoongArchISD::DBAR", SDT_LoongArchVI,
7475
[SDNPHasChain, SDNPSideEffect]>;
76+
def loongarch_ibar : SDNode<"LoongArchISD::IBAR", SDT_LoongArchVI,
77+
[SDNPHasChain, SDNPSideEffect]>;
78+
def loongarch_break : SDNode<"LoongArchISD::BREAK", SDT_LoongArchVI,
79+
[SDNPHasChain, SDNPSideEffect]>;
80+
def loongarch_syscall : SDNode<"LoongArchISD::SYSCALL", SDT_LoongArchVI,
81+
[SDNPHasChain, SDNPSideEffect]>;
7582

7683
//===----------------------------------------------------------------------===//
7784
// Operand and SDNode transformation definitions.
@@ -1341,13 +1348,12 @@ def : Pat<(atomic_load_xor_32 GPR:$addr, GPR:$incr),
13411348

13421349
/// Intrinsics
13431350

1344-
let Predicates = [IsLA32] in {
1345-
def : Pat<(int_loongarch_dbar uimm15:$imm15), (DBAR uimm15:$imm15)>;
1346-
} // Predicates = [IsLA32]
1347-
1348-
let Predicates = [IsLA64] in {
13491351
def : Pat<(loongarch_dbar uimm15:$imm15), (DBAR uimm15:$imm15)>;
1352+
def : Pat<(loongarch_ibar uimm15:$imm15), (IBAR uimm15:$imm15)>;
1353+
def : Pat<(loongarch_break uimm15:$imm15), (BREAK uimm15:$imm15)>;
1354+
def : Pat<(loongarch_syscall uimm15:$imm15), (SYSCALL uimm15:$imm15)>;
13501355

1356+
let Predicates = [IsLA64] in {
13511357
// CRC Check Instructions
13521358
def : PatGprGpr<loongarch_crc_w_d_w, CRC_W_D_W>;
13531359
} // Predicates = [IsLA64]
Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
; RUN: not llc --mtriple=loongarch32 --disable-verify < %s 2>&1 | FileCheck %s
2-
; RUN: not llc --mtriple=loongarch64 --disable-verify < %s 2>&1 | FileCheck %s
1+
; RUN: not llc --mtriple=loongarch32 < %s 2>&1 | FileCheck %s
2+
; RUN: not llc --mtriple=loongarch64 < %s 2>&1 | FileCheck %s
33

4-
define void @dbar_not_constant(i32 %x) nounwind {
5-
; CHECK: argument to '__builtin_loongarch_dbar' must be a constant integer
6-
entry:
7-
call void @llvm.loongarch.dbar(i32 %x)
8-
ret void
9-
}
4+
declare void @llvm.loongarch.dbar(i32)
5+
declare void @llvm.loongarch.ibar(i32)
6+
declare void @llvm.loongarch.break(i32)
7+
declare void @llvm.loongarch.syscall(i32)
108

119
define void @dbar_imm_out_of_hi_range() nounwind {
1210
; CHECK: argument to '__builtin_loongarch_dbar' out of range
@@ -22,4 +20,44 @@ entry:
2220
ret void
2321
}
2422

25-
declare void @llvm.loongarch.dbar(i32)
23+
define void @ibar_imm_out_of_hi_range() nounwind {
24+
; CHECK: argument to '__builtin_loongarch_ibar' out of range
25+
entry:
26+
call void @llvm.loongarch.ibar(i32 32769)
27+
ret void
28+
}
29+
30+
define void @ibar_imm_out_of_lo_range() nounwind {
31+
; CHECK: argument to '__builtin_loongarch_ibar' out of range
32+
entry:
33+
call void @llvm.loongarch.ibar(i32 -1)
34+
ret void
35+
}
36+
37+
define void @break_imm_out_of_hi_range() nounwind {
38+
; CHECK: argument to '__builtin_loongarch_break' out of range
39+
entry:
40+
call void @llvm.loongarch.break(i32 32769)
41+
ret void
42+
}
43+
44+
define void @break_imm_out_of_lo_range() nounwind {
45+
; CHECK: argument to '__builtin_loongarch_break' out of range
46+
entry:
47+
call void @llvm.loongarch.break(i32 -1)
48+
ret void
49+
}
50+
51+
define void @syscall_imm_out_of_hi_range() nounwind {
52+
; CHECK: argument to '__builtin_loongarch_syscall' out of range
53+
entry:
54+
call void @llvm.loongarch.syscall(i32 32769)
55+
ret void
56+
}
57+
58+
define void @syscall_imm_out_of_lo_range() nounwind {
59+
; CHECK: argument to '__builtin_loongarch_syscall' out of range
60+
entry:
61+
call void @llvm.loongarch.syscall(i32 -1)
62+
ret void
63+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
; RUN: not llc --mtriple=loongarch32 < %s 2>&1 | FileCheck %s
2+
; RUN: not llc --mtriple=loongarch64 < %s 2>&1 | FileCheck %s
3+
4+
declare void @llvm.loongarch.dbar(i32)
5+
declare void @llvm.loongarch.ibar(i32)
6+
declare void @llvm.loongarch.break(i32)
7+
declare void @llvm.loongarch.syscall(i32)
8+
9+
define void @dbar_not_constant(i32 %x) nounwind {
10+
; CHECK: immarg operand has non-immediate parameter
11+
entry:
12+
call void @llvm.loongarch.dbar(i32 %x)
13+
ret void
14+
}
15+
16+
define void @ibar(i32 %x) nounwind {
17+
; CHECK: immarg operand has non-immediate parameter
18+
entry:
19+
call void @llvm.loongarch.ibar(i32 %x)
20+
ret void
21+
}
22+
23+
define void @break(i32 %x) nounwind {
24+
; CHECK: immarg operand has non-immediate parameter
25+
entry:
26+
call void @llvm.loongarch.break(i32 %x)
27+
ret void
28+
}
29+
30+
define void @syscall(i32 %x) nounwind {
31+
; CHECK: immarg operand has non-immediate parameter
32+
entry:
33+
call void @llvm.loongarch.syscall(i32 %x)
34+
ret void
35+
}

0 commit comments

Comments
 (0)