Skip to content

Commit

Permalink
[Clang][LoongArch] Add intrinsic for asrtle, asrtgt, lddir, ldpte and…
Browse files Browse the repository at this point in the history
  • Loading branch information
gonglingqin committed Dec 22, 2022
1 parent 0dc4dfa commit aeb8f91
Show file tree
Hide file tree
Showing 15 changed files with 326 additions and 1 deletion.
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/BuiltinsLoongArch.def
Expand Up @@ -21,6 +21,9 @@ 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_cpucfg, "UiUi", "nc", "")
TARGET_BUILTIN(__builtin_loongarch_asrtle_d, "vLiLi", "nc", "64bit")
TARGET_BUILTIN(__builtin_loongarch_asrtgt_d, "vLiLi", "nc", "64bit")

TARGET_BUILTIN(__builtin_loongarch_crc_w_b_w, "iii", "nc", "64bit")
TARGET_BUILTIN(__builtin_loongarch_crc_w_h_w, "iii", "nc", "64bit")
Expand All @@ -47,5 +50,8 @@ TARGET_BUILTIN(__builtin_loongarch_iocsrwr_h, "vUiUi", "nc", "")
TARGET_BUILTIN(__builtin_loongarch_iocsrwr_w, "vUiUi", "nc", "")
TARGET_BUILTIN(__builtin_loongarch_iocsrwr_d, "vULiUi", "nc", "64bit")

TARGET_BUILTIN(__builtin_loongarch_lddir_d, "LiLiIULi", "nc", "64bit")
TARGET_BUILTIN(__builtin_loongarch_ldpte_d, "vLiIULi", "nc", "64bit")

#undef BUILTIN
#undef TARGET_BUILTIN
15 changes: 15 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Expand Up @@ -19724,6 +19724,21 @@ Value *CodeGenFunction::EmitLoongArchBuiltinExpr(unsigned BuiltinID,
case LoongArch::BI__builtin_loongarch_iocsrwr_d:
ID = Intrinsic::loongarch_iocsrwr_d;
break;
case LoongArch::BI__builtin_loongarch_cpucfg:
ID = Intrinsic::loongarch_cpucfg;
break;
case LoongArch::BI__builtin_loongarch_asrtle_d:
ID = Intrinsic::loongarch_asrtle_d;
break;
case LoongArch::BI__builtin_loongarch_asrtgt_d:
ID = Intrinsic::loongarch_asrtgt_d;
break;
case LoongArch::BI__builtin_loongarch_lddir_d:
ID = Intrinsic::loongarch_lddir_d;
break;
case LoongArch::BI__builtin_loongarch_ldpte_d:
ID = Intrinsic::loongarch_ldpte_d;
break;
// TODO: Support more Intrinsics.
}

Expand Down
26 changes: 26 additions & 0 deletions clang/lib/Headers/larchintrin.h
Expand Up @@ -139,12 +139,38 @@ extern __inline void
__builtin_loongarch_iocsrwr_w((unsigned int)_1, (unsigned int)_2);
}

extern __inline unsigned int
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
__cpucfg(unsigned int _1) {
return (unsigned int)__builtin_loongarch_cpucfg((unsigned int)_1);
}

#if __loongarch_grlen == 64
extern __inline void
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
__iocsrwr_d(unsigned long int _1, unsigned int _2) {
__builtin_loongarch_iocsrwr_d((unsigned long int)_1, (unsigned int)_2);
}

extern __inline void
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
__asrtgt_d(long int _1, long int _2) {
__builtin_loongarch_asrtgt_d((long int)_1, (long int)_2);
}

extern __inline void
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
__asrtle_d(long int _1, long int _2) {
__builtin_loongarch_asrtle_d((long int)_1, (long int)_2);
}
#endif

#if __loongarch_grlen == 64
#define __lddir_d(/*long int*/ _1, /*ui5*/ _2) \
((long int)__builtin_loongarch_lddir_d((long int)(_1), (_2)))

#define __ldpte_d(/*long int*/ _1, /*ui5*/ _2) \
((void)__builtin_loongarch_ldpte_d((long int)(_1), (_2)))
#endif

#ifdef __cplusplus
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Sema/SemaChecking.cpp
Expand Up @@ -3715,6 +3715,8 @@ bool Sema::CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI,
case LoongArch::BI__builtin_loongarch_crcc_w_d_w:
case LoongArch::BI__builtin_loongarch_iocsrrd_d:
case LoongArch::BI__builtin_loongarch_iocsrwr_d:
case LoongArch::BI__builtin_loongarch_asrtle_d:
case LoongArch::BI__builtin_loongarch_asrtgt_d:
if (!TI.hasFeature("64bit"))
return Diag(TheCall->getBeginLoc(),
diag::err_loongarch_builtin_requires_la64)
Expand Down Expand Up @@ -3750,6 +3752,13 @@ bool Sema::CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI,
diag::err_loongarch_builtin_requires_la64)
<< TheCall->getSourceRange();
return SemaBuiltinConstantArgRange(TheCall, 2, 0, 16383);
case LoongArch::BI__builtin_loongarch_lddir_d:
case LoongArch::BI__builtin_loongarch_ldpte_d:
if (!TI.hasFeature("64bit"))
return Diag(TheCall->getBeginLoc(),
diag::err_loongarch_builtin_requires_la64)
<< TheCall->getSourceRange();
return SemaBuiltinConstantArgRange(TheCall, 1, 0, 31);
}

return false;
Expand Down
16 changes: 16 additions & 0 deletions clang/test/CodeGen/LoongArch/intrinsic-la32-error.c
Expand Up @@ -95,3 +95,19 @@ unsigned long int iocsrrd_d(unsigned int a) {
void iocsrwr_d(unsigned long int a, unsigned int b) {
__builtin_loongarch_iocsrwr_d(a, b); // expected-error {{this builtin requires target: loongarch64}}
}

void asrtle_d(long int a, long int b) {
__builtin_loongarch_asrtle_d(a, b); // expected-error {{this builtin requires target: loongarch64}}
}

void asrtgt_d(long int a, long int b) {
__builtin_loongarch_asrtgt_d(a, b); // expected-error {{this builtin requires target: loongarch64}}
}

void lddir_d(long int a, int b) {
__builtin_loongarch_lddir_d(a, 1); // expected-error {{this builtin requires target: loongarch64}}
}

void ldpte_d(long int a, int b) {
__builtin_loongarch_ldpte_d(a, 1); // expected-error {{this builtin requires target: loongarch64}}
}
12 changes: 12 additions & 0 deletions clang/test/CodeGen/LoongArch/intrinsic-la32.c
Expand Up @@ -154,3 +154,15 @@ void iocsrwr_w(unsigned int a, unsigned int b) {
__iocsrwr_w(a, b);
__builtin_loongarch_iocsrwr_w(a, b);
}

// LA32-LABEL: @cpucfg(
// LA32-NEXT: entry:
// LA32-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.loongarch.cpucfg(i32 [[A:%.*]])
// LA32-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.loongarch.cpucfg(i32 [[A]])
// LA32-NEXT: ret i32 0
//
unsigned int cpucfg(unsigned int a) {
unsigned int b = __cpucfg(a);
unsigned int c = __builtin_loongarch_cpucfg(a);
return 0;
}
12 changes: 12 additions & 0 deletions clang/test/CodeGen/LoongArch/intrinsic-la64-error.c
Expand Up @@ -20,3 +20,15 @@ void csrxchg_d(unsigned long int a, unsigned long int b) {
__builtin_loongarch_csrxchg_d(a, b, -1); // expected-error {{argument value 4294967295 is outside the valid range [0, 16383]}}
__builtin_loongarch_csrxchg_d(a, b, b); // expected-error {{argument to '__builtin_loongarch_csrxchg_d' must be a constant integer}}
}

void lddir_d(long int a, int b) {
__builtin_loongarch_lddir_d(a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
__builtin_loongarch_lddir_d(a, -1); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 31]}}
__builtin_loongarch_lddir_d(a, b); // expected-error {{argument to '__builtin_loongarch_lddir_d' must be a constant integer}}
}

void ldpte_d(long int a, int b) {
__builtin_loongarch_ldpte_d(a, 32); // expected-error {{argument value 32 is outside the valid range [0, 31]}}
__builtin_loongarch_ldpte_d(a, -1); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 31]}}
__builtin_loongarch_ldpte_d(a, b); // expected-error {{argument to '__builtin_loongarch_ldpte_d' must be a constant integer}}
}
57 changes: 57 additions & 0 deletions clang/test/CodeGen/LoongArch/intrinsic-la64.c
Expand Up @@ -316,3 +316,60 @@ void iocsrwr_d(unsigned long int a, unsigned int b) {
__iocsrwr_d(a, b);
__builtin_loongarch_iocsrwr_d(a, b);
}

// CHECK-LABEL: @asrtle_d(
// CHECK-NEXT: entry:
// CHECK-NEXT: tail call void @llvm.loongarch.asrtle.d(i64 [[A:%.*]], i64 [[B:%.*]])
// CHECK-NEXT: tail call void @llvm.loongarch.asrtle.d(i64 [[A]], i64 [[B]])
// CHECK-NEXT: ret void
//
void asrtle_d(long int a, long int b) {
__asrtle_d(a, b);
__builtin_loongarch_asrtle_d(a, b);
}

// CHECK-LABEL: @asrtgt_d(
// CHECK-NEXT: entry:
// CHECK-NEXT: tail call void @llvm.loongarch.asrtgt.d(i64 [[A:%.*]], i64 [[B:%.*]])
// CHECK-NEXT: tail call void @llvm.loongarch.asrtgt.d(i64 [[A]], i64 [[B]])
// CHECK-NEXT: ret void
//
void asrtgt_d(long int a, long int b) {
__asrtgt_d(a, b);
__builtin_loongarch_asrtgt_d(a, b);
}

// CHECK-LABEL: @lddir_d(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.loongarch.lddir.d(i64 [[A:%.*]], i64 1)
// CHECK-NEXT: [[TMP1:%.*]] = tail call i64 @llvm.loongarch.lddir.d(i64 [[A]], i64 1)
// CHECK-NEXT: ret i64 0
//
long int lddir_d(long int a) {
long int b = __lddir_d(a, 1);
long int c = __builtin_loongarch_lddir_d(a, 1);
return 0;
}

// CHECK-LABEL: @ldpte_d(
// CHECK-NEXT: entry:
// CHECK-NEXT: tail call void @llvm.loongarch.ldpte.d(i64 [[A:%.*]], i64 1)
// CHECK-NEXT: tail call void @llvm.loongarch.ldpte.d(i64 [[A]], i64 1)
// CHECK-NEXT: ret void
//
void ldpte_d(long int a) {
__ldpte_d(a, 1);
__builtin_loongarch_ldpte_d(a, 1);
}

// CHECK-LABEL: @cpucfg(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.loongarch.cpucfg(i32 [[A:%.*]])
// CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @llvm.loongarch.cpucfg(i32 [[A]])
// CHECK-NEXT: ret i32 0
//
unsigned int cpucfg(unsigned int a) {
unsigned int b = __cpucfg(a);
unsigned int c = __builtin_loongarch_cpucfg(a);
return 0;
}
11 changes: 11 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsLoongArch.td
Expand Up @@ -102,4 +102,15 @@ def int_loongarch_iocsrwr_b : Intrinsic<[], [llvm_i32_ty, llvm_i32_ty]>;
def int_loongarch_iocsrwr_h : Intrinsic<[], [llvm_i32_ty, llvm_i32_ty]>;
def int_loongarch_iocsrwr_w : Intrinsic<[], [llvm_i32_ty, llvm_i32_ty]>;
def int_loongarch_iocsrwr_d : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty]>;

def int_loongarch_cpucfg : Intrinsic<[llvm_i32_ty], [llvm_i32_ty]>;

def int_loongarch_asrtle_d : Intrinsic<[], [llvm_i64_ty, llvm_i64_ty]>;
def int_loongarch_asrtgt_d : Intrinsic<[], [llvm_i64_ty, llvm_i64_ty]>;

def int_loongarch_lddir_d : Intrinsic<[llvm_i64_ty],
[llvm_i64_ty, llvm_i64_ty],
[ImmArg<ArgIndex<1>>]>;
def int_loongarch_ldpte_d : Intrinsic<[], [llvm_i64_ty, llvm_i64_ty],
[ImmArg<ArgIndex<1>>]>;
} // TargetPrefix = "loongarch"
59 changes: 59 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
Expand Up @@ -95,6 +95,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::CTLZ, MVT::i32, Custom);
setOperationAction(ISD::INTRINSIC_VOID, MVT::i32, Custom);
setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i32, Custom);
setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom);
setOperationAction(ISD::READ_REGISTER, MVT::i32, Custom);
setOperationAction(ISD::WRITE_REGISTER, MVT::i32, Custom);
if (Subtarget.hasBasicF() && !Subtarget.hasBasicD())
Expand Down Expand Up @@ -687,6 +688,22 @@ LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op,
IOCSRRD_CASE(iocsrrd_h, IOCSRRD_H);
IOCSRRD_CASE(iocsrrd_w, IOCSRRD_W);
#undef IOCSRRD_CASE
case Intrinsic::loongarch_cpucfg: {
return DAG.getMergeValues(
{DAG.getNode(LoongArchISD::CPUCFG, DL, GRLenVT, Op0, Op.getOperand(2)),
Op0},
DL);
}
case Intrinsic::loongarch_lddir_d: {
unsigned Imm = cast<ConstantSDNode>(Op.getOperand(3))->getZExtValue();
if (!isUInt<8>(Imm)) {
DAG.getContext()->emitError("argument to '" + Op->getOperationName(0) +
"' out of range");
return DAG.getMergeValues({DAG.getUNDEF(Op.getValueType()), Op0}, DL);
}

return Op;
}
}
}

Expand Down Expand Up @@ -769,6 +786,29 @@ SDValue LoongArchTargetLowering::lowerINTRINSIC_VOID(SDValue Op,
return Op.getOperand(0);
}
}
#define ASRT_LE_GT_CASE(NAME) \
case Intrinsic::loongarch_##NAME: { \
if (!Subtarget.is64Bit()) { \
DAG.getContext()->emitError(Op->getOperationName(0) + \
" requires target: loongarch64"); \
return Op.getOperand(0); \
} \
return Op; \
}
ASRT_LE_GT_CASE(asrtle_d)
ASRT_LE_GT_CASE(asrtgt_d)
#undef ASRT_LE_GT_CASE
case Intrinsic::loongarch_ldpte_d: {
unsigned Imm = cast<ConstantSDNode>(Op.getOperand(3))->getZExtValue();
if (!isUInt<8>(Imm))
return emitIntrinsicErrorMessage(Op, ErrorMsgOOR, DAG);
if (!Subtarget.is64Bit()) {
DAG.getContext()->emitError(Op->getOperationName(0) +
" requires target: loongarch64");
return Op.getOperand(0);
}
return Op;
}
}
}

Expand Down Expand Up @@ -1159,6 +1199,24 @@ void LoongArchTargetLowering::ReplaceNodeResults(
IOCSRRD_CASE(iocsrrd_h, IOCSRRD_H);
IOCSRRD_CASE(iocsrrd_w, IOCSRRD_W);
#undef IOCSRRD_CASE
case Intrinsic::loongarch_cpucfg: {
Results.push_back(DAG.getNode(
ISD::TRUNCATE, DL, VT,
DAG.getNode(LoongArchISD::CPUCFG, DL, GRLenVT, Op0,
DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2))));
Results.push_back(Op0);
break;
}
case Intrinsic::loongarch_lddir_d: {
if (!Subtarget.is64Bit()) {
DAG.getContext()->emitError(N->getOperationName(0) +
" requires target: loongarch64");
Results.push_back(DAG.getUNDEF(VT));
Results.push_back(Op0);
break;
}
break;
}
}
break;
}
Expand Down Expand Up @@ -1651,6 +1709,7 @@ const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const {
NODE_NAME_CASE(IOCSRWR_H)
NODE_NAME_CASE(IOCSRWR_W)
NODE_NAME_CASE(IOCSRWR_D)
NODE_NAME_CASE(CPUCFG)
}
#undef NODE_NAME_CASE
return nullptr;
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchISelLowering.h
Expand Up @@ -88,6 +88,9 @@ enum NodeType : unsigned {
IOCSRWR_H,
IOCSRWR_W,
IOCSRWR_D,

// Read CPU configuration information operation
CPUCFG,
};
} // end namespace LoongArchISD

Expand Down
14 changes: 13 additions & 1 deletion llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
Expand Up @@ -131,6 +131,8 @@ def loongarch_iocsrwr_w : SDNode<"LoongArchISD::IOCSRWR_W",
def loongarch_iocsrwr_d : SDNode<"LoongArchISD::IOCSRWR_D",
SDT_LoongArchIocsrwr,
[SDNPHasChain, SDNPSideEffect]>;
def loongarch_cpucfg : SDNode<"LoongArchISD::CPUCFG", SDTUnaryOp,
[SDNPHasChain, SDNPSideEffect]>;

//===----------------------------------------------------------------------===//
// Operand and SDNode transformation definitions.
Expand Down Expand Up @@ -194,7 +196,7 @@ def uimm6 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<6>(Imm);}]> {
let ParserMatchClass = UImmAsmOperand<6>;
}

def uimm8 : Operand<GRLenVT> {
def uimm8 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<8>(Imm);}]> {
let ParserMatchClass = UImmAsmOperand<8>;
}

Expand Down Expand Up @@ -1700,7 +1702,17 @@ def : Pat<(loongarch_iocsrwr_b GPR:$rd, GPR:$rj), (IOCSRWR_B GPR:$rd, GPR:$rj)>;
def : Pat<(loongarch_iocsrwr_h GPR:$rd, GPR:$rj), (IOCSRWR_H GPR:$rd, GPR:$rj)>;
def : Pat<(loongarch_iocsrwr_w GPR:$rd, GPR:$rj), (IOCSRWR_W GPR:$rd, GPR:$rj)>;

def : Pat<(loongarch_cpucfg GPR:$rj), (CPUCFG GPR:$rj)>;

let Predicates = [IsLA64] in {
def : Pat<(loongarch_iocsrrd_d GPR:$rj), (IOCSRRD_D GPR:$rj)>;
def : Pat<(loongarch_iocsrwr_d GPR:$rd, GPR:$rj), (IOCSRWR_D GPR:$rd, GPR:$rj)>;
def : Pat<(int_loongarch_asrtle_d GPR:$rj, GPR:$rk),
(ASRTLE_D GPR:$rj, GPR:$rk)>;
def : Pat<(int_loongarch_asrtgt_d GPR:$rj, GPR:$rk),
(ASRTGT_D GPR:$rj, GPR:$rk)>;
def : Pat<(int_loongarch_lddir_d GPR:$rj, timm:$imm8),
(LDDIR GPR:$rj, uimm8:$imm8)>;
def : Pat<(int_loongarch_ldpte_d GPR:$rj, timm:$imm8),
(LDPTE GPR:$rj, uimm8:$imm8)>;
} // Predicates = [IsLA64]

0 comments on commit aeb8f91

Please sign in to comment.