Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions llvm/lib/Target/RISCV/RISCVCallingConv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -486,14 +486,6 @@ bool llvm::CC_RISCV(unsigned ValNo, MVT ValVT, MVT LocVT,
}
}

// Cheriot uses GPCR without a bitcast when possible.
if (LocVT == MVT::f64 && Subtarget.hasVendorXCheriot() && !IsPureCapVarArgs) {
if (MCRegister Reg = State.AllocateReg(ArgGPCRs)) {
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
return false;
}
}

// FP smaller than XLen, uses custom GPR.
if (LocVT == MVT::f16 || LocVT == MVT::bf16 ||
(LocVT == MVT::f32 && XLen == 64)) {
Expand Down
58 changes: 3 additions & 55 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,6 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
addRegisterClass(CapType, &RISCV::GPCRRegClass);
}

if (Subtarget.hasVendorXCheriot()) {
// Cheriot holds f64's in capability registers.
addRegisterClass(MVT::f64, &RISCV::GPCRRegClass);
}

static const MVT::SimpleValueType BoolVecVTs[] = {
MVT::nxv1i1, MVT::nxv2i1, MVT::nxv4i1, MVT::nxv8i1,
MVT::nxv16i1, MVT::nxv32i1, MVT::nxv64i1};
Expand Down Expand Up @@ -685,20 +680,6 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setLibcallName(RTLIB::MEMSET, "memset");
}

if (Subtarget.hasVendorXCheriot()) {
setOperationAction(ISD::ConstantFP, MVT::f64, Custom);

static const unsigned CheriotF64ExpandOps[] = {
ISD::FMINNUM, ISD::FMAXNUM, ISD::FADD, ISD::FSUB,
ISD::FMUL, ISD::FMA, ISD::FDIV, ISD::FSQRT,
ISD::FCEIL, ISD::FTRUNC, ISD::FFLOOR, ISD::FROUND,
ISD::FROUNDEVEN, ISD::FRINT, ISD::FNEARBYINT, ISD::IS_FPCLASS,
ISD::SETCC, ISD::FMAXIMUM, ISD::FMINIMUM, ISD::STRICT_FADD,
ISD::STRICT_FSUB, ISD::STRICT_FMUL, ISD::STRICT_FDIV, ISD::STRICT_FSQRT,
ISD::STRICT_FMA};
setOperationAction(CheriotF64ExpandOps, MVT::f64, Expand);
}

// TODO: On M-mode only targets, the cycle[h]/time[h] CSR may not be present.
// Unfortunately this can't be determined just from the ISA naming string.
setOperationAction(ISD::READCYCLECOUNTER, MVT::i64,
Expand Down Expand Up @@ -6164,44 +6145,11 @@ static SDValue lowerConstant(SDValue Op, SelectionDAG &DAG,
return SDValue();
}

SDValue
RISCVTargetLowering::lowerConstantFP(SDValue Op, SelectionDAG &DAG,
const RISCVSubtarget &Subtarget) const {
SDValue RISCVTargetLowering::lowerConstantFP(SDValue Op,
SelectionDAG &DAG) const {
MVT VT = Op.getSimpleValueType();
const APFloat &Imm = cast<ConstantFPSDNode>(Op)->getValueAPF();

if (Subtarget.hasVendorXCheriot()) {
// Cheriot needs to custom lower f64 immediates using csethigh
if (VT != MVT::f64)
return Op;

SDLoc DL(Op);
uint64_t Val = Imm.bitcastToAPInt().getLimitedValue();

// Materialize 0.0 as cnull
if (Val == 0)
return DAG.getRegister(getNullCapabilityRegister(), MVT::f64);

// Otherwise, materialize the low part into a 32-bit register.
auto Lo = DAG.getConstant(Val & 0xFFFFFFFF, DL, MVT::i32);
auto LoAsCap = DAG.getTargetInsertSubreg(RISCV::sub_cap_addr, DL, MVT::c64,
DAG.getUNDEF(MVT::f64), Lo);

// The high half of a capability register is zeroed by integer ops,
// so if we wanted a zero high half then we are done.
if (Val >> 32 == 0)
return DAG.getBitcast(MVT::f64, LoAsCap);

// Otherwise, materialize the high half and use csethigh to combine the two
// halve.
auto Hi = DAG.getConstant(Val >> 32, DL, MVT::i32);
auto Cap = DAG.getNode(
ISD::INTRINSIC_WO_CHAIN, DL, MVT::c64,
DAG.getTargetConstant(Intrinsic::cheri_cap_high_set, DL, MVT::i32),
LoAsCap, Hi);
return DAG.getBitcast(MVT::f64, Cap);
}

// Can this constant be selected by a Zfa FLI instruction?
bool Negate = false;
int Index = getLegalZfaFPImm(Imm, VT);
Expand Down Expand Up @@ -6851,7 +6799,7 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
case ISD::Constant:
return lowerConstant(Op, DAG, Subtarget);
case ISD::ConstantFP:
return lowerConstantFP(Op, DAG, Subtarget);
return lowerConstantFP(Op, DAG);
case ISD::SELECT:
return lowerSELECT(Op, DAG);
case ISD::BRCOND:
Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/Target/RISCV/RISCVISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -981,8 +981,7 @@ class RISCVTargetLowering : public TargetLowering {
SelectionDAG &DAG) const;
SDValue getTLSDescAddr(GlobalAddressSDNode *N, SelectionDAG &DAG) const;

SDValue lowerConstantFP(SDValue Op, SelectionDAG &DAG,
const RISCVSubtarget &Subtarget) const;
SDValue lowerConstantFP(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
Expand Down
115 changes: 46 additions & 69 deletions llvm/lib/Target/RISCV/RISCVInstrInfoXCheri.td
Original file line number Diff line number Diff line change
Expand Up @@ -1451,7 +1451,7 @@ def : PatGpcrUimm12<int_cheri_bounded_stack_cap, CSetBoundsImm>;
def : PatGpcrGpr<int_cheri_bounded_stack_cap_dynamic, CSetBounds>;
def : PatGpcrUimm12<int_cheri_bounded_stack_cap_dynamic, CSetBoundsImm>;

def : Pat<(CapFrameAddrRegImm(cPTR GPCR:$rs1), simm12:$imm12),
def : Pat<(CapFrameAddrRegImm GPCR:$rs1, simm12:$imm12),
(CIncOffsetImm GPCR:$rs1, simm12:$imm12)>;

/// Pointer-Arithmetic Instructions
Expand All @@ -1463,15 +1463,14 @@ def : Pat<(XLenVT (int_cheri_cap_diff GPCR:$cs1, GPCR:$cs2)),
(XLenVT (EXTRACT_SUBREG GPCR:$cs2, sub_cap_addr)))>;

let Predicates = [IsPureCapABI] in {
def : Pat<(inttoptr(XLenVT GPR:$rs2)), (cPTR(CIncOffset(cPTR C0), GPR:$rs2))>;
def : Pat<(inttoptr simm12:$imm12), (cPTR(CIncOffsetImm(cPTR C0),
simm12:$imm12))>;
def : Pat<(XLenVT(ptrtoint(cPTR GPCR:$rs1))), (PseudoCGetAddr GPCR:$rs1)>;
def : Pat<(inttoptr (XLenVT GPR:$rs2)), (CIncOffset C0, GPR:$rs2)>;
def : Pat<(inttoptr simm12:$imm12), (CIncOffsetImm C0, simm12:$imm12)>;
def : Pat<(XLenVT (ptrtoint GPCR:$rs1)), (PseudoCGetAddr GPCR:$rs1)>;
}

/// Null Capability Patterns

def : Pat<(inttoptr(XLenVT 0)), (CLenVT(COPY(cPTR C0)))>;
def : Pat<(inttoptr (XLenVT 0)), (CLenVT (COPY C0))>;
def : Pat<(ptrtoint (CLenVT (inttoptr (XLenVT 0)))),
(XLenVT (COPY (XLenVT X0)))>;

Expand All @@ -1482,31 +1481,26 @@ def : Pat<(ptrtoint (CLenVT (inttoptr (XLenVT 0)))),
// * Break untagged < tagged semantics
// * Can't implement exact equality
class CheriSetCCPatGpcrGpcr<PatFrag CondOp, dag GprGprDag>
: Pat<(XLenVT(CondOp(cPTR GPCR:$cs1), (cPTR GPCR:$cs2))),
(OutPatFrag<(ops node:$rs1, node:$rs2), GprGprDag>(XLenVT
(EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr)),
(XLenVT(EXTRACT_SUBREG GPCR:$cs2, sub_cap_addr)))>;
: Pat<(XLenVT (CondOp GPCR:$cs1, GPCR:$cs2)),
(OutPatFrag<(ops node:$rs1, node:$rs2), GprGprDag>
(XLenVT (EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr)),
(XLenVT (EXTRACT_SUBREG GPCR:$cs2, sub_cap_addr)))>;

multiclass CheriSetCCPatGpcrImm<PatFrag CondOp, Operand ImmTy, dag GprImmDag> {
def : Pat<(XLenVT(CondOp(cPTR GPCR:$cs1), (inttoptr ImmTy:$imm12))),
(OutPatFrag<(ops node:$rs1, node:$imm12), GprImmDag>(XLenVT
(EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr)),
ImmTy:$imm12)>;
def : Pat<(XLenVT(CondOp(cPTR GPCR:$cs1), (cptradd(inttoptr(XLenVT 0)),
ImmTy:$imm12))),
(OutPatFrag<(ops node:$rs1, node:$imm12), GprImmDag>(XLenVT
(EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr)),
ImmTy:$imm12)>;
def : Pat<(XLenVT(CondOp(cPTR GPCR:$cs1),
(int_cheri_cap_offset_set(inttoptr(XLenVT 0)), ImmTy:$imm12))),
(OutPatFrag<(ops node:$rs1, node:$imm12), GprImmDag>(XLenVT
(EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr)),
ImmTy:$imm12)>;
def : Pat<(XLenVT(CondOp(cPTR GPCR:$cs1),
(int_cheri_cap_address_set(inttoptr(XLenVT 0)), ImmTy:$imm12))),
(OutPatFrag<(ops node:$rs1, node:$imm12), GprImmDag>(XLenVT
(EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr)),
ImmTy:$imm12)>;
def : Pat<(XLenVT (CondOp GPCR:$cs1, (inttoptr ImmTy:$imm12))),
(OutPatFrag<(ops node:$rs1, node:$imm12), GprImmDag>
(XLenVT (EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr)), ImmTy:$imm12)>;
def : Pat<(XLenVT (CondOp GPCR:$cs1, (cptradd (inttoptr (XLenVT 0)), ImmTy:$imm12))),
(OutPatFrag<(ops node:$rs1, node:$imm12), GprImmDag>
(XLenVT (EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr)), ImmTy:$imm12)>;
def : Pat<(XLenVT (CondOp GPCR:$cs1,
(int_cheri_cap_offset_set (inttoptr (XLenVT 0)), ImmTy:$imm12))),
(OutPatFrag<(ops node:$rs1, node:$imm12), GprImmDag>
(XLenVT (EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr)), ImmTy:$imm12)>;
def : Pat<(XLenVT (CondOp GPCR:$cs1,
(int_cheri_cap_address_set (inttoptr (XLenVT 0)), ImmTy:$imm12))),
(OutPatFrag<(ops node:$rs1, node:$imm12), GprImmDag>
(XLenVT (EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr)), ImmTy:$imm12)>;
}

multiclass CheriSetCCPatGpcrSimm12<PatFrag CondOp, dag GprImmDag>
Expand All @@ -1516,9 +1510,9 @@ multiclass CheriSetCCPatGpcrSimm12Plus1<PatFrag CondOp, dag GprImmDag>
: CheriSetCCPatGpcrImm<CondOp, simm12_plus1, GprImmDag>;

class CheriSetCCPatGpcrNull<PatFrag CondOp, dag GprDag>
: Pat<(XLenVT(CondOp(cPTR GPCR:$cs1), (inttoptr(XLenVT 0)))),
(OutPatFrag<(ops node:$rs1), GprDag>(XLenVT(EXTRACT_SUBREG GPCR:$cs1,
sub_cap_addr)))>;
: Pat<(XLenVT (CondOp GPCR:$cs1, (inttoptr (XLenVT 0)))),
(OutPatFrag<(ops node:$rs1), GprDag>
(XLenVT (EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr)))>;

class Swap<PatFrag BinFrag>
: PatFrag<(ops node:$a, node:$b), (BinFrag $b, $a)>;
Expand Down Expand Up @@ -1561,10 +1555,11 @@ defm Select_GPCR : SelectCC_GPR_rrirr<GPCR, CLenVT>;
// No dedicated instructions; see above

class CheriBccPat<PatFrag CondOp, RVInstB Inst>
: Pat<(brcond(XLenVT(CondOp(cPTR GPCR:$rs1), (cPTR GPCR:$rs2))), bb:$imm12),
(Inst(XLenVT(EXTRACT_SUBREG GPCR:$rs1, sub_cap_addr)),
(XLenVT(EXTRACT_SUBREG GPCR:$rs2, sub_cap_addr)),
simm13_lsb0:$imm12)>;
: Pat<(brcond (XLenVT (CondOp GPCR:$rs1, GPCR:$rs2)), bb:$imm12),
(Inst
(XLenVT (EXTRACT_SUBREG GPCR:$rs1, sub_cap_addr)),
(XLenVT (EXTRACT_SUBREG GPCR:$rs2, sub_cap_addr)),
simm13_lsb0:$imm12)>;

def : CheriBccPat<seteq, BEQ>;
def : CheriBccPat<setne, BNE>;
Expand All @@ -1574,10 +1569,11 @@ def : CheriBccPat<setult, BLTU>;
def : CheriBccPat<setuge, BGEU>;

class CheriBccSwapPat<PatFrag CondOp, RVInst InstBcc>
: Pat<(brcond(XLenVT(CondOp(cPTR GPCR:$rs1), (cPTR GPCR:$rs2))), bb:$imm12),
(InstBcc(XLenVT(EXTRACT_SUBREG GPCR:$rs2, sub_cap_addr)),
(XLenVT(EXTRACT_SUBREG GPCR:$rs1, sub_cap_addr)),
simm13_lsb0:$imm12)>;
: Pat<(brcond (XLenVT (CondOp GPCR:$rs1, GPCR:$rs2)), bb:$imm12),
(InstBcc
(XLenVT (EXTRACT_SUBREG GPCR:$rs2, sub_cap_addr)),
(XLenVT (EXTRACT_SUBREG GPCR:$rs1, sub_cap_addr)),
simm13_lsb0:$imm12)>;

def : CheriBccSwapPat<setgt, BLT>;
def : CheriBccSwapPat<setle, BGE>;
Expand All @@ -1591,18 +1587,15 @@ def : PatGpcrGpcr<riscv_cap_equal_exact, CSEQX, XLenVT>;

/// Special Capability Register Access Instructions

def : Pat<(int_cheri_ddc_get), (CSpecialRW SCR_DDC.Encoding, (cPTR C0))>;
let Predicates = [HasCheri,
IsPureCapABI] in def : Pat<(int_cheri_stack_cap_get),
(CLenVT(COPY(cPTR C2)))>;
def : Pat<(int_cheri_ddc_get), (CSpecialRW SCR_DDC.Encoding, C0)>;
let Predicates = [HasCheri, IsPureCapABI] in
def : Pat<(int_cheri_stack_cap_get), (CLenVT (COPY C2))>;

let Predicates = [HasCheri, IsCapMode] in
def : Pat<(int_cheri_pcc_get), (AUIPCC 0)>;

let Predicates = [HasCheri,
NotCapMode] in def : Pat<(int_cheri_pcc_get),
(CSpecialRW SCR_PCC.Encoding,
(cPTR C0))>;
let Predicates = [HasCheri, NotCapMode] in
def : Pat<(int_cheri_pcc_get), (CSpecialRW SCR_PCC.Encoding, C0)>;

/// Fast Register-Clearing Instructions

Expand Down Expand Up @@ -1831,14 +1824,13 @@ defm : PseudoCmpXchgPat<"atomic_cmp_swap_cap", PseudoCmpXchgCap, CLenVT, GPCR>;
/// Capability Mode Instructions

multiclass CheriLdPat<PatFrag LoadOp, RVInst Inst, ValueType ReturnVt = XLenVT> {
def : Pat<(ReturnVt(LoadOp(CapRegImm(cPTR GPCR:$rs1), simm12:$imm12))),
def : Pat<(ReturnVt (LoadOp (CapRegImm GPCR:$rs1, simm12:$imm12))),
(Inst GPCR:$rs1, simm12:$imm12)>;
}

multiclass CheriStPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy, ValueType StoreVt = XLenVT> {
def : Pat<(StoreOp(StoreVt StTy:$rs2), (CapRegImm(cPTR GPCR:$rs1),
simm12:$imm12)),
(Inst(StoreVt StTy:$rs2), GPCR:$rs1, simm12:$imm12)>;
def : Pat<(StoreOp (StoreVt StTy:$rs2), (CapRegImm GPCR:$rs1, simm12:$imm12)),
(Inst (StoreVt StTy:$rs2), GPCR:$rs1, simm12:$imm12)>;
}

multiclass CheriAtomicStPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy, ValueType StoreVt>
Expand Down Expand Up @@ -2295,11 +2287,6 @@ defm : CheriLdPat<load, CLC_128, CLenVT>;
defm : CheriStPat<store, CSC_128, GPCR, CLenVT>;
} // Predicates = [HasCheri, IsRV64, IsCapMode]

let Predicates = [HasCheri, HasCheriot, IsRV32, IsCapMode] in {
defm : CheriLdPat<load, CLC_64, f64>;
defm : CheriStPat<store, CSC_64, GPCR, f64>;
} // Predicates = [HasCheri, HasCheriot, IsRV32, IsCapMode]

//===----------------------------------------------------------------------===//
// Compress Instruction tablegen backend.
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -2442,17 +2429,7 @@ let Predicates = [HasCheri, IsRV32, IsCapMode, IsRVE] in {
let mayLoad = true, mayStore = false, hasSideEffects = false in
def PseudoCLLW : Pseudo<(outs GPCR:$dst), (ins bare_symbol:$src), [],
"cllc", "$dst, $src">;
def : Pat<(c64(load(cPTR(load(iPTR globaladdr:$src))))),
(PseudoCLLW bare_symbol:$src)>;
def : Pat<(f64(load(cPTR(load(iPTR globaladdr:$src))))),
def : Pat<(load (cPTR (load (iPTR globaladdr:$src)))),
(PseudoCLLW bare_symbol:$src)>;
} // Predicates = [HasCheri, IsRV32, IsCapMode, IsRVE]

// Cheriot stores f64 in cap registers, so bitcasting between f64 and c64
// is a no-op.
multiclass NopCapRegCast<ValueType Ty1, ValueType Ty2> {
def : Pat<(Ty1(bitconvert(Ty2 GPCR:$Val))), (Ty1 GPCR:$Val)>;
def : Pat<(Ty2(bitconvert(Ty1 GPCR:$Val))), (Ty2 GPCR:$Val)>;
}

let Predicates = [HasCheri, HasCheriot] in { defm : NopCapRegCast<c64, f64>; }

Loading