Index: llvm/include/llvm/IR/IntrinsicsAArch64.td =================================================================== --- llvm/include/llvm/IR/IntrinsicsAArch64.td +++ llvm/include/llvm/IR/IntrinsicsAArch64.td @@ -2662,4 +2662,17 @@ def int_aarch64_sme_cntsh : AdvSIMD_SME_CNTSB_Intrinsic; def int_aarch64_sme_cntsw : AdvSIMD_SME_CNTSB_Intrinsic; def int_aarch64_sme_cntsd : AdvSIMD_SME_CNTSB_Intrinsic; + + // + // PSTATE Functions + // + + def int_aarch64_sme_get_pstatesm : DefaultAttrsIntrinsic<[llvm_i1_ty], []>; + + def int_aarch64_sme_get_tpidr2 + : DefaultAttrsIntrinsic<[llvm_i64_ty], [], + [IntrNoMem, IntrHasSideEffects]>; + def int_aarch64_sme_set_tpidr2 + : DefaultAttrsIntrinsic<[], [llvm_i64_ty], + [IntrNoMem, IntrHasSideEffects]>; } Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -19282,6 +19282,17 @@ return DAG.getMergeValues( {A, DAG.getZExtOrTrunc(B, DL, MVT::i1), A.getValue(2)}, DL); } + case Intrinsic::aarch64_sme_get_pstatesm: { + SDLoc DL(N); + SDValue Chain = N->getOperand(0); + auto Register = AArch64SysReg::SVCR; + SDValue MRS = DAG.getNode(AArch64ISD::MRS, DL, MVT::i64, Chain, + DAG.getConstant(Register, DL, MVT::i64)); + SDValue Mask = DAG.getConstant(/* PSTATE.SM */ 1, DL, MVT::i64); + SDValue And = DAG.getNode(ISD::AND, DL, MVT::i64, MRS, Mask); + SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, And); + return DAG.getMergeValues({Trunc, Chain}, DL); + } default: break; } Index: llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td =================================================================== --- llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td +++ llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td @@ -138,6 +138,12 @@ def : InstAlias<"smstop sm", (MSRpstatesvcrImm1 0b001, 0b0)>; def : InstAlias<"smstop za", (MSRpstatesvcrImm1 0b010, 0b0)>; +// Read and write TPIDR2_EL0 +def : Pat<(int_aarch64_sme_set_tpidr2 i64:$val), + (MSR 0xde85, GPR64:$val)>; +def : Pat<(i64 (int_aarch64_sme_get_tpidr2)), + (MRS 0xde85)>; + //===----------------------------------------------------------------------===// // SVE2 instructions //===----------------------------------------------------------------------===// Index: llvm/test/CodeGen/AArch64/sme-get-pstatesm.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/sme-get-pstatesm.ll @@ -0,0 +1,14 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sme -verify-machineinstrs < %s | FileCheck %s + +define i1 @is_streaming() { +; CHECK-LABEL: is_streaming: +; CHECK: // %bb.0: +; CHECK-NEXT: mrs x8, SVCR +; CHECK-NEXT: and w0, w8, #0x1 +; CHECK-NEXT: ret + %pstate = call i1 @llvm.aarch64.sme.get.pstatesm() + ret i1 %pstate +} + +declare i1 @llvm.aarch64.sme.get.pstatesm() Index: llvm/test/CodeGen/AArch64/sme-read-write-tpidr2.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/sme-read-write-tpidr2.ll @@ -0,0 +1,23 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=aarch64 -mattr=+sme < %s | FileCheck %s + +define i64 @get_tpidr2_el0() { +; CHECK-LABEL: get_tpidr2_el0: +; CHECK: // %bb.0: +; CHECK-NEXT: mrs x0, TPIDR2_EL0 +; CHECK-NEXT: ret + %res = call i64 @llvm.aarch64.sme.get.tpidr2() + ret i64 %res +} + +define void @set_tpidr2_el0(i64 %v) { +; CHECK-LABEL: set_tpidr2_el0: +; CHECK: // %bb.0: +; CHECK-NEXT: msr TPIDR2_EL0, x0 +; CHECK-NEXT: ret + call void @llvm.aarch64.sme.set.tpidr2(i64 %v) + ret void +} + +declare i64 @llvm.aarch64.sme.get.tpidr2() +declare void @llvm.aarch64.sme.set.tpidr2(i64 %v)