Currently attributes for intrinsics are emitted using the ArrayRef<AttrKind> based constructor for AttributeLists. This works out fine for simple enum attributes, but doesn't really generalize to attributes that accept values. We're already doing something awkward for alignment attributes, and I'd like to have a cleaner solution to this with https://discourse.llvm.org/t/rfc-unify-memory-effect-attributes/65579 in mind. The new generation approach is to instead directly construct Attributes, giving us access to the full generality of that interface. To avoid significantly increasing the size of the generated code, we now also deduplicate the attribute sets. The code generated per unique AttributeList looks like this: case 204: { AS[0] = {1, getIntrinsicArgAttributeSet(C, 5)}; AS[1] = {AttributeList::FunctionIndex, getIntrinsicFnAttributeSet(C, 10)}; NumAttrs = 2; break; } and then the helper functions contain something like case 5: return AttributeSet::get(C, { Attribute::get(C, Attribute::NoCapture), }); and case 10: return AttributeSet::get(C, { Attribute::get(C, Attribute::NoUnwind), Attribute::get(C, Attribute::ArgMemOnly), }); A casualty of this change is the intrin-properties.td test, as I don't think that FileCheck allows matching this kind of output. Differential Revision: https://reviews.llvm.org/D135679
52 lines
1.6 KiB
TableGen
52 lines
1.6 KiB
TableGen
// RUN: llvm-tblgen -gen-intrinsic-impl -I %p/../../include %s | FileCheck %s
|
|
|
|
// Get the minimum blurb necessary to process ...
|
|
include "llvm/CodeGen/ValueTypes.td"
|
|
include "llvm/CodeGen/SDNodeProperties.td"
|
|
|
|
class LLVMType<ValueType vt> {
|
|
ValueType VT = vt;
|
|
int isAny = 0;
|
|
}
|
|
|
|
def llvm_i32_ty : LLVMType<i32>;
|
|
|
|
class IntrinsicProperty<bit is_default = 0> {
|
|
bit IsDefault = is_default;
|
|
}
|
|
|
|
def IntrNoMem : IntrinsicProperty;
|
|
def IntrHasSideEffects : IntrinsicProperty;
|
|
|
|
class Intrinsic<list<LLVMType> ret_types,
|
|
list<LLVMType> param_types = [],
|
|
list<IntrinsicProperty> intr_properties = [],
|
|
string name = "",
|
|
list<SDNodeProperty> sd_properties = [],
|
|
bit disable_default_attributes = 0> : SDPatternOperator {
|
|
string LLVMName = name;
|
|
string TargetPrefix = "";
|
|
list<LLVMType> RetTypes = ret_types;
|
|
list<LLVMType> ParamTypes = param_types;
|
|
list<IntrinsicProperty> IntrProperties = intr_properties;
|
|
let Properties = sd_properties;
|
|
bit DisableDefaultAttributes = 1;
|
|
|
|
|
|
bit isTarget = 0;
|
|
bit DisableDefaultAttributes = disable_default_attributes;
|
|
}
|
|
|
|
// ... this intrinsic.
|
|
def int_random_gen : Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrHasSideEffects]>;
|
|
|
|
// CHECK: static AttributeSet getIntrinsicFnAttributeSet(
|
|
// CHECK: case 0:
|
|
// CHECK-NEXT: return AttributeSet::get(C, {
|
|
// CHECK-NEXT: Attribute::get(C, Attribute::NoUnwind),
|
|
// CHECK-NEXT: });
|
|
|
|
// CHECK: 1, // llvm.random.gen
|
|
// CHECK: case 1:
|
|
// CHECK-NEXT: AS[0] = {AttributeList::FunctionIndex, getIntrinsicFnAttributeSet(C, 0)};
|