From 4fa6c515f3d7d2287b13feec72458c34826d2a08 Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Sat, 10 Feb 2024 02:38:10 +0000 Subject: [PATCH] [CodeGen] Rework MVT representation of capabilities and add type inference This more closely aligns how capabilites are handled with iPTR and iN types, introducing a new cPTR wildcard and fixed-width cN types that it maps to, with iPTRAny being iPTR and cPTR. As a result we no longer need to duplicate patterns for each fixed-width type in certain cases, and the few upstream MIPS tests we've long marked as XFAIL'ed now pass. As part of this, a few of the APIs around MVTs have been renamed from fat pointer terminology to use capability instead. Where relatively straightforward to do these have then been adopted throughout, but some are pervasive and have deprecated aliases under the old names, whose uses should be incrementally reduced. --- llvm/include/llvm/CodeGen/TargetLowering.h | 6 +- llvm/include/llvm/CodeGen/ValueTypes.h | 12 +- llvm/include/llvm/CodeGen/ValueTypes.td | 11 +- llvm/include/llvm/IR/Intrinsics.td | 6 +- llvm/include/llvm/IR/IntrinsicsCHERICap.td | 92 +++---- llvm/include/llvm/IR/IntrinsicsMips.td | 16 +- llvm/include/llvm/Support/MachineValueType.h | 65 ++--- llvm/include/llvm/Target/Target.td | 3 +- .../include/llvm/Target/TargetSelectionDAG.td | 18 +- .../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 31 ++- llvm/lib/CodeGen/TargetLoweringBase.cpp | 5 - llvm/lib/CodeGen/ValueTypes.cpp | 18 +- llvm/lib/IR/Function.cpp | 14 -- llvm/lib/Target/Mips/Mips.td | 3 - llvm/lib/Target/Mips/MipsCallingConv.td | 16 +- llvm/lib/Target/Mips/MipsISelLowering.cpp | 6 +- llvm/lib/Target/Mips/MipsInstrCheri.td | 208 +++++++--------- llvm/lib/Target/Mips/MipsRegisterInfo.td | 2 +- llvm/lib/Target/Mips/MipsSubtarget.h | 3 +- .../RISCV/RISCVExpandAtomicPseudoInsts.cpp | 8 +- llvm/lib/Target/RISCV/RISCVInstrInfo.td | 9 +- llvm/lib/Target/RISCV/RISCVInstrInfoXCheri.td | 83 ++----- llvm/lib/Target/RISCV/RISCVRegisterInfo.td | 2 +- llvm/lib/Target/RISCV/RISCVSubtarget.h | 2 +- llvm/test/CodeGen/Mips/cconv/vector.ll | 2 - llvm/test/CodeGen/Mips/cheri/call-c13-null.ll | 10 +- .../test/CodeGen/Mips/msa/basic_operations.ll | 3 - llvm/test/CodeGen/Mips/msa/cc_without_nan.ll | 6 - llvm/test/CodeGen/Mips/msa/elm_copy.ll | 1 - llvm/test/CodeGen/Mips/msa/elm_insv.ll | 1 - llvm/test/CodeGen/Mips/msa/immediates.ll | 6 - .../RISCV/cheri/unaligned-fp-load-store.ll | 2 +- llvm/utils/TableGen/CodeGenDAGPatterns.cpp | 233 ++++++++++-------- llvm/utils/TableGen/CodeGenDAGPatterns.h | 8 +- llvm/utils/TableGen/CodeGenTarget.cpp | 18 +- llvm/utils/TableGen/DAGISelMatcher.cpp | 16 +- llvm/utils/TableGen/DAGISelMatcherOpt.cpp | 6 +- llvm/utils/TableGen/GlobalISelEmitter.cpp | 4 +- llvm/utils/TableGen/IntrinsicEmitter.cpp | 33 +-- 39 files changed, 469 insertions(+), 519 deletions(-) diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index f429919703f0..b1f4fc3b979c 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -367,7 +367,7 @@ class TargetLoweringBase { uint32_t AS) const { #endif if (DL.isFatPointer(AS)) - return MVT::getFatPointerVT(DL.getPointerSizeInBits(AS)); + return MVT::getCapabilityVT(DL.getPointerSizeInBits(AS)); return MVT::getIntegerVT(DL.getPointerSizeInBits(AS)); } @@ -382,7 +382,7 @@ class TargetLoweringBase { uint32_t AS) const { #endif if (DL.isFatPointer(AS)) - return MVT::getFatPointerVT(DL.getPointerSizeInBits(AS)); + return MVT::getCapabilityVT(DL.getPointerSizeInBits(AS)); return MVT::getIntegerVT(DL.getPointerSizeInBits(AS)); } @@ -3477,7 +3477,7 @@ class TargetLoweringBase { bool EnableExtLdPromotion; /// The type to use for CHERI capabilities (if supported) - /// Should be one of iFATPTR64/128/256 + /// Should be one of c64/c128/c256 MVT CapType = MVT(); /// Whether the CHERI capability type supports precise bounds for any diff --git a/llvm/include/llvm/CodeGen/ValueTypes.h b/llvm/include/llvm/CodeGen/ValueTypes.h index c3d75c83d49e..895baf089bb9 100644 --- a/llvm/include/llvm/CodeGen/ValueTypes.h +++ b/llvm/include/llvm/CodeGen/ValueTypes.h @@ -144,11 +144,15 @@ namespace llvm { return isSimple() ? V.isInteger() : isExtendedInteger(); } - /// Return true if this is a fat pointer type. - bool isFatPointer() const { - return isSimple() ? V.isFatPointer() : false; + /// Return true if this is a capability type. + bool isCapability() const { + // TODO: isExtendedCapability? + return isSimple() ? V.isCapability() : false; } + /// Return true if this is a capability type. Deprecated. + bool isFatPointer() const { return isCapability(); } + /// Return true if this is an integer, but not a vector. bool isScalarInteger() const { return isSimple() ? V.isScalarInteger() : isExtendedScalarInteger(); @@ -213,7 +217,7 @@ namespace llvm { /// Return true if this is an overloaded type for TableGen. bool isOverloaded() const { return (V == MVT::iAny || V == MVT::fAny || V == MVT::vAny || - V == MVT::iPTRAny || V == MVT::iFATPTRAny); + V == MVT::iPTRAny); } /// Return true if the bit size is a multiple of 8. diff --git a/llvm/include/llvm/CodeGen/ValueTypes.td b/llvm/include/llvm/CodeGen/ValueTypes.td index c053e2eea9e9..b8f0a5e95494 100644 --- a/llvm/include/llvm/CodeGen/ValueTypes.td +++ b/llvm/include/llvm/CodeGen/ValueTypes.td @@ -226,11 +226,12 @@ def externref : ValueType<0, 182>; // WebAssembly's externref type def x86amx : ValueType<8192, 183>; // X86 AMX value def i64x8 : ValueType<512, 184>; // 8 Consecutive GPRs (AArch64) -def iFATPTR64 : ValueType<64, !add(i64x8.Value, 1)>; // 64-bit fat pointer. -def iFATPTR128: ValueType<128, !add(iFATPTR64.Value, 1)>; // 128-bit fat pointer. -def iFATPTR256: ValueType<256, !add(iFATPTR128.Value, 1)>; // 256-bit fat pointer. -def iFATPTR512: ValueType<512, !add(iFATPTR256.Value, 1)>; // 512-bit fat pointer. -def iFATPTRAny: ValueType<0, !add(iFATPTR512.Value, 1)>; // Any fat pointer. +def c64 : ValueType<64, !add(i64x8.Value, 1)>; // 64-bit capability value +def c128 : ValueType<128, !add(c64.Value, 1)>; // 128-bit capability value +def c256 : ValueType<256, !add(c128.Value, 1)>; // 256-bit capability value + +// Pseudo valuetype mapped to the current capability pointer size. +def cPTR : ValueType<0, 247>; def token : ValueType<0, 248>; // TokenTy def MetadataVT : ValueType<0, 249>; // Metadata diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index 3a8c00b0bf36..6a6917f1d59f 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -187,8 +187,8 @@ class LLVMAnyPointerType let isAny = true; } -class LLVMFatPointerType - : LLVMType{ +class LLVMCapabilityType + : LLVMType{ LLVMType ElTy = elty; } @@ -261,7 +261,7 @@ def llvm_ppcf128_ty : LLVMType; def llvm_ptr_ty : LLVMPointerType; // i8* def llvm_ptrptr_ty : LLVMPointerType; // i8** def llvm_anyptr_ty : LLVMAnyPointerType; // (space)i8* -def llvm_fatptr_ty : LLVMFatPointerType; // (space)i8* +def llvm_cap_ty : LLVMCapabilityType; // (space)i8* def llvm_anyptrptr_ty : LLVMAnyPointerType; // i8*(space)* def llvm_empty_ty : LLVMType; // { } def llvm_descriptor_ty : LLVMPointerType; // { }* diff --git a/llvm/include/llvm/IR/IntrinsicsCHERICap.td b/llvm/include/llvm/IR/IntrinsicsCHERICap.td index d0b40851a318..192930be40ae 100644 --- a/llvm/include/llvm/IR/IntrinsicsCHERICap.td +++ b/llvm/include/llvm/IR/IntrinsicsCHERICap.td @@ -14,150 +14,150 @@ def int_cheri_cap_length_get : Intrinsic<[llvm_anyint_ty], - [llvm_fatptr_ty], + [llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_base_get : Intrinsic<[llvm_anyint_ty], - [llvm_fatptr_ty], + [llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_perms_and : - Intrinsic<[llvm_fatptr_ty], - [llvm_fatptr_ty, llvm_anyint_ty], + Intrinsic<[llvm_cap_ty], + [llvm_cap_ty, llvm_anyint_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_perms_get : Intrinsic<[llvm_anyint_ty], - [llvm_fatptr_ty], + [llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_flags_set : - Intrinsic<[llvm_fatptr_ty], - [llvm_fatptr_ty, llvm_anyint_ty], + Intrinsic<[llvm_cap_ty], + [llvm_cap_ty, llvm_anyint_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_flags_get : Intrinsic<[llvm_anyint_ty], - [llvm_fatptr_ty], + [llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_high_set : - Intrinsic<[llvm_fatptr_ty], - [llvm_fatptr_ty, llvm_anyint_ty], + Intrinsic<[llvm_cap_ty], + [llvm_cap_ty, llvm_anyint_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_high_get : Intrinsic<[llvm_anyint_ty], - [llvm_fatptr_ty], + [llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_bounds_set : - Intrinsic<[llvm_fatptr_ty], - [llvm_fatptr_ty, llvm_anyint_ty], + Intrinsic<[llvm_cap_ty], + [llvm_cap_ty, llvm_anyint_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_bounds_set_exact : - Intrinsic<[llvm_fatptr_ty], - [llvm_fatptr_ty, llvm_anyint_ty], + Intrinsic<[llvm_cap_ty], + [llvm_cap_ty, llvm_anyint_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_type_get : Intrinsic<[llvm_anyint_ty], - [llvm_fatptr_ty], + [llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_tag_get : ClangBuiltin<"__builtin_cheri_tag_get">, Intrinsic<[llvm_i1_ty], - [llvm_fatptr_ty], + [llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_sealed_get : ClangBuiltin<"__builtin_cheri_sealed_get">, Intrinsic<[llvm_i1_ty], - [llvm_fatptr_ty], + [llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_tag_clear : ClangBuiltin<"__builtin_cheri_tag_clear">, - Intrinsic<[llvm_fatptr_ty], - [llvm_fatptr_ty], + Intrinsic<[llvm_cap_ty], + [llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_seal : ClangBuiltin<"__builtin_cheri_seal">, - Intrinsic<[llvm_fatptr_ty], - [llvm_fatptr_ty, llvm_fatptr_ty], + Intrinsic<[llvm_cap_ty], + [llvm_cap_ty, llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_conditional_seal : ClangBuiltin<"__builtin_cheri_conditional_seal">, - Intrinsic<[llvm_fatptr_ty], - [llvm_fatptr_ty, llvm_fatptr_ty], + Intrinsic<[llvm_cap_ty], + [llvm_cap_ty, llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_unseal : ClangBuiltin<"__builtin_cheri_unseal">, - Intrinsic<[llvm_fatptr_ty], - [llvm_fatptr_ty, llvm_fatptr_ty], + Intrinsic<[llvm_cap_ty], + [llvm_cap_ty, llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_seal_entry: ClangBuiltin<"__builtin_cheri_seal_entry">, - Intrinsic<[llvm_fatptr_ty], [llvm_fatptr_ty], + Intrinsic<[llvm_cap_ty], [llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_perms_check : - Intrinsic<[], [llvm_fatptr_ty, llvm_anyint_ty], + Intrinsic<[], [llvm_cap_ty, llvm_anyint_ty], [IntrNoMem, IntrHasSideEffects, IntrWillReturn]>; def int_cheri_cap_type_check : ClangBuiltin<"__builtin_cheri_type_check">, - Intrinsic<[], [llvm_fatptr_ty, llvm_fatptr_ty], + Intrinsic<[], [llvm_cap_ty, llvm_cap_ty], [IntrNoMem, IntrHasSideEffects, IntrWillReturn]>; def int_cheri_cap_subset_test: ClangBuiltin<"__builtin_cheri_subset_test">, - Intrinsic<[llvm_i1_ty], [llvm_fatptr_ty, llvm_fatptr_ty], [IntrNoMem, IntrWillReturn]>; + Intrinsic<[llvm_i1_ty], [llvm_cap_ty, llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_equal_exact: ClangBuiltin<"__builtin_cheri_equal_exact">, - Intrinsic<[llvm_i1_ty], [llvm_fatptr_ty, llvm_fatptr_ty], [IntrNoMem, IntrWillReturn]>; + Intrinsic<[llvm_i1_ty], [llvm_cap_ty, llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_stack_cap_get : ClangBuiltin<"__builtin_cheri_stack_get">, - Intrinsic<[llvm_fatptr_ty], [], [IntrNoMem, IntrWillReturn]>; + Intrinsic<[llvm_cap_ty], [], [IntrNoMem, IntrWillReturn]>; def int_cheri_ddc_get : ClangBuiltin<"__builtin_cheri_global_data_get">, - Intrinsic<[llvm_fatptr_ty], [], [IntrNoMem, IntrWillReturn]>; + Intrinsic<[llvm_cap_ty], [], [IntrNoMem, IntrWillReturn]>; def int_cheri_pcc_get : ClangBuiltin<"__builtin_cheri_program_counter_get">, - Intrinsic<[llvm_fatptr_ty], [], [IntrNoMem, IntrWillReturn]>; + Intrinsic<[llvm_cap_ty], [], [IntrNoMem, IntrWillReturn]>; //////////////////////////////////////////////////////////////////////////////// // Offset-related intrinsics //////////////////////////////////////////////////////////////////////////////// def int_cheri_cap_offset_set: - Intrinsic<[llvm_fatptr_ty], [llvm_fatptr_ty, llvm_anyint_ty], [IntrNoMem, IntrWillReturn]>; + Intrinsic<[llvm_cap_ty], [llvm_cap_ty, llvm_anyint_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_offset_get: - Intrinsic<[llvm_anyint_ty], [llvm_fatptr_ty], [IntrNoMem, IntrWillReturn]>; + Intrinsic<[llvm_anyint_ty], [llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_diff: - Intrinsic<[llvm_anyint_ty], [llvm_fatptr_ty,llvm_fatptr_ty], [IntrNoMem, IntrWillReturn]>; + Intrinsic<[llvm_anyint_ty], [llvm_cap_ty,llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; //////////////////////////////////////////////////////////////////////////////// // Pointer / capability interoperation intrinsics //////////////////////////////////////////////////////////////////////////////// def int_cheri_cap_address_get: - Intrinsic<[llvm_anyint_ty], [llvm_fatptr_ty], [IntrNoMem, IntrWillReturn]>; + Intrinsic<[llvm_anyint_ty], [llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_address_set: - Intrinsic<[llvm_fatptr_ty], [llvm_fatptr_ty, llvm_anyint_ty], [IntrNoMem, IntrWillReturn]>; + Intrinsic<[llvm_cap_ty], [llvm_cap_ty, llvm_anyint_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_to_pointer: - Intrinsic<[llvm_anyint_ty], [llvm_fatptr_ty, llvm_fatptr_ty], [IntrNoMem, IntrWillReturn]>; + Intrinsic<[llvm_anyint_ty], [llvm_cap_ty, llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_from_pointer: - Intrinsic<[llvm_fatptr_ty], [llvm_fatptr_ty, llvm_anyint_ty], [IntrNoMem, IntrWillReturn]>; + Intrinsic<[llvm_cap_ty], [llvm_cap_ty, llvm_anyint_ty], [IntrNoMem, IntrWillReturn]>; //////////////////////////////////////////////////////////////////////////////// // Building capabilities from untagged data //////////////////////////////////////////////////////////////////////////////// def int_cheri_cap_build: ClangBuiltin<"__builtin_cheri_cap_build">, - Intrinsic<[llvm_fatptr_ty], [llvm_fatptr_ty, llvm_fatptr_ty], [IntrNoMem, IntrWillReturn]>; + Intrinsic<[llvm_cap_ty], [llvm_cap_ty, llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_cap_type_copy: ClangBuiltin<"__builtin_cheri_cap_type_copy">, - Intrinsic<[llvm_fatptr_ty], [llvm_fatptr_ty, llvm_fatptr_ty], [IntrNoMem, IntrWillReturn]>; + Intrinsic<[llvm_cap_ty], [llvm_cap_ty, llvm_cap_ty], [IntrNoMem, IntrWillReturn]>; //////////////////////////////////////////////////////////////////////////////// // Tag memory accessor functions //////////////////////////////////////////////////////////////////////////////// def int_cheri_cap_load_tags: - Intrinsic<[llvm_anyint_ty], [llvm_fatptr_ty], [IntrReadMem]>; + Intrinsic<[llvm_anyint_ty], [llvm_cap_ty], [IntrReadMem]>; /// Round length to compressed capability precision: def int_cheri_round_representable_length : @@ -177,6 +177,6 @@ def int_cheri_representable_alignment_mask : /// NB: They *only* has this additional meaning at the IR level; at the DAG and /// MIR levels they cannot be assumed safe like at the IR level. def int_cheri_bounded_stack_cap : - Intrinsic<[llvm_fatptr_ty], [llvm_fatptr_ty, llvm_anyint_ty], [IntrNoMem, IntrWillReturn]>; + Intrinsic<[llvm_cap_ty], [llvm_cap_ty, llvm_anyint_ty], [IntrNoMem, IntrWillReturn]>; def int_cheri_bounded_stack_cap_dynamic : - Intrinsic<[llvm_fatptr_ty], [llvm_fatptr_ty, llvm_anyint_ty], [IntrNoMem, IntrWillReturn]>; + Intrinsic<[llvm_cap_ty], [llvm_cap_ty, llvm_anyint_ty], [IntrNoMem, IntrWillReturn]>; diff --git a/llvm/include/llvm/IR/IntrinsicsMips.td b/llvm/include/llvm/IR/IntrinsicsMips.td index 0c04fe48adb6..234bca2cf89a 100644 --- a/llvm/include/llvm/IR/IntrinsicsMips.td +++ b/llvm/include/llvm/IR/IntrinsicsMips.td @@ -1792,33 +1792,33 @@ def int_mips_cap_cause_set : Intrinsic<[], [llvm_i64_ty], []>; def int_mips_captable_get : ClangBuiltin<"__builtin_mips_cheri_get_captable">, - Intrinsic<[llvm_fatptr_ty], [], [IntrNoMem]>; + Intrinsic<[llvm_cap_ty], [], [IntrNoMem]>; def int_mips_idc_get : GCCBuiltinAlias<"__builtin_mips_cheri_get_invoke_data_cap">, ClangBuiltin<"__builtin_mips_cheri_invoke_data_cap_get">, - Intrinsic<[llvm_fatptr_ty], [], [IntrNoMem]>; + Intrinsic<[llvm_cap_ty], [], [IntrNoMem]>; def int_mips_kr1c_get : GCCBuiltinAlias<"__builtin_mips_cheri_get_kernel_cap1">, ClangBuiltin<"__builtin_mips_cheri_kernel_cap1_get">, - Intrinsic<[llvm_fatptr_ty], [], [IntrNoMem]>; + Intrinsic<[llvm_cap_ty], [], [IntrNoMem]>; def int_mips_kr2c_get : GCCBuiltinAlias<"__builtin_mips_cheri_get_kernel_cap2">, ClangBuiltin<"__builtin_mips_cheri_kernel_cap2_get">, - Intrinsic<[llvm_fatptr_ty], [], [IntrNoMem]>; + Intrinsic<[llvm_cap_ty], [], [IntrNoMem]>; def int_mips_kcc_get : GCCBuiltinAlias<"__builtin_mips_cheri_get_kernel_code_cap">, ClangBuiltin<"__builtin_mips_cheri_kernel_code_cap_get">, - Intrinsic<[llvm_fatptr_ty], [], [IntrNoMem]>; + Intrinsic<[llvm_cap_ty], [], [IntrNoMem]>; def int_mips_kdc_get : GCCBuiltinAlias<"__builtin_mips_cheri_get_kernel_data_cap">, ClangBuiltin<"__builtin_mips_cheri_kernel_data_cap_get">, - Intrinsic<[llvm_fatptr_ty], [], [IntrNoMem]>; + Intrinsic<[llvm_cap_ty], [], [IntrNoMem]>; def int_mips_epcc_get : GCCBuiltinAlias<"__builtin_mips_cheri_get_exception_program_counter_cap">, ClangBuiltin<"__builtin_mips_cheri_exception_program_counter_cap_get">, - Intrinsic<[llvm_fatptr_ty], [], [IntrNoMem]>; + Intrinsic<[llvm_cap_ty], [], [IntrNoMem]>; def int_mips_stack_to_cap : - Intrinsic<[llvm_fatptr_ty], [llvm_fatptr_ty], [IntrNoMem]>; + Intrinsic<[llvm_cap_ty], [llvm_cap_ty], [IntrNoMem]>; } diff --git a/llvm/include/llvm/Support/MachineValueType.h b/llvm/include/llvm/Support/MachineValueType.h index c93b2de8cada..be8964a9b9c0 100644 --- a/llvm/include/llvm/Support/MachineValueType.h +++ b/llvm/include/llvm/Support/MachineValueType.h @@ -280,17 +280,15 @@ namespace llvm { x86amx = 183, // This is an X86 AMX value i64x8 = 184, // 8 Consecutive GPRs (AArch64) - iFATPTR64 = i64x8 + 1, // 64-bit fat pointer type - iFATPTR128 = iFATPTR64 + 1, // 128-bit fat pointer type - iFATPTR256 = iFATPTR128 + 1, // 256-bit fat pointer type - iFATPTR512 = iFATPTR256 + 1, // 512-bit fat pointer type - iFATPTRAny = iFATPTR512 + 1, // Generic fat pointer type (must be - // legalised to a sized version) - FIRST_FAT_POINTER = iFATPTR64, - LAST_FAT_POINTER = iFATPTRAny, + c64 = i64x8 + 1, // This is a 64 bit capability value + c128 = c64 + 1, // This is a 128 bit capability value + c256 = c128 + 1, // This is a 256 bit capability value + + FIRST_CAPABILITY_VALUETYPE = c64, + LAST_CAPABILITY_VALUETYPE = c256, FIRST_VALUETYPE = 1, // This is always the beginning of the list. - LAST_VALUETYPE = iFATPTRAny, // This always remains at the end of the list. + LAST_VALUETYPE = c256, // This always remains at the end of the list. VALUETYPE_SIZE = LAST_VALUETYPE + 1, // This is the current maximum for LAST_VALUETYPE. @@ -298,15 +296,20 @@ namespace llvm { // This value must be a multiple of 32. MAX_ALLOWED_VALUETYPE = 192, + // A capability value the size of the capability pointer of the current + // target. This should only be used internal to tblgen! + cPTR = 247, + // A value of type llvm::TokenTy token = 248, // This is MDNode or MDString. Metadata = 249, - // An int value the size of the pointer of the current - // target to any address space. This must only be used internal to - // tblgen. Other than for overloading, we treat iPTRAny the same as iPTR. + // An int or capability value the size of the int or capability pointer + // of the current target to any address space. This must only be used + // internal to tblgen. Other than for overloading, we treat iPTRAny the + // same as iPTR and/or cPTR. iPTRAny = 250, // A vector with any length and element size. This is used @@ -373,12 +376,15 @@ namespace llvm { SimpleTy <= MVT::LAST_INTEGER_SCALABLE_VECTOR_VALUETYPE)); } - /// Return true if this is a fat pointer type. - bool isFatPointer() const { - return (SimpleTy >= MVT::FIRST_FAT_POINTER) && - (SimpleTy <= MVT::LAST_FAT_POINTER); + /// Return true if this is a capability type. + bool isCapability() const { + return (SimpleTy >= MVT::FIRST_CAPABILITY_VALUETYPE) && + (SimpleTy <= MVT::LAST_CAPABILITY_VALUETYPE); } + /// Return true if this is a capability type. Deprecated. + bool isFatPointer() const { return isCapability(); } + /// Return true if this is an integer, not including vectors. bool isScalarInteger() const { return (SimpleTy >= MVT::FIRST_INTEGER_VALUETYPE && @@ -475,7 +481,7 @@ namespace llvm { bool isOverloaded() const { return (SimpleTy == MVT::Any || SimpleTy == MVT::iAny || SimpleTy == MVT::fAny || SimpleTy == MVT::vAny || - SimpleTy == MVT::iPTRAny || SimpleTy == MVT::iFATPTRAny); + SimpleTy == MVT::iPTRAny); } /// Return a vector with the same number of elements as this vector, but @@ -902,12 +908,8 @@ namespace llvm { case Other: llvm_unreachable("Value type is non-standard value, Other."); case iPTR: + case cPTR: llvm_unreachable("Value type size is target-dependent. Ask TLI."); - case iFATPTR64: return TypeSize::Fixed(64); - case iFATPTR128: return TypeSize::Fixed(128); - case iFATPTR256: return TypeSize::Fixed(256); - case iFATPTR512: return TypeSize::Fixed(512); - case iFATPTRAny: case iPTRAny: case iAny: case fAny: @@ -967,6 +969,7 @@ namespace llvm { case x86mmx: case f64 : case i64 : + case c64: case v64i1: case v8i8: case v4i16: @@ -991,6 +994,7 @@ namespace llvm { case f128: case ppcf128: case i128: + case c128: case v128i1: case v16i8: case v8i16: @@ -1017,6 +1021,7 @@ namespace llvm { case v3f64: return TypeSize::Fixed(192); case v7i32: case v7f32: return TypeSize::Fixed(224); + case c256: case v256i1: case v128i2: case v64i4: @@ -1233,18 +1238,16 @@ namespace llvm { } } - static MVT getFatPointerVT(unsigned BitWidth) { + static MVT getCapabilityVT(unsigned BitWidth) { switch (BitWidth) { default: return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); case 64: - return MVT::iFATPTR64; + return MVT::c64; case 128: - return MVT::iFATPTR128; + return MVT::c128; case 256: - return MVT::iFATPTR256; - case 512: - return MVT::iFATPTR512; + return MVT::c256; } } @@ -1499,6 +1502,12 @@ namespace llvm { force_iteration_on_noniterable_enum); } + static auto capability_valuetypes() { + return enum_seq_inclusive(MVT::FIRST_CAPABILITY_VALUETYPE, + MVT::LAST_CAPABILITY_VALUETYPE, + force_iteration_on_noniterable_enum); + } + static auto fp_valuetypes() { return enum_seq_inclusive(MVT::FIRST_FP_VALUETYPE, MVT::LAST_FP_VALUETYPE, force_iteration_on_noniterable_enum); diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td index 9551b2072ca0..187eaf39f763 100644 --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -800,8 +800,9 @@ def encoder; /// derived from this. TableGen treats the register class as having a symbolic /// type that it doesn't know, and resolves the actual regclass to use by using /// the TargetRegisterInfo::getPointerRegClass() hook at codegen time. -class PointerLikeRegClass { +class PointerLikeRegClass { int RegClassKind = Kind; + ValueType RegClassType = Type; } diff --git a/llvm/include/llvm/Target/TargetSelectionDAG.td b/llvm/include/llvm/Target/TargetSelectionDAG.td index 21de4bbd5668..e358487246dc 100644 --- a/llvm/include/llvm/Target/TargetSelectionDAG.td +++ b/llvm/include/llvm/Target/TargetSelectionDAG.td @@ -109,7 +109,7 @@ def SDTOther : SDTypeProfile<1, 0, [SDTCisVT<0, OtherVT>]>; // for 'vt'. def SDTUNDEF : SDTypeProfile<1, 0, []>; // for 'undef'. def SDTUnaryOp : SDTypeProfile<1, 1, []>; // for bitconvert. -def SDTFatPtrAddOp : SDTypeProfile<1, 2, [ +def SDTPtrAddOp : SDTypeProfile<1, 2, [ SDTCisSameAs<0, 1>, SDTCisPtrTy<0>, SDTCisInt<2> ]>; @@ -471,7 +471,7 @@ def trunc : SDNode<"ISD::TRUNCATE" , SDTIntTruncOp>; def bitconvert : SDNode<"ISD::BITCAST" , SDTUnaryOp>; def inttoptr : SDNode<"ISD::INTTOPTR" , SDTUnaryOp>; def ptrtoint : SDNode<"ISD::PTRTOINT" , SDTUnaryOp>; -def ptradd : SDNode<"ISD::PTRADD" , SDTFatPtrAddOp>; +def ptradd : SDNode<"ISD::PTRADD" , SDTPtrAddOp>; def addrspacecast : SDNode<"ISD::ADDRSPACECAST", SDTUnaryOp>; def extractelt : SDNode<"ISD::EXTRACT_VECTOR_ELT", SDTVecExtract>; def insertelt : SDNode<"ISD::INSERT_VECTOR_ELT", SDTVecInsert>; @@ -1875,14 +1875,14 @@ def trunc_masked_scatter_i32 : MSN->getMemoryVT().getScalarType() == MVT::i32; }]>; -// We can't use let MemoryVT = iFATPTRAny here since by the time it runs we -// have turned it into an iFATPTR128, etc -> use the C++ predicate below. We -// also can't set IsAtomic, since that requires MemoryVT, but that only -// influences the auto-generated code predicate, and ours should suffice. +// We can't use let MemoryVT = cPTR here since by the time it runs we have +// turned it into a c128, etc -> use the C++ predicate below. We also can't +// set IsAtomic, since that requires MemoryVT, but that only influences the +// auto-generated code predicate, and ours should suffice. multiclass binary_atomic_op_cap { def "" : PatFrag<(ops node:$ptr, node:$val), (atomic_op node:$ptr, node:$val), [{ - return cast(N)->getMemoryVT().isFatPointer(); + return cast(N)->getMemoryVT().isCapability(); }]>; defm NAME : binary_atomic_op_ord; @@ -1891,7 +1891,7 @@ multiclass binary_atomic_op_cap { multiclass ternary_atomic_op_cap { def "" : PatFrag<(ops node:$ptr, node:$cmp, node:$val), (atomic_op node:$ptr, node:$cmp, node:$val), [{ - return cast(N)->getMemoryVT().isFatPointer(); + return cast(N)->getMemoryVT().isCapability(); }]>; defm NAME : ternary_atomic_op_ord; @@ -1915,7 +1915,7 @@ defm atomic_cmp_swap_cap : ternary_atomic_op_cap; def atomic_load_cap : PatFrag<(ops node:$ptr), (atomic_load_cap_node node:$ptr), [{ - return cast(N)->getMemoryVT().isFatPointer(); + return cast(N)->getMemoryVT().isCapability(); }]>; //===----------------------------------------------------------------------===// diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 350532e85da4..3fece3548605 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -2571,7 +2571,15 @@ CheckType(const unsigned char *MatcherTable, unsigned &MatcherIndex, SDValue N, if (N.getValueType() == VT) return true; // Handle the case when VT is iPTR. - return VT == MVT::iPTR && N.getValueType() == TLI->getPointerTy(DL, 0); + if (VT == MVT::iPTR && N.getValueType() == TLI->getPointerTy(DL, 0)) + return true; + + // Handle the case when VT is cPTR. + // XXX: Hard-coded AS + if (VT == MVT::cPTR && N.getValueType() == TLI->getPointerTy(DL, 200)) + return true; + + return false; } LLVM_ATTRIBUTE_ALWAYS_INLINE static bool @@ -2607,8 +2615,17 @@ CheckValueType(const unsigned char *MatcherTable, unsigned &MatcherIndex, return true; // Handle the case when VT is iPTR. - return VT == MVT::iPTR && - cast(N)->getVT() == TLI->getPointerTy(DL, 0); + if (VT == MVT::iPTR && + cast(N)->getVT() == TLI->getPointerTy(DL, 0)) + return true; + + // Handle the case when VT is cPTR. + // XXX: Hard-coded AS + if (VT == MVT::cPTR && + cast(N)->getVT() == TLI->getPointerTy(DL, 200)) + return true; + + return false; } // Bit 0 stores the sign of the immediate. The upper bits contain the magnitude @@ -3203,6 +3220,9 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch, // FIXME: is AS0 correct here? if (CaseVT == MVT::iPTR) CaseVT = TLI->getPointerTy(CurDAG->getDataLayout(), 0); + else if (CaseVT == MVT::cPTR) + // XXX: Hard-coded AS + CaseVT = TLI->getPointerTy(CurDAG->getDataLayout(), 200); // If the VT matches, then we will execute this case. if (CurNodeVT == CaseVT) @@ -3486,6 +3506,9 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch, // FIXME: is AS0 correct here? This is what it was before if (VT == MVT::iPTR) VT = TLI->getPointerTy(CurDAG->getDataLayout(), 0).SimpleTy; + else if (VT == MVT::cPTR) + // XXX: Hard-coded AS + VT = TLI->getPointerTy(CurDAG->getDataLayout(), 200).SimpleTy; VTs.push_back(VT); } @@ -3662,7 +3685,9 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch, "Invalid number of results to complete!"); assert((NodeToMatch->getValueType(i) == Res.getValueType() || NodeToMatch->getValueType(i) == MVT::iPTR || + NodeToMatch->getValueType(i) == MVT::cPTR || Res.getValueType() == MVT::iPTR || + Res.getValueType() == MVT::cPTR || NodeToMatch->getValueType(i).getSizeInBits() == Res.getValueSizeInBits()) && "invalid replacement"); diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp index 89a7564241da..3c35ac1fe29e 100644 --- a/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -1854,11 +1854,6 @@ TargetLoweringBase::getTypeLegalizationCost(const DataLayout &DL, // the only operation that costs anything is the split. After splitting // we need to handle two types. while (true) { - if (MTy == MVT::iFATPTRAny) { - auto T = MTy.getTypeForEVT(C); - MTy = MVT::getFatPointerVT( - DL.getPointerSizeInBits(T->getPointerAddressSpace())); - } assert(!MTy.isOverloaded()); LegalizeKind LK = getTypeConversion(C, MTy); diff --git a/llvm/lib/CodeGen/ValueTypes.cpp b/llvm/lib/CodeGen/ValueTypes.cpp index 1e50f2b021e4..0524003a1882 100644 --- a/llvm/lib/CodeGen/ValueTypes.cpp +++ b/llvm/lib/CodeGen/ValueTypes.cpp @@ -159,14 +159,11 @@ std::string EVT::getEVTString() const { getVectorElementType().getEVTString(); if (isInteger()) return "i" + utostr(getSizeInBits()); + if (isCapability()) + return "c" + utostr(getSizeInBits()); if (isFloatingPoint()) return "f" + utostr(getSizeInBits()); llvm_unreachable("Invalid EVT!"); - case MVT::iFATPTR64: return "iFATPTR64"; - case MVT::iFATPTR128: return "iFATPTR128"; - case MVT::iFATPTR256: return "iFATPTR256"; - case MVT::iFATPTR512: return "iFATPTR512"; - case MVT::iFATPTRAny: return "iFATPTRAny"; case MVT::bf16: return "bf16"; case MVT::ppcf128: return "ppcf128"; case MVT::isVoid: return "isVoid"; @@ -537,11 +534,10 @@ Type *EVT::getTypeForEVT(LLVMContext &Context) const { case MVT::nxv8f64: return ScalableVectorType::get(Type::getDoubleTy(Context), 8); case MVT::Metadata: return Type::getMetadataTy(Context); - case MVT::iFATPTR64: - case MVT::iFATPTR128: - case MVT::iFATPTR256: - case MVT::iFATPTR512: - case MVT::iFATPTRAny: + case MVT::c64: + case MVT::c128: + case MVT::c256: + // XXX: Hard-coded AS return PointerType::get(Type::getInt8Ty(Context), 200); } // clang-format on @@ -571,7 +567,7 @@ MVT MVT::getVT(Type *Ty, bool HandleUnknown){ case Type::PointerTyID: { // FIXME: require a DataLayout here! if (isCheriPointer(Ty, nullptr)) - return MVT(MVT::iFATPTRAny); + return MVT(MVT::cPTR); return MVT(MVT::iPTR); } case Type::FixedVectorTyID: diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index d3942ca53f4c..d3074ff84033 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -1007,11 +1007,6 @@ enum IIT_Info { IIT_ANYPTR_TO_ELT = 56, IIT_I2 = 57, IIT_I4 = 58, - IIT_IFATPTR64 = IIT_I4 + 1, - IIT_IFATPTR128 = IIT_IFATPTR64 + 1, - IIT_IFATPTR256 = IIT_IFATPTR128 + 1, - IIT_IFATPTR512 = IIT_IFATPTR256 + 1, - IIT_IFATPTRAny = IIT_IFATPTR512 + 1, }; static void DecodeIITType(unsigned &NextElt, ArrayRef Infos, @@ -1151,15 +1146,6 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef Infos, DecodeIITType(NextElt, Infos, Info, OutputTable); return; } - case IIT_IFATPTR64: - case IIT_IFATPTR128: - case IIT_IFATPTR256: - case IIT_IFATPTR512: - case IIT_IFATPTRAny: { - OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 200)); - DecodeIITType(++NextElt, Infos, Info, OutputTable); - return; - } case IIT_ARG: { unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); OutputTable.push_back(IITDescriptor::get(IITDescriptor::Argument, ArgInfo)); diff --git a/llvm/lib/Target/Mips/Mips.td b/llvm/lib/Target/Mips/Mips.td index 7e80343aa66b..6752e60ac193 100644 --- a/llvm/lib/Target/Mips/Mips.td +++ b/llvm/lib/Target/Mips/Mips.td @@ -8,9 +8,6 @@ // This is the top level entry point for the Mips target. //===----------------------------------------------------------------------===// -// Ugly hack to notify TableGen that we support fat pointers -class SupportsFatPointers; - //===----------------------------------------------------------------------===// // Target-independent interfaces //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/Mips/MipsCallingConv.td b/llvm/lib/Target/Mips/MipsCallingConv.td index bce6752905a0..fd9659956b31 100644 --- a/llvm/lib/Target/Mips/MipsCallingConv.td +++ b/llvm/lib/Target/Mips/MipsCallingConv.td @@ -169,12 +169,12 @@ def CC_MipsN : CallingConv<[ // All stack parameter slots become 64-bit doublewords and are 8-byte aligned. CCIfType<[f32], CCAssignToStack<4, 8>>, CCIfType<[i64, f64], CCAssignToStack<8, 8>>, - CCIfType<[iFATPTR64, iFATPTR128, iFATPTR256, iFATPTR512], CCAssignToReg<[C3, C4, C5, C6, C7, C8, C9, C10]>>, - CCIfType<[iFATPTR64, iFATPTR128, iFATPTR256, iFATPTR512], CCDelegateTo> + CCIfType<[c64, c128, c256], CCAssignToReg<[C3, C4, C5, C6, C7, C8, C9, C10]>>, + CCIfType<[c64, c128, c256], CCDelegateTo> ]>; def CC_CHERI_CCall : CallingConv<[ - CCIfType<[iFATPTR64, iFATPTR128, iFATPTR256, iFATPTR512], CCAssignToReg<[C1, C2, C3, C4, C5, C6, C7, C8, C9, C10]>>, + CCIfType<[c64, c128, c256], CCAssignToReg<[C1, C2, C3, C4, C5, C6, C7, C8, C9, C10]>>, CCIfType<[i64], CCAssignToReg<[V0_64]>>, CCDelegateTo ]>; @@ -198,7 +198,7 @@ def CC_MipsN_VarArg : CallingConv<[ CCIfType<[f32], CCAssignToStack<4, 8>>, CCIfType<[i64, f64], CCAssignToStack<8, 8>>, // All capability arguments are passed on the stack: - CCIfType<[iFATPTR64, iFATPTR128, iFATPTR256, iFATPTR512], CCDelegateTo> + CCIfType<[c64, c128, c256], CCDelegateTo> ]>; // In purecap mode, all variadic arguments are passed on the stack. @@ -208,7 +208,7 @@ def CC_MipsCheriPureCap_VarArg : CallingConv<[ // All stack parameter slots become 64-bit doublewords and are 8-byte aligned. CCIfType<[f32], CCAssignToStack<4, 8>>, CCIfType<[i64, f64], CCAssignToStack<8, 8>>, - CCIfType<[iFATPTR64, iFATPTR128, iFATPTR256, iFATPTR512], CCDelegateTo> + CCIfType<[c64, c128, c256], CCDelegateTo> ]>; def RetCC_MipsN : CallingConv<[ @@ -242,7 +242,7 @@ def RetCC_MipsN : CallingConv<[ // f64 are returned in registers D0, D2 CCIfType<[f64], CCAssignToReg<[D0_64, D2_64]>>, // Capabilities are returned in C3, C4 - CCIfType<[iFATPTR64, iFATPTR128, iFATPTR256, iFATPTR512], CCAssignToReg<[C3, C4]>> + CCIfType<[c64, c128, c256], CCAssignToReg<[C3, C4]>> ]>; //===----------------------------------------------------------------------===// @@ -285,9 +285,9 @@ def CC_MipsN_FastCC : CallingConv<[ // 8-byte aligned. CCIfType<[i64, f64], CCAssignToStack<8, 8>>, - CCIfType<[iFATPTR64, iFATPTR128, iFATPTR256, iFATPTR512], CCAssignToReg<[C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, + CCIfType<[c64, c128, c256], CCAssignToReg<[C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C13, C14, C15, C16]>>, - CCIfType<[iFATPTR64, iFATPTR128, iFATPTR256, iFATPTR512], CCDelegateTo> + CCIfType<[c64, c128, c256], CCDelegateTo> ]>; def CC_Mips_FastCC : CallingConv<[ diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index 439472564d42..e5a4e6a0d427 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -1272,7 +1272,7 @@ performCIncOffsetToCandAddrCombine(SDNode *N, SelectionDAG &DAG, // t6: i64 = llvm.cheri.cap.address.get TargetConstant:i64<9>, t4 // t8: i64 = and t6, Constant:i64<16383> // t10: i64 = sub nsw Constant:i64<0>, t8 - // t11: iFATPTR128 = PTRADD t4, t10 + // t11: c128 = PTRADD t4, t10 // This can be folded to a CAndAddr with the inverted mask (i.e. XOR -1, // mask). @@ -2668,8 +2668,8 @@ SDValue MipsTargetLowering::lowerADDRSPACECAST(SDValue Op, SelectionDAG &DAG) if (Src.getValueType() == Op.getValueType()) return Src; if (ABI.IsCheriPureCap()) { - // XXXAR: HACK for the capability table (we turn this into an iFATPTR later - // so we can just return the value + // XXXAR: HACK for the capability table (we turn this into a capability + // later so we can just return the value) if (isa(Src)) { return Op; } diff --git a/llvm/lib/Target/Mips/MipsInstrCheri.td b/llvm/lib/Target/Mips/MipsInstrCheri.td index ae2ba9306a48..7680b0c2f13c 100644 --- a/llvm/lib/Target/Mips/MipsInstrCheri.td +++ b/llvm/lib/Target/Mips/MipsInstrCheri.td @@ -443,9 +443,8 @@ def CCSeal : CheriFmt3Op<0x1f, (outs CheriOpnd:$r1), (ins CheriOpnd:$r2, CheriOp def CTestSubset : CheriFmt3Op<0x20, (outs GPR64Opnd:$r1), (ins CheriOpnd0IsDDC:$r2, CheriOpnd:$r3), "ctestsubset\t$r1, $r2, $r3", [(set GPR64Opnd: $r1, (CapSubsetTest CheriOpnd0IsDDC: $r2, CheriOpnd: $r3))]>; -// Note: we need to duplicate these patterns for iFATPTR128,256, etc. for some reason multiclass UseCNullPatterns { - def : Pat<(ptradd NullPat, (i64 0)), (COPY CNULL)>; + def : Pat<(ptradd NullPat, (i64 0)), (CapRegType (COPY CNULL))>; def : Pat<(ptradd NullPat, GPR64Opnd:$addr), (CIncOffset CNULL, $addr)>; def : Pat<(int_cheri_cap_offset_set NullPat, GPR64Opnd:$addr), (CIncOffset CNULL, $addr)>; def : Pat<(int_cheri_cap_address_set NullPat, GPR64Opnd:$addr), (CSetAddr CNULL, $addr)>; @@ -455,10 +454,7 @@ multiclass UseCNullPatterns { def : Pat<(int_cheri_cap_address_set NullPat, simm11s0Pattern:$imm), (CIncOffsetImm CNULL, simm11s0Pattern:$imm)>; } } -defm : UseCNullPatterns<(iFATPTR64 (inttoptr (i64 0)))>; -defm : UseCNullPatterns<(iFATPTR128 (inttoptr (i64 0)))>; -defm : UseCNullPatterns<(iFATPTR256 (inttoptr (i64 0)))>; -defm : UseCNullPatterns<(CapRegType (inttoptr (i64 0)))>; +defm : UseCNullPatterns<(inttoptr (i64 0))>; // Cursors @@ -939,88 +935,76 @@ def CSCB : CheriFmtCSC<0, (outs GPR32Opnd:$rd), (ins GPR32Opnd: $rs, CheriOpnd0 "cscb\t$rd, $rs, $cb">; } -def AddrFI64 : ComplexPattern; -def AddrFI128 : ComplexPattern; -def AddrFI256 : ComplexPattern; +def CapFI : ComplexPattern; // Load and store patterns for frame indices // FIXME: truncstore/extload nodes are not being used? -// These patterns need duplicating for each of the capability sizes. It's not -// clear why: we should be able to pattern match a ComplexPattern with an -// overloaded return type, but that appears to be broken. -multiclass FrameIndexStorePatterns { - def : Pat<(storeOp intTy:$rs, (iFatptrTy (ptradd Addr:$addr, immfrag:$offset))), (OutOp $rs, ZERO_64, immfrag:$offset, $addr)>; - def : Pat<(storeOp intTy:$rs, Addr:$addr), (OutOp $rs, ZERO_64, (i64 0), $addr)>; +multiclass FrameIndexStorePatterns { + def : Pat<(storeOp intTy:$rs, (ptradd CapFI:$addr, immfrag:$offset)), (OutOp $rs, ZERO_64, immfrag:$offset, $addr)>; + def : Pat<(storeOp intTy:$rs, CapFI:$addr), (OutOp $rs, ZERO_64, (i64 0), $addr)>; } -multiclass FrameIndexLoadPatterns { - def : Pat<(intTy (loadOp (iFatptrTy (ptradd Addr:$addr, immfrag:$offset)))), (OutOp ZERO_64, immfrag:$offset, $addr)>; - def : Pat<(intTy (loadOp Addr:$addr)), (OutOp ZERO_64, (i64 0), $addr)>; +multiclass FrameIndexLoadPatterns { + def : Pat<(intTy (loadOp (ptradd CapFI:$addr, immfrag:$offset))), (OutOp ZERO_64, immfrag:$offset, $addr)>; + def : Pat<(intTy (loadOp CapFI:$addr)), (OutOp ZERO_64, (i64 0), $addr)>; } -multiclass FrameIndexPatterns { - // FIXME: avoid this pattern for i8/i16 stack loads - def : Pat<(store CheriOpnd:$cs, (iFatptrTy (ptradd Addr:$addr, simm11s4Pattern:$offset))), (STORECAP $cs, ZERO_64, imm:$offset, $addr)>; - def : Pat<(store CheriOpnd:$cs, Addr:$addr), (STORECAP $cs, ZERO_64, (i64 0), $addr)>; - - def : Pat<(load (iFatptrTy (ptradd Addr:$addr, simm11s4Pattern:$offset))), (LOADCAP ZERO_64, imm:$offset, $addr)>; - def : Pat<(load Addr:$addr), (LOADCAP ZERO_64, (i64 0), $addr)>; - - // i64 load - defm: FrameIndexLoadPatterns; - - // i32 load - defm: FrameIndexLoadPatterns; - defm: FrameIndexLoadPatterns; - defm: FrameIndexLoadPatterns; - defm: FrameIndexLoadPatterns; - - // i16 load - defm: FrameIndexLoadPatterns; - defm: FrameIndexLoadPatterns; - defm: FrameIndexLoadPatterns; - defm: FrameIndexLoadPatterns; - // Use clhu instead of clh for anyext to match MIPS - defm: FrameIndexLoadPatterns; - defm: FrameIndexLoadPatterns; - - // i8 load - defm: FrameIndexLoadPatterns; - defm: FrameIndexLoadPatterns; - defm: FrameIndexLoadPatterns; - defm: FrameIndexLoadPatterns; - // Use clbu instead of clb for anyext to match MIPS - defm: FrameIndexLoadPatterns; - defm: FrameIndexLoadPatterns; - - // i1 load - defm: FrameIndexLoadPatterns; - defm: FrameIndexLoadPatterns; - defm: FrameIndexLoadPatterns; - defm: FrameIndexLoadPatterns; - // Use clbu instead of clb for anyext to match MIPS - defm: FrameIndexLoadPatterns; - defm: FrameIndexLoadPatterns; - - // stores - - // This pattern allows omitting lots of unnncessary sll instructions - def : Pat<(store (i32 (trunc GPR64:$rs)), Addr:$addr), (CAPSTORE3264 $rs, ZERO_64, (i64 0), $addr)>; - - defm: FrameIndexStorePatterns; - defm: FrameIndexStorePatterns; - defm: FrameIndexStorePatterns; - // GPR32 versions - defm: FrameIndexStorePatterns; - defm: FrameIndexStorePatterns; - - defm: FrameIndexStorePatterns; - defm: FrameIndexStorePatterns; -} - -defm : FrameIndexPatterns; -defm : FrameIndexPatterns; -defm : FrameIndexPatterns; - +// FIXME: avoid this pattern for i8/i16 stack loads +def : Pat<(store CheriOpnd:$cs, (ptradd CapFI:$addr, simm11s4Pattern:$offset)), (STORECAP $cs, ZERO_64, imm:$offset, $addr)>; +def : Pat<(store CheriOpnd:$cs, CapFI:$addr), (STORECAP $cs, ZERO_64, (i64 0), $addr)>; + +def : Pat<(load (ptradd CapFI:$addr, simm11s4Pattern:$offset)), (LOADCAP ZERO_64, imm:$offset, $addr)>; +def : Pat<(load CapFI:$addr), (LOADCAP ZERO_64, (i64 0), $addr)>; + +// i64 load +defm: FrameIndexLoadPatterns; + +// i32 load +defm: FrameIndexLoadPatterns; +defm: FrameIndexLoadPatterns; +defm: FrameIndexLoadPatterns; +defm: FrameIndexLoadPatterns; + +// i16 load +defm: FrameIndexLoadPatterns; +defm: FrameIndexLoadPatterns; +defm: FrameIndexLoadPatterns; +defm: FrameIndexLoadPatterns; +// Use clhu instead of clh for anyext to match MIPS +defm: FrameIndexLoadPatterns; +defm: FrameIndexLoadPatterns; + +// i8 load +defm: FrameIndexLoadPatterns; +defm: FrameIndexLoadPatterns; +defm: FrameIndexLoadPatterns; +defm: FrameIndexLoadPatterns; +// Use clbu instead of clb for anyext to match MIPS +defm: FrameIndexLoadPatterns; +defm: FrameIndexLoadPatterns; + +// i1 load +defm: FrameIndexLoadPatterns; +defm: FrameIndexLoadPatterns; +defm: FrameIndexLoadPatterns; +defm: FrameIndexLoadPatterns; +// Use clbu instead of clb for anyext to match MIPS +defm: FrameIndexLoadPatterns; +defm: FrameIndexLoadPatterns; + +// stores + +// This pattern allows omitting lots of unnncessary sll instructions +def : Pat<(store (i32 (trunc GPR64:$rs)), CapFI:$addr), (CAPSTORE3264 $rs, ZERO_64, (i64 0), $addr)>; + +defm: FrameIndexStorePatterns; +defm: FrameIndexStorePatterns; +defm: FrameIndexStorePatterns; +// GPR32 versions +defm: FrameIndexStorePatterns; +defm: FrameIndexStorePatterns; + +defm: FrameIndexStorePatterns; +defm: FrameIndexStorePatterns; class CheriBoundedStackPseudo : CheriPseudo<(outs CheriOpnd: $cd), ins, "#CapGlobalAddrPseudo $cd, $fi, $frameoffs, $size", []> { let hasSideEffects = 0; // could actually trap if we are out of stack space but I don't think that matters @@ -1040,35 +1024,29 @@ def CheriBoundedStackPseudoImm : CheriBoundedStackPseudo<(ins CheriOpnd:$fi, sim // FIXME: duplicated to avoid machine verified errors def CheriBoundedStackPseudoReg : CheriBoundedStackPseudo<(ins CheriOpnd:$fi, simm11s0:$frameoffs, GPR64Opnd:$size)>; -// TODO: for some reason all these need to be duplicated for the AddrFI patterns again -multiclass StackCapPatterns { - def : Pat<(iFatptrTy (int_cheri_bounded_stack_cap Addr:$fi, uimm11s0Pattern:$size)), - (CheriBoundedStackPseudoImm (Addr:$fi), (i64 0), imm:$size)>; - def : Pat<(iFatptrTy (int_cheri_bounded_stack_cap Addr:$fi, GPR64Opnd:$size)), - (CheriBoundedStackPseudoReg (Addr:$fi), (i64 0), GPR64Opnd:$size)>; - - // These should not be needed since they would mask bugs in CheriBoundAllocas.cpp. - // (but keep them here just in case): - // let AddedComplexity = -120 in { - // // If the incoffset was placed in a different basic block we - // // might have to turn the bounded stack cap into a plain setbounds: - // def : Pat<(iFatptrTy (int_cheri_bounded_stack_cap CheriOpnd:$reg, uimm11s0Pattern:$size)), - // (iFatptrTy (CSetBounds CheriOpnd:$reg, imm:$size))>; - // def : Pat<(iFatptrTy (int_cheri_bounded_stack_cap CheriOpnd:$reg, GPR64Opnd:$size)), - // (iFatptrTy (CSetBounds CheriOpnd:$reg, GPR64Opnd:$size))>; - // } - - // NOTE: removing the parentheses around (AddrFI128:$fi) in the output pattern will result in - // an invalid CIncOffset: %2:cherigpr = CIncOffset %2:cherigpr, $zero_64 - def : Pat<(iFatptrTy Addr:$fi), (CIncOffset (Addr:$fi), ZERO_64)>; - let AddedComplexity = 5 in { - // Add complexity to select this before the generic CIncOffsetImm pattern - def : Pat<(iFatptrTy (ptradd Addr:$fi, simm11s0Pattern:$offset)), (CIncOffsetImm (Addr:$fi), imm:$offset)>; - } +def : Pat<(int_cheri_bounded_stack_cap CapFI:$fi, uimm11s0Pattern:$size), + (CheriBoundedStackPseudoImm (CapFI:$fi), (i64 0), imm:$size)>; +def : Pat<(int_cheri_bounded_stack_cap CapFI:$fi, GPR64Opnd:$size), + (CheriBoundedStackPseudoReg (CapFI:$fi), (i64 0), GPR64Opnd:$size)>; + +// These should not be needed since they would mask bugs in CheriBoundAllocas.cpp. +// (but keep them here just in case): +// let AddedComplexity = -120 in { +// // If the incoffset was placed in a different basic block we +// // might have to turn the bounded stack cap into a plain setbounds: +// def : Pat<(int_cheri_bounded_stack_cap CheriOpnd:$reg, uimm11s0Pattern:$size), +// (CSetBounds CheriOpnd:$reg, imm:$size)>; +// def : Pat<(int_cheri_bounded_stack_cap CheriOpnd:$reg, GPR64Opnd:$size), +// (CSetBounds CheriOpnd:$reg, GPR64Opnd:$size)>; +// } + +// NOTE: removing the parentheses around (CapFI:$fi) in the output pattern will result in +// an invalid CIncOffset: %2:cherigpr = CIncOffset %2:cherigpr, $zero_64 +def : Pat<(cPTR CapFI:$fi), (CIncOffset (CapFI:$fi), ZERO_64)>; +let AddedComplexity = 5 in { + // Add complexity to select this before the generic CIncOffsetImm pattern + def : Pat<(ptradd CapFI:$fi, simm11s0Pattern:$offset), (CIncOffsetImm (CapFI:$fi), imm:$offset)>; } -defm : StackCapPatterns; -defm : StackCapPatterns; -defm : StackCapPatterns; def : Pat<(int_cheri_bounded_stack_cap_dynamic CheriOpnd:$cs, GPR64Opnd:$rt), (CSetBounds CheriOpnd:$cs, GPR64Opnd:$rt)>; @@ -1080,17 +1058,13 @@ def : Pat<(int_cheri_bounded_stack_cap_dynamic CheriOpnd:$cs, uimm11s0Pattern:$i // auto FI = cast(N); // return CurDAG->getTargetFrameIndex(FI->getIndex(), MVT::i32); // }]>; -// def : Pat<(iFATPTR128 frameindex:$fi), (CIncOffset (frameindex_to_targetframeindex $fi), ZERO_64)>; +// def : Pat<(c128 frameindex:$fi), (CIncOffset (frameindex_to_targetframeindex $fi), ZERO_64)>; // // Using a Pseudo instruction also seems to work fine: -// def StackToCapPseudo64 : CheriPseudo<(outs CheriOpnd: $cd), (ins CheriOpnd:$fi), "#StackToCapPseudo $cd, $fi", [(set CheriOpnd:$cd, AddrFI64:$fi)]>; -// def StackToCapPseudo128 : CheriPseudo<(outs CheriOpnd: $cd), (ins CheriOpnd:$fi), "#StackToCapPseudo $cd, $fi", [(set CheriOpnd:$cd, AddrFI128:$fi)]>; -// def StackToCapPseudo256 : CheriPseudo<(outs CheriOpnd: $cd), (ins CheriOpnd:$fi), "#StackToCapPseudo $cd, $fi", [(set CheriOpnd:$cd, AddrFI256:$fi)]>; +// def StackToCapPseudo : CheriPseudo<(outs CheriOpnd: $cd), (ins CheriOpnd:$fi), "#StackToCapPseudo $cd, $fi", [(set CheriOpnd:$cd, CapFI:$fi)]>; // TODO: maybe this will allow folding more offsets into the CIncOffset/clc/csc, etc. -// def addrRegImm64 : ComplexPattern; -// def addrRegImm128 : ComplexPattern; -// def addrRegImm256 : ComplexPattern; +// def addrRegImm : ComplexPattern; let Defs = [C11], Uses = [C11], hasSideEffects = 1, hasNoSchedulingInfo=1, Predicates=[IsCHERI,IsCHERIABI] in { diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.td b/llvm/lib/Target/Mips/MipsRegisterInfo.td index c71a4b32a92d..1d99479ab1c0 100644 --- a/llvm/lib/Target/Mips/MipsRegisterInfo.td +++ b/llvm/lib/Target/Mips/MipsRegisterInfo.td @@ -444,7 +444,7 @@ def CPURAReg : RegisterClass<"Mips", [i32], 32, (add RA)>, Unallocatable; def CPUSPReg : RegisterClass<"Mips", [i32], 32, (add SP)>, Unallocatable; def CapRegType : ValueTypeByHwMode<[Cap64, Cap128, Cap256, DefaultMode], - [iFATPTR64, iFATPTR128, iFATPTR256, iFATPTR128]>; + [c64, c128, c256, c128]>; def CheriGPR : RegisterClass<"Mips", [CapRegType], 256, (add C1, C2, C3, C4, C5, C6, C7, C8, C9, diff --git a/llvm/lib/Target/Mips/MipsSubtarget.h b/llvm/lib/Target/Mips/MipsSubtarget.h index fea7f421d769..fb5e77f4133c 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.h +++ b/llvm/lib/Target/Mips/MipsSubtarget.h @@ -373,8 +373,7 @@ class MipsSubtarget : public MipsGenSubtargetInfo { bool isCheri256() const { return IsCheri256; } bool useCheriCapTable() const { return getABI().IsCheriPureCap(); }; MVT typeForCapabilities() const { - return IsCheri64 ? MVT::iFATPTR64 : - (IsCheri128 ? MVT::iFATPTR128 : MVT::iFATPTR256); + return IsCheri64 ? MVT::c64 : (IsCheri128 ? MVT::c128 : MVT::c256); } /// This is a very ugly hack. CodeGenPrepare can sink pointer arithmetic to diff --git a/llvm/lib/Target/RISCV/RISCVExpandAtomicPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandAtomicPseudoInsts.cpp index 27200ec66240..0e52026b829a 100644 --- a/llvm/lib/Target/RISCV/RISCVExpandAtomicPseudoInsts.cpp +++ b/llvm/lib/Target/RISCV/RISCVExpandAtomicPseudoInsts.cpp @@ -496,9 +496,9 @@ static unsigned getLRForRMW(bool PtrIsCap, AtomicOrdering Ordering, MVT VT) { return getLRForRMW32(PtrIsCap, Ordering); if (VT == MVT::i64) return getLRForRMW64(PtrIsCap, Ordering); - if (VT == MVT::iFATPTR64) + if (VT == MVT::c64) return getLRForRMWCap64(PtrIsCap, Ordering); - if (VT == MVT::iFATPTR128) + if (VT == MVT::c128) return getLRForRMWCap128(PtrIsCap, Ordering); llvm_unreachable("Unexpected LR type\n"); } @@ -512,9 +512,9 @@ static unsigned getSCForRMW(bool PtrIsCap, AtomicOrdering Ordering, MVT VT) { return getSCForRMW32(PtrIsCap, Ordering); if (VT == MVT::i64) return getSCForRMW64(PtrIsCap, Ordering); - if (VT == MVT::iFATPTR64) + if (VT == MVT::c64) return getSCForRMWCap64(PtrIsCap, Ordering); - if (VT == MVT::iFATPTR128) + if (VT == MVT::c128) return getSCForRMWCap128(PtrIsCap, Ordering); llvm_unreachable("Unexpected SC type\n"); } diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index 9fa44a42c5dc..5970feb67fc2 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -44,6 +44,9 @@ def SDT_RISCVIntBinOpW : SDTypeProfile<1, 2, [ def SDT_RISCVIntShiftDOpW : SDTypeProfile<1, 3, [ SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64>, SDTCisVT<3, i64> ]>; +def SDT_RISCVSymLoad : SDTypeProfile<1, 1, [ + SDTCisSameAs<0, 1>, SDTCisPtrTy<0> +]>; // Target-independent nodes, but with target-specific formats. def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart, @@ -92,9 +95,9 @@ def riscv_add_tprel : SDNode<"RISCVISD::ADD_TPREL", SDTCisSameAs<0, 3>, SDTCisInt<0>]>>; -def riscv_la : SDNode<"RISCVISD::LA", SDTLoad, +def riscv_la : SDNode<"RISCVISD::LA", SDT_RISCVSymLoad, [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; -def riscv_la_tls_ie : SDNode<"RISCVISD::LA_TLS_IE", SDTLoad, +def riscv_la_tls_ie : SDNode<"RISCVISD::LA_TLS_IE", SDT_RISCVSymLoad, [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; def riscv_la_tls_gd : SDNode<"RISCVISD::LA_TLS_GD", SDTIntUnaryOp>; @@ -299,7 +302,7 @@ def BareSymbol : AsmOperandClass { } // A bare symbol. -def bare_symbol : Operand { +def bare_symbol : Operand { let ParserMatchClass = BareSymbol; } diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXCheri.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXCheri.td index 64e78b5881e4..63ee0b4f6b09 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoXCheri.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXCheri.td @@ -17,10 +17,6 @@ def SDT_RISCVCheriBoolUnary : SDTypeProfile<1, 1, [ SDTCisInt<0>, SDTCisVT<1, CLenVT> ]>; -def SDT_RISCVCheriAddr : SDTypeProfile<1, 1, [ - SDTCisVT<0, CLenVT>, SDTCisPtrTy<1> -]>; - def SDT_RISCVCheriBoolBinary : SDTypeProfile<1, 2, [ SDTCisInt<0>, SDTCisVT<1, CLenVT>, SDTCisVT<2, CLenVT> ]>; @@ -40,12 +36,12 @@ def riscv_cap_subset_test : SDNode<"RISCVISD::CAP_SUBSET_TEST", SDT_RISCVCheriBoolBinary>; def riscv_cap_equal_exact : SDNode<"RISCVISD::CAP_EQUAL_EXACT", SDT_RISCVCheriBoolBinary>; -def riscv_cllc : SDNode<"RISCVISD::CLLC", SDT_RISCVCheriAddr>; -def riscv_clgc : SDNode<"RISCVISD::CLGC", SDTLoad, +def riscv_cllc : SDNode<"RISCVISD::CLLC", SDT_RISCVSymLoad>; +def riscv_clgc : SDNode<"RISCVISD::CLGC", SDT_RISCVSymLoad, [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; -def riscv_cla_tls_ie : SDNode<"RISCVISD::CLA_TLS_IE", SDTLoad, +def riscv_cla_tls_ie : SDNode<"RISCVISD::CLA_TLS_IE", SDT_RISCVSymLoad, [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; -def riscv_clc_tls_gd : SDNode<"RISCVISD::CLC_TLS_GD", SDT_RISCVCheriAddr>; +def riscv_clc_tls_gd : SDNode<"RISCVISD::CLC_TLS_GD", SDT_RISCVSymLoad>; //===----------------------------------------------------------------------===// // Operand and SDNode transformation definitions. @@ -125,14 +121,10 @@ def uimm10_lsb0000 : Operand, }]; } -def CapFrameAddrRegImm64 : ComplexPattern; -def CapFrameAddrRegImm128 : ComplexPattern; -def CapRegImm64 : ComplexPattern; -def CapRegImm128 : ComplexPattern; +def CapFrameAddrRegImm : ComplexPattern; +def CapRegImm : ComplexPattern; //===----------------------------------------------------------------------===// // Instruction Formats @@ -1233,9 +1225,7 @@ def : PatGpcrUimm12; def : PatGpcrGpr; def : PatGpcrUimm12; -def : Pat<(CapFrameAddrRegImm64 GPCR:$rs1, simm12:$imm12), - (CIncOffsetImm GPCR:$rs1, simm12:$imm12)>; -def : Pat<(CapFrameAddrRegImm128 GPCR:$rs1, simm12:$imm12), +def : Pat<(CapFrameAddrRegImm GPCR:$rs1, simm12:$imm12), (CIncOffsetImm GPCR:$rs1, simm12:$imm12)>; /// Pointer-Arithmetic Instructions @@ -1246,11 +1236,11 @@ def : Pat<(CapFrameAddrRegImm128 GPCR:$rs1, simm12:$imm12), let Predicates = [HasCheri, NotCheriISAv9] in { def : Pat<(int_cheri_cap_to_pointer GPCR:$rs1, GPCRC0IsDDC:$rs2), (CToPtr GPCR:$rs1, GPCRC0IsDDC:$rs2)>; -def : Pat<(int_cheri_cap_to_pointer (CLenVT (int_cheri_ddc_get)), GPCR:$rs1), +def : Pat<(int_cheri_cap_to_pointer (int_cheri_ddc_get), GPCR:$rs1), (CToPtr $rs1, DDC)>; def : Pat<(int_cheri_cap_from_pointer GPCRC0IsDDC:$rs1, GPR:$rs2), (CFromPtr GPCRC0IsDDC:$rs1, GPR:$rs2)>; -def : Pat<(int_cheri_cap_from_pointer (CLenVT (int_cheri_ddc_get)), GPR:$rs2), +def : Pat<(int_cheri_cap_from_pointer (int_cheri_ddc_get), GPR:$rs2), (CFromPtr DDC, $rs2)>; } // let Predicates = [HasCheri, NotCheriISAv9] def : Pat<(int_cheri_cap_diff GPCR:$cs1, GPCR:$cs2), @@ -1271,7 +1261,7 @@ def : Pat<(ptrtoint GPCR:$rs1), (CToPtr GPCR:$rs1, DDC)>; /// Null Capability Patterns def : Pat<(inttoptr (XLenVT 0)), (CLenVT (COPY C0))>; -def : Pat<(XLenVT (ptrtoint (CLenVT (inttoptr (XLenVT 0))))), +def : Pat<(ptrtoint (CLenVT (inttoptr (XLenVT 0)))), (XLenVT (COPY (XLenVT X0)))>; /// Pointer-Comparison Instructions @@ -1290,32 +1280,15 @@ multiclass CheriSetCCPatGpcrImm { def : Pat<(CondOp GPCR:$cs1, (inttoptr ImmTy:$imm12)), (OutPatFrag<(ops node:$rs1, node:$imm12), GprImmDag> (EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr), ImmTy:$imm12)>; - def : Pat<(CondOp GPCR:$cs1, - (ptradd (iFATPTR64 (inttoptr (XLenVT 0))), ImmTy:$imm12)), - (OutPatFrag<(ops node:$rs1, node:$imm12), GprImmDag> - (EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr), ImmTy:$imm12)>; - def : Pat<(CondOp GPCR:$cs1, - (ptradd (iFATPTR128 (inttoptr (XLenVT 0))), ImmTy:$imm12)), + def : Pat<(CondOp GPCR:$cs1, (ptradd (inttoptr (XLenVT 0)), ImmTy:$imm12)), (OutPatFrag<(ops node:$rs1, node:$imm12), GprImmDag> (EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr), ImmTy:$imm12)>; def : Pat<(CondOp GPCR:$cs1, - (int_cheri_cap_offset_set - (iFATPTR64 (inttoptr (XLenVT 0))), ImmTy:$imm12)), + (int_cheri_cap_offset_set (inttoptr (XLenVT 0)), ImmTy:$imm12)), (OutPatFrag<(ops node:$rs1, node:$imm12), GprImmDag> (EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr), ImmTy:$imm12)>; def : Pat<(CondOp GPCR:$cs1, - (int_cheri_cap_offset_set - (iFATPTR128 (inttoptr (XLenVT 0))), ImmTy:$imm12)), - (OutPatFrag<(ops node:$rs1, node:$imm12), GprImmDag> - (EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr), ImmTy:$imm12)>; - def : Pat<(CondOp GPCR:$cs1, - (int_cheri_cap_address_set - (iFATPTR64 (inttoptr (XLenVT 0))), ImmTy:$imm12)), - (OutPatFrag<(ops node:$rs1, node:$imm12), GprImmDag> - (EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr), ImmTy:$imm12)>; - def : Pat<(CondOp GPCR:$cs1, - (int_cheri_cap_address_set - (iFATPTR128 (inttoptr (XLenVT 0))), ImmTy:$imm12)), + (int_cheri_cap_address_set (inttoptr (XLenVT 0)), ImmTy:$imm12)), (OutPatFrag<(ops node:$rs1, node:$imm12), GprImmDag> (EXTRACT_SUBREG GPCR:$cs1, sub_cap_addr), ImmTy:$imm12)>; } @@ -1336,7 +1309,7 @@ class Swap // NB: Constants are wrapped as (ptradd (inttoptr 0) C) so the operand order // isn't canonicalised like for integers so we have to add extra patterns for -// the commutative and inverse cases. Maybe we should support Constant:iFATPTR, +// the commutative and inverse cases. Maybe we should support Constant:cN, // represent them as (inttoptr C), or just canonicalise the current form? def : CheriSetCCPatGpcrGpcr; @@ -1585,24 +1558,24 @@ multiclass AMOCapPat { } let Predicates = [HasCheri, IsRV32, NotCapMode] in { -defm : LdPat; -defm : StPat; +defm : LdPat; +defm : StPat; } // Predicates = [HasCheri, IsRV32, NotCapMode] let Predicates = [HasCheri, IsRV64, NotCapMode] in { -defm : LdPat; -defm : StPat; +defm : LdPat; +defm : StPat; } // Predicates = [HasCheri, IsRV64, NotCapMode] let Predicates = [HasCheri, HasStdExtA, IsRV32, NotCapMode] in { -defm : LdPat; -defm : AtomicStPat; +defm : LdPat; +defm : AtomicStPat; defm : AMOCapPat<"64", "atomic_swap_cap", "AMOSWAP_C">; } // Predicates = [HasCheri, HasStdExtA, IsRV32, NotCapMode] let Predicates = [HasCheri, HasStdExtA, IsRV64, NotCapMode] in { -defm : LdPat; -defm : AtomicStPat; +defm : LdPat; +defm : AtomicStPat; defm : AMOCapPat<"128", "atomic_swap_cap", "AMOSWAP_C">; } // Predicates = [HasCheri, HasStdExtA, IsRV64, NotCapMode] @@ -1637,16 +1610,12 @@ defm : PseudoCmpXchgPat<"atomic_cmp_swap_cap", PseudoCmpXchgCap, GPCR>; /// Capability Mode Instructions multiclass CheriLdPat { - def : Pat<(LoadOp (CapRegImm64 GPCR:$rs1, simm12:$imm12)), - (Inst GPCR:$rs1, simm12:$imm12)>; - def : Pat<(LoadOp (CapRegImm128 GPCR:$rs1, simm12:$imm12)), + def : Pat<(LoadOp (CapRegImm GPCR:$rs1, simm12:$imm12)), (Inst GPCR:$rs1, simm12:$imm12)>; } multiclass CheriStPat { - def : Pat<(StoreOp StTy:$rs2, (CapRegImm64 GPCR:$rs1, simm12:$imm12)), - (Inst StTy:$rs2, GPCR:$rs1, simm12:$imm12)>; - def : Pat<(StoreOp StTy:$rs2, (CapRegImm128 GPCR:$rs1, simm12:$imm12)), + def : Pat<(StoreOp StTy:$rs2, (CapRegImm GPCR:$rs1, simm12:$imm12)), (Inst StTy:$rs2, GPCR:$rs1, simm12:$imm12)>; } diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td index c2650bd2b58d..716fdf2aa924 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td @@ -182,7 +182,7 @@ def XLenRI : RegInfoByHwMode< [RV32, RV64], [RegInfo<32,32,32>, RegInfo<64,64,64>]>; def CLenVT : ValueTypeByHwMode<[RV32, RV64], - [iFATPTR64, iFATPTR128]>; + [c64, c128]>; def CLenRI : RegInfoByHwMode< [RV32, RV64], [RegInfo<64,64,64>, RegInfo<128,128,128>]>; diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h index 8d836550cab2..e06e81869ba5 100644 --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -233,7 +233,7 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo { } MVT typeForCapabilities() const { assert(HasCheri && "Cannot get capability type for non-CHERI"); - return is64Bit() ? MVT::iFATPTR128 : MVT::iFATPTR64; + return is64Bit() ? MVT::c128 : MVT::c64; } bool hasMacroFusion() const { return hasLUIADDIFusion(); } diff --git a/llvm/test/CodeGen/Mips/cconv/vector.ll b/llvm/test/CodeGen/Mips/cconv/vector.ll index 08645d634ebc..b8c474a7c90a 100644 --- a/llvm/test/CodeGen/Mips/cconv/vector.ll +++ b/llvm/test/CodeGen/Mips/cconv/vector.ll @@ -1,5 +1,3 @@ -; XXXAR: for some reason we always use $w0 here, but we don't really care about MIPS64R5 so just skip the test -; XFAIL: * ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=mips-unknown-linux-gnu -mcpu=mips32 -disable-mips-delay-filler | FileCheck %s --check-prefixes=MIPS32,MIPS32EB ; RUN: llc < %s -mtriple=mips64-unknown-linux-gnu -relocation-model=pic -mcpu=mips64 -disable-mips-delay-filler -mips-jalr-reloc=false | FileCheck %s --check-prefixes=MIPS64,MIPS64EB diff --git a/llvm/test/CodeGen/Mips/cheri/call-c13-null.ll b/llvm/test/CodeGen/Mips/cheri/call-c13-null.ll index fdf119644984..595ff520493f 100644 --- a/llvm/test/CodeGen/Mips/cheri/call-c13-null.ll +++ b/llvm/test/CodeGen/Mips/cheri/call-c13-null.ll @@ -14,15 +14,15 @@ declare i8 addrspace(200)* @many_cap_args(i8 addrspace(200)* %arg1, i8 addrspace ; Check that the debug output prints -; DEBUG-OUTPUT-CHECK: Clearing $c13 in call_one_arg_from_many_arg(is varargs: 0) callee = {{t[0-9]+}}: iFATPTR128 = GlobalAddress 0 +; DEBUG-OUTPUT-CHECK: Clearing $c13 in call_one_arg_from_many_arg(is varargs: 0) callee = {{t[0-9]+}}: c128 = GlobalAddress 0 ; DEBUG-OUTPUT-CHECK-NEXT: Lowering return for function with $c13 live-in: call_one_arg_from_many_arg(is varargs: 0) -; DEBUG-OUTPUT-CHECK-NEXT: Clearing $c13 in call_one_arg_from_variadic_with_va_start(is varargs: 1) callee = {{t[0-9]+}}: iFATPTR128 = GlobalAddress 0 +; DEBUG-OUTPUT-CHECK-NEXT: Clearing $c13 in call_one_arg_from_variadic_with_va_start(is varargs: 1) callee = {{t[0-9]+}}: c128 = GlobalAddress 0 ; DEBUG-OUTPUT-CHECK-NEXT: Lowering return for function with $c13 live-in: call_one_arg_from_variadic_with_va_start(is varargs: 1) -; DEBUG-OUTPUT-CHECK-NEXT: Clearing $c13 in call_one_arg_from_variadic_without_va_start(is varargs: 1) callee = {{t[0-9]+}}: iFATPTR128 = GlobalAddress 0 +; DEBUG-OUTPUT-CHECK-NEXT: Clearing $c13 in call_one_arg_from_variadic_without_va_start(is varargs: 1) callee = {{t[0-9]+}}: c128 = GlobalAddress 0 ; DEBUG-OUTPUT-CHECK-NEXT: Lowering return for function with $c13 live-in: call_one_arg_from_variadic_without_va_start(is varargs: 1) -; DEBUG-OUTPUT-CHECK-NEXT: Clearing $c13 in call_variadic_no_onstack_from_varargs(is varargs: 1) callee = {{t[0-9]+}}: iFATPTR128 = GlobalAddress 0 +; DEBUG-OUTPUT-CHECK-NEXT: Clearing $c13 in call_variadic_no_onstack_from_varargs(is varargs: 1) callee = {{t[0-9]+}}: c128 = GlobalAddress 0 ; DEBUG-OUTPUT-CHECK-NEXT: Lowering return for function with $c13 live-in: call_variadic_no_onstack_from_varargs(is varargs: 1) -; DEBUG-OUTPUT-CHECK-NEXT: Clearing $c13 in call_variadic_no_onstack_from_many_args(is varargs: 0) callee = {{t[0-9]+}}: iFATPTR128 = GlobalAddress 0 +; DEBUG-OUTPUT-CHECK-NEXT: Clearing $c13 in call_variadic_no_onstack_from_many_args(is varargs: 0) callee = {{t[0-9]+}}: c128 = GlobalAddress 0 ; DEBUG-OUTPUT-CHECK-NEXT: Lowering return for function with $c13 live-in: call_variadic_no_onstack_from_many_args(is varargs: 0) ; CHECK-LABEL: .text diff --git a/llvm/test/CodeGen/Mips/msa/basic_operations.ll b/llvm/test/CodeGen/Mips/msa/basic_operations.ll index 573b8074b3ae..9ddb91f0770d 100644 --- a/llvm/test/CodeGen/Mips/msa/basic_operations.ll +++ b/llvm/test/CodeGen/Mips/msa/basic_operations.ll @@ -18,9 +18,6 @@ ; RUN: -verify-machineinstrs < %s \ ; RUN: | FileCheck -check-prefixes=N64,N64-LE %s -; For some reason CHERI breaks this this test, but we don't support msa anyway -; XFAIL: * - @v4i8 = global <4 x i8> @v16i8 = global <16 x i8> @v8i16 = global <8 x i16> diff --git a/llvm/test/CodeGen/Mips/msa/cc_without_nan.ll b/llvm/test/CodeGen/Mips/msa/cc_without_nan.ll index ed8104ad6950..eda4f478e3a2 100644 --- a/llvm/test/CodeGen/Mips/msa/cc_without_nan.ll +++ b/llvm/test/CodeGen/Mips/msa/cc_without_nan.ll @@ -1,10 +1,4 @@ ; RUN: llc -mtriple mips64-unknown-linux -mcpu=mips64r5 -mattr=+msa -verify-machineinstrs < %s | FileCheck %s -; FIXME: emitINSERT_DF_VIDX() creates an invalid sequence: -; %25:gpr64 = DSLL %5:gpr32, 3 -; %26:msa128d = SLD_B %7:msa128d(tied-def 0), %7:msa128d, %25.sub_32:gpr64 -; Expected a GPR64 register, but got a GPR32 register -; Since we don't care about MSA for CHERI, mark this as XFAIL for now -; XFAIL: * ; The fcmp fast flag will result in conversion from ; setolt, setoeq, setole, setone to diff --git a/llvm/test/CodeGen/Mips/msa/elm_copy.ll b/llvm/test/CodeGen/Mips/msa/elm_copy.ll index 6706d1353def..908c23421bb0 100644 --- a/llvm/test/CodeGen/Mips/msa/elm_copy.ll +++ b/llvm/test/CodeGen/Mips/msa/elm_copy.ll @@ -9,7 +9,6 @@ ; RUN: FileCheck %s -check-prefixes=MIPS-ANY,MIPS64 ; RUN: llc -march=mips64el -mcpu=mips64r2 -mattr=+msa,+fp64 -relocation-model=pic < %s | \ ; RUN: FileCheck %s -check-prefixes=MIPS-ANY,MIPS64 -; XFAIL: * @llvm_mips_copy_s_b_ARG1 = global <16 x i8> , align 16 @llvm_mips_copy_s_b_RES = global i32 0, align 16 diff --git a/llvm/test/CodeGen/Mips/msa/elm_insv.ll b/llvm/test/CodeGen/Mips/msa/elm_insv.ll index 048d38075f57..a94a105e5005 100644 --- a/llvm/test/CodeGen/Mips/msa/elm_insv.ll +++ b/llvm/test/CodeGen/Mips/msa/elm_insv.ll @@ -9,7 +9,6 @@ ; RUN: FileCheck %s -check-prefixes=MIPS-ANY,MIPS64 ; RUN: llc -march=mips64el -mcpu=mips64r2 -mattr=+msa,+fp64 -relocation-model=pic < %s | \ ; RUN: FileCheck %s -check-prefixes=MIPS-ANY,MIPS64 -; XFAIL: * @llvm_mips_insert_b_ARG1 = global <16 x i8> , align 16 @llvm_mips_insert_b_ARG3 = global i32 27, align 16 diff --git a/llvm/test/CodeGen/Mips/msa/immediates.ll b/llvm/test/CodeGen/Mips/msa/immediates.ll index af64d7e96c1f..db1eb17cf4a1 100644 --- a/llvm/test/CodeGen/Mips/msa/immediates.ll +++ b/llvm/test/CodeGen/Mips/msa/immediates.ll @@ -6,12 +6,6 @@ ; RUN: llc -march=mips64 -mattr=+msa,+fp64 -relocation-model=pic -target-abi n64 < %s \ ; RUN: | FileCheck %s -check-prefixes=MSA,MSA64N64 -; For some hard to debug reason this is broken with CHERI clang, but we don't care about MSA -; XFAIL: * - -; FIXME: this crashes clang: -; llvm::DAGTypeLegalizer::ExpandChainLibCall (this=0x7fffffffbb10, LC=llvm::RTLIB::UNKNOWN_LIBCALL, Node=0x7242c8, isSigned=false) at llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp:1071: SDValue InChain = Node->getOperand(0); - ; Test that the immediate intrinsics don't crash LLVM. ; Some of the intrinsics lower to equivalent forms. diff --git a/llvm/test/CodeGen/RISCV/cheri/unaligned-fp-load-store.ll b/llvm/test/CodeGen/RISCV/cheri/unaligned-fp-load-store.ll index 91dfa6a688a1..e9ee02095263 100644 --- a/llvm/test/CodeGen/RISCV/cheri/unaligned-fp-load-store.ll +++ b/llvm/test/CodeGen/RISCV/cheri/unaligned-fp-load-store.ll @@ -5,7 +5,7 @@ ; RUN: llc -mtriple=riscv64 -mattr=+f,+xcheri,+cap-mode -target-abi l64pc128f -verify-machineinstrs < %s \ ; RUN: | %cheri128_FileCheck --check-prefixes=CHECK,RV64IFXCHERI %s --allow-unused-prefixes ; Previously expandUnalignedLoad() would trigger assertions for unaligned floating-point values since we were creating -; incorrect iFATPTR constants. +; incorrect capability constants. declare i32 @printf(i8 addrspace(200)*, ...) addrspace(200) define i32 @unaligned_float(float addrspace(200)* nocapture readonly %arg, float %newval) unnamed_addr addrspace(200) nounwind { diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp index fbc1b5f28aa6..08c909e251d3 100644 --- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -46,9 +46,6 @@ static inline bool isVector(MVT VT) { static inline bool isScalar(MVT VT) { return !VT.isVector(); } -static inline bool isScalarIntegerOrFatPtr(MVT VT) { - return VT.isScalarInteger() || VT.isFatPointer(); -} template static bool berase_if(MachineValueTypeSet &S, Predicate P) { @@ -272,85 +269,91 @@ void TypeSetByHwMode::dump() const { } bool TypeSetByHwMode::intersect(SetType &Out, const SetType &In) { - bool OutP = Out.count(MVT::iPTR), InP = In.count(MVT::iPTR); - // Complement of In. - auto CompIn = [&In](MVT T) -> bool { return !In.count(T); }; - - if (OutP == InP) - return berase_if(Out, CompIn); - - // Compute the intersection of scalars separately to account for only - // one set containing iPTR. - // The intersection of iPTR with a set of integer scalar types that does not - // include iPTR will result in the most specific scalar type: - // - iPTR is more specific than any set with two elements or more - // - iPTR is less specific than any single integer scalar type. - // For example - // { iPTR } * { i32 } -> { i32 } - // { iPTR } * { i32 i64 } -> { iPTR } - // and - // { iPTR i32 } * { i32 } -> { i32 } - // { iPTR i32 } * { i32 i64 } -> { i32 i64 } - // { iPTR i32 } * { i32 i64 i128 } -> { iPTR i32 } - - // Let In' = elements only in In, Out' = elements only in Out, and - // IO = elements common to both. Normally IO would be returned as the result - // of the intersection, but we need to account for iPTR being a "wildcard" of - // sorts. Since elements in IO are those that match both sets exactly, they - // will all belong to the output. If any of the "leftovers" (i.e. In' or - // Out') contain iPTR, it means that the other set doesn't have it, but it - // could have (1) a more specific type, or (2) a set of types that is less - // specific. The "leftovers" from the other set is what we want to examine - // more closely. - - auto subtract = [](const SetType &A, const SetType &B) { - SetType Diff = A; - berase_if(Diff, [&B](MVT T) { return B.count(T); }); - return Diff; - }; - - if (InP) { - SetType OutOnly = subtract(Out, In); - if (OutOnly.empty()) { - // This means that Out \subset In, so no change to Out. - return false; - } - unsigned NumI = llvm::count_if(OutOnly, isScalarIntegerOrFatPtr); - if (NumI == 1 && OutOnly.size() == 1) { - // There is only one element in Out', and it happens to be a scalar - // integer that should be kept as a match for iPTR in In. - return false; + auto IntersectP = [&](Optional WildVT, function_ref P) { + // Complement of In within this partition. + auto CompIn = [&](MVT T) -> bool { return !In.count(T) && P(T); }; + + if (!WildVT) + return berase_if(Out, CompIn); + + bool OutW = Out.count(*WildVT), InW = In.count(*WildVT); + if (OutW == InW) + return berase_if(Out, CompIn); + + // Compute the intersection of scalars separately to account for only one + // set containing WildVT. + // The intersection of WildVT with a set of corresponding types that does + // not include WildVT will result in the most specific type: + // - WildVT is more specific than any set with two elements or more + // - WildVT is less specific than any single type. + // For example, for iPTR and scalar integer types + // { iPTR } * { i32 } -> { i32 } + // { iPTR } * { i32 i64 } -> { iPTR } + // and + // { iPTR i32 } * { i32 } -> { i32 } + // { iPTR i32 } * { i32 i64 } -> { i32 i64 } + // { iPTR i32 } * { i32 i64 i128 } -> { iPTR i32 } + + // Looking at just this partition, let In' = elements only in In, + // Out' = elements only in Out, and IO = elements common to both. Normally + // IO would be returned as the result of the intersection, but we need to + // account for WildVT being a "wildcard" of sorts. Since elements in IO are + // those that match both sets exactly, they will all belong to the output. + // If any of the "leftovers" (i.e. In' or Out') contain WildVT, it means + // that the other set doesn't have it, but it could have (1) a more + // specific type, or (2) a set of types that is less specific. The + // "leftovers" from the other set is what we want to examine more closely. + + auto Leftovers = [&](const SetType &A, const SetType &B) { + SetType Diff = A; + berase_if(Diff, [&](MVT T) { return B.count(T) || !P(T); }); + return Diff; + }; + + if (InW) { + SetType OutLeftovers = Leftovers(Out, In); + if (OutLeftovers.size() < 2) { + // WildVT not added to Out. Keep the possible single leftover. + return false; + } + // WildVT replaces the leftovers. + berase_if(Out, CompIn); + Out.insert(*WildVT); + return true; } - berase_if(Out, CompIn); - if (NumI == 1) { - // Replace the iPTR with the leftover scalar integer. - Out.insert(*llvm::find_if(OutOnly, isScalarIntegerOrFatPtr)); - } else if (NumI > 1) { - Out.insert(MVT::iPTR); + + // OutW == true + SetType InLeftovers = Leftovers(In, Out); + unsigned SizeOut = Out.size(); + berase_if(Out, CompIn); // This will remove at least the WildVT. + if (InLeftovers.size() < 2) { + // WildVT deleted from Out. Add back the possible single leftover. + Out.insert(InLeftovers); + return true; } - return true; - } - // OutP == true - SetType InOnly = subtract(In, Out); - unsigned SizeOut = Out.size(); - berase_if(Out, CompIn); // This will remove at least the iPTR. - unsigned NumI = llvm::count_if(InOnly, isScalarIntegerOrFatPtr); - if (NumI == 0) { - // iPTR deleted from Out. - return true; - } - if (NumI == 1) { - // Replace the iPTR with the leftover scalar integer. - Out.insert(*llvm::find_if(InOnly, isScalarIntegerOrFatPtr)); - return true; - } + // Keep the WildVT in Out. + Out.insert(*WildVT); + // If WildVT was the only element initially removed from Out, then Out + // has not changed. + return SizeOut != Out.size(); + }; + + typedef std::pair> WildPartT; + static const WildPartT WildParts[] = { + {MVT::iPTR, [](MVT T) { return T.isScalarInteger() || T == MVT::iPTR; }}, + {MVT::cPTR, [](MVT T) { return T.isCapability() || T == MVT::cPTR; }}, + }; + + bool Changed = false; + for (const auto &I : WildParts) + Changed |= IntersectP(I.first, I.second); + + Changed |= IntersectP(llvm::None, [&](MVT T) { + return !any_of(WildParts, [=](const WildPartT &I) { return I.second(T); }); + }); - // NumI > 1: Keep the iPTR in Out. - Out.insert(MVT::iPTR); - // If iPTR was the only element initially removed from Out, then Out - // has not changed. - return SizeOut != Out.size(); + return Changed; } bool TypeSetByHwMode::validate() const { @@ -837,12 +840,12 @@ void TypeInfer::expandOverloads(TypeSetByHwMode::SetType &Out, switch (Ov.SimpleTy) { case MVT::iPTRAny: Out.insert(MVT::iPTR); - return; - case MVT::iFATPTRAny: - Out.insert(MVT::iFATPTR64); - Out.insert(MVT::iFATPTR128); - Out.insert(MVT::iFATPTR256); - Out.insert(MVT::iFATPTR512); + for (MVT T : MVT::capability_valuetypes()) { + if (Legal.count(T)) { + Out.insert(MVT::cPTR); + break; + } + } return; case MVT::iAny: for (MVT T : MVT::integer_valuetypes()) @@ -1658,18 +1661,9 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, // Operand must be a particular type. return NodeToApply->UpdateNodeType(ResNo, VVT, TP); case SDTCisPtrTy: { - // Operand must be a pointer type. - // If we support fat pointers, then this narrows it down to two types. - if (TP.getDAGPatterns().enableFatPointers()) { - // FIXME: We should be able to do the type inference correctly from the - // two types, but for now just disable this constraint on architectures - // with fat pointers. - return false; - ArrayRef PtrTys({ValueTypeByHwMode(MVT::iFATPTRAny), - ValueTypeByHwMode(MVT::iPTR)}); - return NodeToApply->UpdateNodeType(ResNo, PtrTys, TP); - } - return NodeToApply->UpdateNodeType(ResNo, MVT::iPTR, TP); + // Operand must be a legal pointer (iPTR, or possibly cPTR) type. + const auto &PtrTys = TP.getDAGPatterns().getLegalPtrTypes(); + return NodeToApply->UpdateNodeType(ResNo, PtrTys, TP); } case SDTCisInt: // Require it to be one of the legal integer VTs. @@ -1783,8 +1777,10 @@ bool TreePatternNode::UpdateNodeTypeFromInst(unsigned ResNo, } // PointerLikeRegClass has a type that is determined at runtime. - if (Operand->isSubClassOf("PointerLikeRegClass")) - return UpdateNodeType(ResNo, MVT::iPTR, TP); + if (Operand->isSubClassOf("PointerLikeRegClass")) { + Record *R = Operand->getValueAsDef("RegClassType"); + return UpdateNodeType(ResNo, getValueType(R), TP); + } // Both RegisterClass and RegisterOperand operands derive their types from a // register class def. @@ -1883,7 +1879,7 @@ MVT::SimpleValueType SDNodeInfo::getKnownType(unsigned ResNo) const { return Constraint.VVT.getSimple().SimpleTy; break; case SDTypeConstraint::SDTCisPtrTy: - return MVT::iPTR; + return MVT::iPTRAny; } } return MVT::Other; @@ -2336,7 +2332,8 @@ static TypeSetByHwMode getImplicitType(Record *R, unsigned ResNo, } if (R->isSubClassOf("PointerLikeRegClass")) { assert(ResNo == 0 && "Regclass can only have one result!"); - TypeSetByHwMode VTS(MVT::iPTR); + Record *T = R->getValueAsDef("RegClassType"); + TypeSetByHwMode VTS(getValueType(T)); TP.getInfer().expandOverloads(VTS); return VTS; } @@ -3205,11 +3202,7 @@ void TreePattern::dump() const { print(errs()); } CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R, PatternRewriterFn PatternRewriter) : Records(R), Target(R), LegalVTS(Target.getLegalValueTypes()), - PatternRewriter(PatternRewriter) { - - // If the target declares a class called SupportsFatPointers, then we enable - // support for two types of pointer. - FatPointers = R.getClass("SupportsFatPointers"); + LegalPtrVTS(ComputeLegalPtrTypes()), PatternRewriter(PatternRewriter) { Intrinsics = CodeGenIntrinsicTable(Records); ParseNodeInfo(); @@ -3247,6 +3240,36 @@ Record *CodeGenDAGPatterns::getSDNodeNamed(StringRef Name) const { return N; } +// Compute the subset of iPTR and cPTR legal for each mode, coalescing into the +// default mode where possible to avoid predicate explosion. +TypeSetByHwMode CodeGenDAGPatterns::ComputeLegalPtrTypes() const { + auto LegalPtrsForSet = [](const MachineValueTypeSet &In) { + MachineValueTypeSet Out; + Out.insert(MVT::iPTR); + for (MVT T : MVT::capability_valuetypes()) { + if (In.count(T)) { + Out.insert(MVT::cPTR); + break; + } + } + return Out; + }; + + const auto &LegalTypes = getLegalTypes(); + MachineValueTypeSet LegalPtrsDefault = + LegalPtrsForSet(LegalTypes.get(DefaultMode)); + + TypeSetByHwMode LegalPtrTypes; + for (const auto &I : LegalTypes) { + MachineValueTypeSet S = LegalPtrsForSet(I.second); + if (I.first != DefaultMode && S == LegalPtrsDefault) + continue; + LegalPtrTypes.getOrCreate(I.first).insert(S); + } + + return LegalPtrTypes; +} + // Parse all of the SDNode definitions for the target, populating SDNodes. void CodeGenDAGPatterns::ParseNodeInfo() { std::vector Nodes = Records.getAllDerivedDefinitions("SDNode"); diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.h b/llvm/utils/TableGen/CodeGenDAGPatterns.h index 6438af01c4c8..1c3d1ce34d53 100644 --- a/llvm/utils/TableGen/CodeGenDAGPatterns.h +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.h @@ -1121,10 +1121,8 @@ class CodeGenDAGPatterns { /// emit. std::vector PatternsToMatch; - /// Flag indicating whether fat pointers should be supported. - bool FatPointers; - TypeSetByHwMode LegalVTS; + TypeSetByHwMode LegalPtrVTS; using PatternRewriterFn = std::function; PatternRewriterFn PatternRewriter; @@ -1138,8 +1136,7 @@ class CodeGenDAGPatterns { CodeGenTarget &getTargetInfo() { return Target; } const CodeGenTarget &getTargetInfo() const { return Target; } const TypeSetByHwMode &getLegalTypes() const { return LegalVTS; } - - bool enableFatPointers() { return FatPointers; } + const TypeSetByHwMode &getLegalPtrTypes() const { return LegalPtrVTS; } Record *getSDNodeNamed(StringRef Name) const; @@ -1242,6 +1239,7 @@ class CodeGenDAGPatterns { } private: + TypeSetByHwMode ComputeLegalPtrTypes() const; void ParseNodeInfo(); void ParseNodeTransforms(); void ParseComplexPatterns(); diff --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp index 2be33ecfa4af..aa06e963ac02 100644 --- a/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/llvm/utils/TableGen/CodeGenTarget.cpp @@ -240,15 +240,14 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) { case MVT::nxv2f64: return "MVT::nxv2f64"; case MVT::nxv4f64: return "MVT::nxv4f64"; case MVT::nxv8f64: return "MVT::nxv8f64"; + case MVT::c64: return "MVT::c64"; + case MVT::c128: return "MVT::c128"; + case MVT::c256: return "MVT::c256"; + case MVT::cPTR: return "MVT::cPTR"; case MVT::token: return "MVT::token"; case MVT::Metadata: return "MVT::Metadata"; case MVT::iPTR: return "MVT::iPTR"; case MVT::iPTRAny: return "MVT::iPTRAny"; - case MVT::iFATPTR64: return "MVT::iFATPTR64"; - case MVT::iFATPTR128:return "MVT::iFATPTR128"; - case MVT::iFATPTR256:return "MVT::iFATPTR256"; - case MVT::iFATPTR512:return "MVT::iFATPTR512"; - case MVT::iFATPTRAny:return "MVT::iFATPTRAny"; case MVT::Untyped: return "MVT::Untyped"; case MVT::funcref: return "MVT::funcref"; case MVT::externref: return "MVT::externref"; @@ -740,11 +739,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R, continue; MVT::SimpleValueType VT = getValueType(TyEl->getValueAsDef("VT")); - // iFATPTRAny is overloaded from the perspective of the back end (it - // becomes one of the fixed-sized iFATPTR types), but it is not overloaded - // from the perspective of the IR, where it is (currently, at least) always - // an address-space-200 pointer. - if (MVT(VT).isOverloaded() && (MVT(VT) != MVT::iFATPTRAny)) { + if (MVT(VT).isOverloaded()) { OverloadedVTs.push_back(VT); isOverloaded = true; } @@ -931,7 +926,8 @@ bool CodeGenIntrinsic::isParamAPointer(unsigned ParamIdx) const { if (ParamIdx >= IS.ParamVTs.size()) return false; MVT ParamType = MVT(IS.ParamVTs[ParamIdx]); - return ParamType == MVT::iPTR || ParamType == MVT::iPTRAny; + return ParamType == MVT::iPTR || ParamType == MVT::cPTR || + ParamType == MVT::iPTRAny; } bool CodeGenIntrinsic::isParamImmArg(unsigned ParamIdx) const { diff --git a/llvm/utils/TableGen/DAGISelMatcher.cpp b/llvm/utils/TableGen/DAGISelMatcher.cpp index e436a931a9f5..4d38d269da52 100644 --- a/llvm/utils/TableGen/DAGISelMatcher.cpp +++ b/llvm/utils/TableGen/DAGISelMatcher.cpp @@ -334,6 +334,14 @@ static bool TypesAreContradictory(MVT::SimpleValueType T1, // contradict. if (T1 == T2) return false; + if (T1 == MVT::iPTRAny) + return TypesAreContradictory(MVT::iPTR, T2) && + TypesAreContradictory(MVT::cPTR, T2); + + if (T2 == MVT::iPTRAny) + return TypesAreContradictory(T1, MVT::iPTR) && + TypesAreContradictory(T1, MVT::cPTR); + // If either type is about iPtr, then they don't conflict unless the other // one is not a scalar integer type. if (T1 == MVT::iPTR) @@ -342,7 +350,13 @@ static bool TypesAreContradictory(MVT::SimpleValueType T1, if (T2 == MVT::iPTR) return !MVT(T1).isInteger() || MVT(T1).isVector(); - // Otherwise, they are two different non-iPTR types, they conflict. + if (T1 == MVT::cPTR) + return !MVT(T2).isCapability() || MVT(T2).isVector(); + + if (T2 == MVT::cPTR) + return !MVT(T1).isCapability() || MVT(T1).isVector(); + + // Otherwise, they are two different non-iPTR/cPTR types, they conflict. return true; } diff --git a/llvm/utils/TableGen/DAGISelMatcherOpt.cpp b/llvm/utils/TableGen/DAGISelMatcherOpt.cpp index 4273bd69b87d..cdc6e055ebeb 100644 --- a/llvm/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/llvm/utils/TableGen/DAGISelMatcherOpt.cpp @@ -369,9 +369,9 @@ static void FactorNodes(std::unique_ptr &InputMatcherPtr) { cast_or_null(FindNodeWithKind(NewOptionsToMatch[i], Matcher::CheckType)); if (!CTM || - // iPTR checks could alias any other case without us knowing, don't - // bother with them. - CTM->getType() == MVT::iPTR || + // iPTR/cPTR checks could alias any other case without us knowing, + // don't bother with them. + CTM->getType() == MVT::iPTR || CTM->getType() == MVT::cPTR || // SwitchType only works for result #0. CTM->getResNo() != 0 || // If the CheckType isn't at the start of the list, see if we can move diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index 4b47cda41567..605bd4fdb564 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -1729,7 +1729,9 @@ Error OperandMatcher::addTypeCheckPredicate(const TypeSetByHwMode &VTy, if (!VTy.isMachineValueType()) return failedImport("unsupported typeset"); - if (VTy.getMachineValueType() == MVT::iPTR && OperandIsAPointer) { + if ((VTy.getMachineValueType() == MVT::iPTR || + VTy.getMachineValueType() == MVT::cPTR) && + OperandIsAPointer) { addPredicate(0); return Error::success(); } diff --git a/llvm/utils/TableGen/IntrinsicEmitter.cpp b/llvm/utils/TableGen/IntrinsicEmitter.cpp index f05656ac58d4..798fec68d477 100644 --- a/llvm/utils/TableGen/IntrinsicEmitter.cpp +++ b/llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -256,11 +256,6 @@ enum IIT_Info { IIT_ANYPTR_TO_ELT = 56, IIT_I2 = 57, IIT_I4 = 58, - IIT_IFATPTR64 = IIT_I4 + 1, - IIT_IFATPTR128 = IIT_IFATPTR64 + 1, - IIT_IFATPTR256 = IIT_IFATPTR128 + 1, - IIT_IFATPTR512 = IIT_IFATPTR256 + 1, - IIT_IFATPTRAny = IIT_IFATPTR512 + 1, }; static void EncodeFixedValueType(MVT::SimpleValueType VT, @@ -283,11 +278,6 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT, switch (VT) { default: PrintFatalError("unhandled MVT in intrinsic!"); - case MVT::iFATPTR64: return Sig.push_back(IIT_IFATPTR64); - case MVT::iFATPTR128: return Sig.push_back(IIT_IFATPTR128); - case MVT::iFATPTR256: return Sig.push_back(IIT_IFATPTR256); - case MVT::iFATPTR512: return Sig.push_back(IIT_IFATPTR512); - case MVT::iFATPTRAny: return Sig.push_back(IIT_IFATPTRAny); case MVT::f16: return Sig.push_back(IIT_F16); case MVT::bf16: return Sig.push_back(IIT_BF16); case MVT::f32: return Sig.push_back(IIT_F32); @@ -389,11 +379,15 @@ static void EncodeFixedType(Record *R, std::vector &ArgCodes, return Sig.push_back((ArgNo << 3) | Tmp); } - case MVT::iPTR: { + case MVT::iPTR: + case MVT::cPTR: { unsigned AddrSpace = 0; if (R->isSubClassOf("LLVMQualPointerType")) { AddrSpace = R->getValueAsInt("AddrSpace"); assert(AddrSpace < 256 && "Address space exceeds 255"); + } else if (VT == MVT::cPTR) { + // XXX: Hard-coded AS + AddrSpace = 200; } if (AddrSpace) { Sig.push_back(IIT_ANYPTR); @@ -404,23 +398,6 @@ static void EncodeFixedType(Record *R, std::vector &ArgCodes, return EncodeFixedType(R->getValueAsDef("ElTy"), ArgCodes, NextArgCode, Sig, Mapping); } - case MVT::iFATPTR64: - case MVT::iFATPTR128: - case MVT::iFATPTR256: - case MVT::iFATPTR512: - case MVT::iFATPTRAny: { - switch (VT) { - default: llvm_unreachable("VT already checked!"); - case MVT::iFATPTR64: Sig.push_back(IIT_IFATPTR64); break; - case MVT::iFATPTR128: Sig.push_back(IIT_IFATPTR128); break; - case MVT::iFATPTR256: Sig.push_back(IIT_IFATPTR256); break; - case MVT::iFATPTR512: Sig.push_back(IIT_IFATPTR512); break; - case MVT::iFATPTRAny: Sig.push_back(IIT_IFATPTRAny); break; - } - Sig.push_back(200); - return EncodeFixedType(R->getValueAsDef("ElTy"), ArgCodes, NextArgCode, Sig, - Mapping); - } } if (MVT(VT).isVector()) {