diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td index 5fdb01a548bbb..a7fc6f20134d3 100644 --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -1390,6 +1390,10 @@ def HasCheriot : Predicate<"Subtarget->hasVendorXCheriot()">, AssemblerPredicate<(all_of FeatureVendorXCheriot), "CHERIoT Extension">; +def HasNoCheriot : Predicate<"!Subtarget->hasVendorXCheriot()">, + AssemblerPredicate<(all_of(not FeatureVendorXCheriot)), + "CHERIoT Extension">; + def FeatureRelax : SubtargetFeature<"relax", "EnableLinkerRelax", "true", "Enable Linker relaxation.">; diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 74981d853c124..9b06ef6befd61 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -10067,6 +10067,25 @@ SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, // Expand CFromPtr since the dedicated instruction has been removed. return emitCFromPtrReplacement(DAG, DL, Op.getOperand(1), Op.getOperand(2), Op.getValueType(), XLenVT); + + case Intrinsic::cheri_cap_offset_get: { + if (!Subtarget.hasVendorXCheriot()) + return {}; + + // cheri_cap_offset_get is not directly implemented on Cheriot, so expand + // it to (sub (address_get), (base_get)). We lower this during operation + // legalization for that the subtraction has an opportunity to be + // optimized by DAGCombine. + auto Cap = Op->getOperand(1); + auto Addr = DAG.getNode( + ISD::INTRINSIC_WO_CHAIN, DL, XLenVT, + DAG.getConstant(llvm::Intrinsic::cheri_cap_address_get, DL, XLenVT), + Cap); + auto Base = DAG.getNode( + ISD::INTRINSIC_WO_CHAIN, DL, XLenVT, + DAG.getConstant(llvm::Intrinsic::cheri_cap_base_get, DL, XLenVT), Cap); + return DAG.getNode(ISD::SUB, DL, XLenVT, Addr, Base); + } case Intrinsic::cheri_cap_to_pointer: // Expand CToPtr since the dedicated instruction has been removed. // NB: DDC/PCC relocation has been removed, so we no longer subtract the diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXCheri.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXCheri.td index 587bebdf55fac..17ef8e5526a8e 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoXCheri.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXCheri.td @@ -378,7 +378,6 @@ def CGetLen : Cheri_r<0x3, "cgetlen">; let mayLoad = true in def CGetTag : Cheri_r<0x4, "cgettag">; def CGetSealed : Cheri_r<0x5, "cgetsealed">; -def CGetOffset : Cheri_r<0x6, "cgetoffset">; def CGetFlags : Cheri_r<0x7, "cgetflags">; def CGetHigh : Cheri_r<0x17, "cgethigh">; def CGetTop : Cheri_r<0x18, "cgettop">; @@ -389,6 +388,10 @@ def PseudoCGetAddr : Pseudo<(outs GPR:$rd), (ins GPCR:$cs1), [], "cgetaddr", "$rd, $cs1">; } +let Predicates = [HasCheri, HasNoCheriot] in { + def CGetOffset : Cheri_r<0x6, "cgetoffset">; +} + let Predicates = [HasCheriot] in { def : InstAlias<"ct.cgetperm $rd, $rs1", (CGetPerm GPR:$rd, GPCR:$rs1)>; def : InstAlias<"ct.cgettype $rd, $rs1", (CGetType GPR:$rd, GPCR:$rs1)>; @@ -1408,7 +1411,8 @@ def : PatGpcr; def : PatGpcr; def : PatGpcr; def : PatGpcr; -def : PatGpcr; +let Predicates = [HasNoCheriot] in def : PatGpcr; def : PatGpcr; def : Pat<(XLenVT (int_cheri_cap_address_get GPCR:$cs1)), (PseudoCGetAddr GPCR:$cs1)>; def : PatGpcr; diff --git a/llvm/test/CodeGen/RISCV/cheri/cheriot-offset-get.ll b/llvm/test/CodeGen/RISCV/cheri/cheriot-offset-get.ll new file mode 100644 index 0000000000000..6452ec234c875 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/cheri/cheriot-offset-get.ll @@ -0,0 +1,14 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=riscv32cheriot --mcpu=cheriot -target-abi=cheriot -mattr=+xcheri,+cap-mode,+xcheriot -o - %s | FileCheck %s + +define i32 @test1(i8 addrspace(200)* %cap) nounwind { +; CHECK-LABEL: test1: +; CHECK: # %bb.0: +; CHECK-NEXT: ct.cgetbase a1, ca0 +; CHECK-NEXT: sub a0, a0, a1 +; CHECK-NEXT: ct.cret + %newcap = call i32 @llvm.cheri.cap.offset.get.i32(i8 addrspace(200)* %cap) + ret i32 %newcap +} + +declare i32 @llvm.cheri.cap.offset.get.i32(i8 addrspace(200)*)