gonglingqin created this revision.
gonglingqin added reviewers: xen0n, xry111, SixWeining, wangleiat, MaskRay,
XiaodongLoong.
Herald added subscribers: StephenFan, hiraditya.
Herald added a project: All.
gonglingqin requested review of this revision.
Herald added projects: clang, LLVM.
Herald added subscribers: llvm-commits, cfe-commits.
Diagnostics for intrinsic input parameters have also been added.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D138094
Files:
clang/include/clang/Basic/BuiltinsLoongArch.def
clang/lib/CodeGen/CGBuiltin.cpp
clang/lib/Headers/larchintrin.h
clang/lib/Sema/SemaChecking.cpp
clang/test/CodeGen/LoongArch/intrinsic-error.c
clang/test/CodeGen/LoongArch/intrinsic.c
llvm/include/llvm/IR/IntrinsicsLoongArch.td
llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
llvm/lib/Target/LoongArch/LoongArchISelLowering.h
llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
llvm/test/CodeGen/LoongArch/intrinsic-error.ll
llvm/test/CodeGen/LoongArch/intrinsic.ll
Index: llvm/test/CodeGen/LoongArch/intrinsic.ll
===================================================================
--- llvm/test/CodeGen/LoongArch/intrinsic.ll
+++ llvm/test/CodeGen/LoongArch/intrinsic.ll
@@ -3,6 +3,9 @@
; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s
declare void @llvm.loongarch.dbar(i32)
+declare void @llvm.loongarch.ibar(i32)
+declare void @llvm.loongarch.break(i32)
+declare void @llvm.loongarch.syscall(i32)
define void @foo() nounwind {
; CHECK-LABEL: foo:
@@ -13,3 +16,33 @@
call void @llvm.loongarch.dbar(i32 0)
ret void
}
+
+define void @ibar() nounwind {
+; CHECK-LABEL: ibar:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: ibar 0
+; CHECK-NEXT: ret
+entry:
+ call void @llvm.loongarch.ibar(i32 0)
+ ret void
+}
+
+define void @break() nounwind {
+; CHECK-LABEL: break:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: break 1
+; CHECK-NEXT: ret
+entry:
+ call void @llvm.loongarch.break(i32 1)
+ ret void
+}
+
+define void @syscall() nounwind {
+; CHECK-LABEL: syscall:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: syscall 1
+; CHECK-NEXT: ret
+entry:
+ call void @llvm.loongarch.syscall(i32 1)
+ ret void
+}
Index: llvm/test/CodeGen/LoongArch/intrinsic-error.ll
===================================================================
--- llvm/test/CodeGen/LoongArch/intrinsic-error.ll
+++ llvm/test/CodeGen/LoongArch/intrinsic-error.ll
@@ -1,6 +1,11 @@
; RUN: not llc --mtriple=loongarch32 --disable-verify < %s 2>&1 | FileCheck %s
; RUN: not llc --mtriple=loongarch64 --disable-verify < %s 2>&1 | FileCheck %s
+declare void @llvm.loongarch.dbar(i32)
+declare void @llvm.loongarch.ibar(i32)
+declare void @llvm.loongarch.break(i32)
+declare void @llvm.loongarch.syscall(i32)
+
define void @dbar_not_constant(i32 %x) nounwind {
; CHECK: argument to '__builtin_loongarch_dbar' must be a constant integer
entry:
@@ -8,6 +13,27 @@
ret void
}
+define void @ibar(i32 %x) nounwind {
+; CHECK: argument to '__builtin_loongarch_ibar' must be a constant integer
+entry:
+ call void @llvm.loongarch.ibar(i32 %x)
+ ret void
+}
+
+define void @break(i32 %x) nounwind {
+; CHECK: argument to '__builtin_loongarch_break' must be a constant integer
+entry:
+ call void @llvm.loongarch.break(i32 %x)
+ ret void
+}
+
+define void @syscall(i32 %x) nounwind {
+; CHECK: argument to '__builtin_loongarch_syscall' must be a constant integer
+entry:
+ call void @llvm.loongarch.syscall(i32 %x)
+ ret void
+}
+
define void @dbar_imm_out_of_hi_range() nounwind {
; CHECK: argument to '__builtin_loongarch_dbar' out of range
entry:
@@ -22,4 +48,44 @@
ret void
}
-declare void @llvm.loongarch.dbar(i32)
+define void @ibar_imm_out_of_hi_range() nounwind {
+; CHECK: argument to '__builtin_loongarch_ibar' out of range
+entry:
+ call void @llvm.loongarch.ibar(i32 32769)
+ ret void
+}
+
+define void @ibar_imm_out_of_lo_range() nounwind {
+; CHECK: argument to '__builtin_loongarch_ibar' out of range
+entry:
+ call void @llvm.loongarch.ibar(i32 -1)
+ ret void
+}
+
+define void @break_imm_out_of_hi_range() nounwind {
+; CHECK: argument to '__builtin_loongarch_break' out of range
+entry:
+ call void @llvm.loongarch.break(i32 32769)
+ ret void
+}
+
+define void @break_imm_out_of_lo_range() nounwind {
+; CHECK: argument to '__builtin_loongarch_break' out of range
+entry:
+ call void @llvm.loongarch.break(i32 -1)
+ ret void
+}
+
+define void @syscall_imm_out_of_hi_range() nounwind {
+; CHECK: argument to '__builtin_loongarch_syscall' out of range
+entry:
+ call void @llvm.loongarch.syscall(i32 32769)
+ ret void
+}
+
+define void @syscall_imm_out_of_lo_range() nounwind {
+; CHECK: argument to '__builtin_loongarch_syscall' out of range
+entry:
+ call void @llvm.loongarch.syscall(i32 -1)
+ ret void
+}
Index: llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
===================================================================
--- llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -35,7 +35,8 @@
SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisInt<2>, SDTCisSameAs<2, 3>
]>;
-def SDT_LoongArchDBAR : SDTypeProfile<0, 1, [SDTCisVT<0, GRLenVT>]>;
+// "VI" means no output and an integer input.
+def SDT_LoongArchVI : SDTypeProfile<0, 1, [SDTCisVT<0, GRLenVT>]>;
// TODO: Add LoongArch specific DAG Nodes
// Target-independent nodes, but with target-specific formats.
@@ -67,8 +68,14 @@
def loongarch_bitrev_w : SDNode<"LoongArchISD::BITREV_W", SDTUnaryOp>;
def loongarch_clzw : SDNode<"LoongArchISD::CLZ_W", SDTIntBitCountUnaryOp>;
def loongarch_ctzw : SDNode<"LoongArchISD::CTZ_W", SDTIntBitCountUnaryOp>;
-def loongarch_dbar : SDNode<"LoongArchISD::DBAR", SDT_LoongArchDBAR,
+def loongarch_dbar : SDNode<"LoongArchISD::DBAR", SDT_LoongArchVI,
[SDNPHasChain, SDNPSideEffect]>;
+def loongarch_ibar : SDNode<"LoongArchISD::IBAR", SDT_LoongArchVI,
+ [SDNPHasChain, SDNPSideEffect]>;
+def loongarch_break : SDNode<"LoongArchISD::BREAK", SDT_LoongArchVI,
+ [SDNPHasChain, SDNPSideEffect]>;
+def loongarch_syscall : SDNode<"LoongArchISD::SYSCALL", SDT_LoongArchVI,
+ [SDNPHasChain, SDNPSideEffect]>;
//===----------------------------------------------------------------------===//
// Operand and SDNode transformation definitions.
@@ -1318,10 +1325,16 @@
let Predicates = [IsLA32] in {
def : Pat<(int_loongarch_dbar uimm15:$imm15), (DBAR uimm15:$imm15)>;
+def : Pat<(int_loongarch_ibar uimm15:$imm15), (IBAR uimm15:$imm15)>;
+def : Pat<(int_loongarch_break uimm15:$imm15), (BREAK uimm15:$imm15)>;
+def : Pat<(int_loongarch_syscall uimm15:$imm15), (SYSCALL uimm15:$imm15)>;
} // Predicates = [IsLA32]
let Predicates = [IsLA64] in {
def : Pat<(loongarch_dbar uimm15:$imm15), (DBAR uimm15:$imm15)>;
+def : Pat<(loongarch_ibar uimm15:$imm15), (IBAR uimm15:$imm15)>;
+def : Pat<(loongarch_break uimm15:$imm15), (BREAK uimm15:$imm15)>;
+def : Pat<(loongarch_syscall uimm15:$imm15), (SYSCALL uimm15:$imm15)>;
// CRC Check Instructions
def : PatGprGpr<loongarch_crc_w_d_w, CRC_W_D_W>;
Index: llvm/lib/Target/LoongArch/LoongArchISelLowering.h
===================================================================
--- llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -58,7 +58,10 @@
BITREV_W,
// Intrinsic operations
+ BREAK,
DBAR,
+ IBAR,
+ SYSCALL,
// CRC check operations
CRC_W_D_W
Index: llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
===================================================================
--- llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -576,35 +576,82 @@
}
}
+// Helper function that emits error message for intrinsics with void return
+// value.
+static SDValue emitIntrinsicErrorMessage(SDValue Op, StringRef Name,
+ StringRef ErrorMsg,
+ SelectionDAG &DAG) {
+
+ DAG.getContext()->emitError("argument to '" + Name + "' " + ErrorMsg);
+ return Op.getOperand(0);
+}
+
SDValue LoongArchTargetLowering::lowerINTRINSIC_VOID(SDValue Op,
SelectionDAG &DAG) const {
SDLoc DL(Op);
MVT GRLenVT = Subtarget.getGRLenVT();
+ SDValue Op0 = Op.getOperand(0);
+ SDValue Op2 = Op.getOperand(2);
+ StringRef Name;
+ const StringRef ErrorMsgConst = "must be a constant integer";
+ const StringRef ErrorMsgOOR = "out of range";
switch (Op.getConstantOperandVal(1)) {
default:
// TODO: Add more Intrinsics.
return SDValue();
case Intrinsic::loongarch_dbar: {
- SDValue Op0 = Op.getOperand(0);
- SDValue Op2 = Op.getOperand(2);
- if (!isa<ConstantSDNode>(Op2)) {
- DAG.getContext()->emitError("argument to '__builtin_loongarch_dbar' must "
- "be a constant integer");
- return Op.getOperand(0);
- }
+ Name = "__builtin_loongarch_dbar";
+ if (!isa<ConstantSDNode>(Op2))
+ return emitIntrinsicErrorMessage(Op, Name, ErrorMsgConst, DAG);
unsigned Imm = cast<ConstantSDNode>(Op2)->getZExtValue();
- if (!isUInt<15>(Imm)) {
- DAG.getContext()->emitError(
- "argument to '__builtin_loongarch_dbar' out of range");
- return Op0;
- }
+ if (!isUInt<15>(Imm))
+ return emitIntrinsicErrorMessage(Op, Name, ErrorMsgOOR, DAG);
if (GRLenVT == MVT::i32)
return Op;
return DAG.getNode(LoongArchISD::DBAR, DL, MVT::Other, Op0,
DAG.getConstant(Imm, DL, GRLenVT));
}
+ case Intrinsic::loongarch_ibar: {
+ Name = "__builtin_loongarch_ibar";
+ if (!isa<ConstantSDNode>(Op2))
+ return emitIntrinsicErrorMessage(Op, Name, ErrorMsgConst, DAG);
+ unsigned Imm = cast<ConstantSDNode>(Op2)->getZExtValue();
+ if (!isUInt<15>(Imm))
+ return emitIntrinsicErrorMessage(Op, Name, ErrorMsgOOR, DAG);
+
+ if (GRLenVT == MVT::i32)
+ return Op;
+ return DAG.getNode(LoongArchISD::IBAR, DL, MVT::Other, Op0,
+ DAG.getConstant(Imm, DL, GRLenVT));
+ }
+ case Intrinsic::loongarch_break: {
+ Name = "__builtin_loongarch_break";
+ if (!isa<ConstantSDNode>(Op2))
+ return emitIntrinsicErrorMessage(Op, Name, ErrorMsgConst, DAG);
+ unsigned Imm = cast<ConstantSDNode>(Op2)->getZExtValue();
+ if (!isUInt<15>(Imm))
+ return emitIntrinsicErrorMessage(Op, Name, ErrorMsgOOR, DAG);
+
+ if (GRLenVT == MVT::i32)
+ return Op;
+ return DAG.getNode(LoongArchISD::BREAK, DL, MVT::Other, Op0,
+ DAG.getConstant(Imm, DL, GRLenVT));
+ }
+ case Intrinsic::loongarch_syscall: {
+ Name = "__builtin_loongarch_syscall";
+ if (!isa<ConstantSDNode>(Op2))
+ return emitIntrinsicErrorMessage(Op, Name, ErrorMsgConst, DAG);
+ unsigned Imm = cast<ConstantSDNode>(Op2)->getZExtValue();
+ if (!isUInt<15>(Imm))
+ return emitIntrinsicErrorMessage(Op, Name, ErrorMsgOOR, DAG);
+
+ if (GRLenVT == MVT::i32)
+ return Op;
+ return DAG.getNode(LoongArchISD::SYSCALL, DL, MVT::Other, Op0,
+ DAG.getConstant(Imm, DL, GRLenVT));
+ }
}
}
@@ -1351,6 +1398,9 @@
NODE_NAME_CASE(CLZ_W)
NODE_NAME_CASE(CTZ_W)
NODE_NAME_CASE(DBAR)
+ NODE_NAME_CASE(IBAR)
+ NODE_NAME_CASE(BREAK)
+ NODE_NAME_CASE(SYSCALL)
NODE_NAME_CASE(CRC_W_D_W)
}
#undef NODE_NAME_CASE
Index: llvm/include/llvm/IR/IntrinsicsLoongArch.td
===================================================================
--- llvm/include/llvm/IR/IntrinsicsLoongArch.td
+++ llvm/include/llvm/IR/IntrinsicsLoongArch.td
@@ -49,7 +49,11 @@
//===----------------------------------------------------------------------===//
// LoongArch BASE
+def int_loongarch_break : Intrinsic<[], [llvm_i32_ty]>;
def int_loongarch_dbar : Intrinsic<[], [llvm_i32_ty]>;
+def int_loongarch_ibar : Intrinsic<[], [llvm_i32_ty]>;
+def int_loongarch_syscall : Intrinsic<[], [llvm_i32_ty]>;
+
def int_loongarch_crc_w_d_w : Intrinsic<[llvm_i32_ty],
[llvm_i64_ty, llvm_i32_ty]>;
} // TargetPrefix = "loongarch"
Index: clang/test/CodeGen/LoongArch/intrinsic.c
===================================================================
--- clang/test/CodeGen/LoongArch/intrinsic.c
+++ clang/test/CodeGen/LoongArch/intrinsic.c
@@ -20,3 +20,44 @@
return __builtin_loongarch_dbar(0);
}
+// LA32-LABEL: @ibar(
+// LA32-NEXT: entry:
+// LA32-NEXT: call void @llvm.loongarch.ibar(i32 0)
+// LA32-NEXT: ret void
+//
+// LA64-LABEL: @ibar(
+// LA64-NEXT: entry:
+// LA64-NEXT: call void @llvm.loongarch.ibar(i32 0)
+// LA64-NEXT: ret void
+//
+void ibar() {
+ return __builtin_loongarch_ibar(0);
+}
+
+// LA32-LABEL: @loongarch_break(
+// LA32-NEXT: entry:
+// LA32-NEXT: call void @llvm.loongarch.break(i32 1)
+// LA32-NEXT: ret void
+//
+// LA64-LABEL: @loongarch_break(
+// LA64-NEXT: entry:
+// LA64-NEXT: call void @llvm.loongarch.break(i32 1)
+// LA64-NEXT: ret void
+//
+void loongarch_break() {
+ __builtin_loongarch_break(1);
+}
+
+// LA32-LABEL: @syscall(
+// LA32-NEXT: entry:
+// LA32-NEXT: call void @llvm.loongarch.syscall(i32 1)
+// LA32-NEXT: ret void
+//
+// LA64-LABEL: @syscall(
+// LA64-NEXT: entry:
+// LA64-NEXT: call void @llvm.loongarch.syscall(i32 1)
+// LA64-NEXT: ret void
+//
+void syscall() {
+ __builtin_loongarch_syscall(1);
+}
Index: clang/test/CodeGen/LoongArch/intrinsic-error.c
===================================================================
--- clang/test/CodeGen/LoongArch/intrinsic-error.c
+++ clang/test/CodeGen/LoongArch/intrinsic-error.c
@@ -14,3 +14,18 @@
void dbar_out_of_lo_range() {
return __builtin_loongarch_dbar(-1); // expected-error {{argument value 4294967295 is outside the valid range [0, 32767]}}
}
+
+void ibar_out_of_range() {
+ __builtin_loongarch_ibar(32769); // expected-error {{argument value 32769 is outside the valid range [0, 32767]}}
+ __builtin_loongarch_ibar(-1); // expected-error {{argument value 4294967295 is outside the valid range [0, 32767]}}
+}
+
+void loongarch_break_out_of_range() {
+ __builtin_loongarch_break(32769); // expected-error {{argument value 32769 is outside the valid range [0, 32767]}}
+ __builtin_loongarch_break(-1); // expected-error {{argument value 4294967295 is outside the valid range [0, 32767]}}
+}
+
+void syscall_out_of_range() {
+ __builtin_loongarch_syscall(32769); // expected-error {{argument value 32769 is outside the valid range [0, 32767]}}
+ __builtin_loongarch_syscall(-1); // expected-error {{argument value 4294967295 is outside the valid range [0, 32767]}}
+}
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -3685,7 +3685,10 @@
diag::err_loongarch_builtin_requires_la64)
<< TheCall->getSourceRange();
break;
+ case LoongArch::BI__builtin_loongarch_break:
case LoongArch::BI__builtin_loongarch_dbar:
+ case LoongArch::BI__builtin_loongarch_ibar:
+ case LoongArch::BI__builtin_loongarch_syscall:
// Check if immediate is in [0, 32767].
return SemaBuiltinConstantArgRange(TheCall, 0, 0, 32767);
}
Index: clang/lib/Headers/larchintrin.h
===================================================================
--- clang/lib/Headers/larchintrin.h
+++ clang/lib/Headers/larchintrin.h
@@ -22,8 +22,14 @@
}
#endif
+#define __break(/*ui15*/ _1) __builtin_loongarch_break((_1))
+
#define __dbar(/*ui15*/ _1) __builtin_loongarch_dbar((_1))
+#define __ibar(/*ui15*/ _1) __builtin_loongarch_ibar((_1))
+
+#define __syscall(/*ui15*/ _1) __builtin_loongarch_syscall((_1))
+
#ifdef __cplusplus
}
#endif
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -19648,6 +19648,15 @@
case LoongArch::BI__builtin_loongarch_crc_w_d_w:
ID = Intrinsic::loongarch_crc_w_d_w;
break;
+ case LoongArch::BI__builtin_loongarch_break:
+ ID = Intrinsic::loongarch_break;
+ break;
+ case LoongArch::BI__builtin_loongarch_ibar:
+ ID = Intrinsic::loongarch_ibar;
+ break;
+ case LoongArch::BI__builtin_loongarch_syscall:
+ ID = Intrinsic::loongarch_syscall;
+ break;
// TODO: Support more Intrinsics.
}
Index: clang/include/clang/Basic/BuiltinsLoongArch.def
===================================================================
--- clang/include/clang/Basic/BuiltinsLoongArch.def
+++ clang/include/clang/Basic/BuiltinsLoongArch.def
@@ -18,6 +18,9 @@
// TODO: Support more builtins.
// TODO: Added feature constraints.
TARGET_BUILTIN(__builtin_loongarch_dbar, "vIUi", "nc", "")
+TARGET_BUILTIN(__builtin_loongarch_ibar, "vIUi", "nc", "")
+TARGET_BUILTIN(__builtin_loongarch_break, "vIUi", "nc", "")
+TARGET_BUILTIN(__builtin_loongarch_syscall, "vIUi", "nc", "")
TARGET_BUILTIN(__builtin_loongarch_crc_w_d_w, "iLii", "nc", "64bit")
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits