diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -17,7 +17,9 @@ // Properties we keep track of for intrinsics. //===----------------------------------------------------------------------===// -class IntrinsicProperty; +class IntrinsicProperty { + bit IsDefault = is_default; +} // Intr*Mem - Memory properties. If no property is set, the worst case // is assumed (it may read and write any memory it can get access to and it may @@ -331,7 +333,8 @@ list param_types = [], list intr_properties = [], string name = "", - list sd_properties = []> : SDPatternOperator { + list sd_properties = [], + bit disable_default_attributes = 0> : SDPatternOperator { string LLVMName = name; string TargetPrefix = ""; // Set to a prefix for target-specific intrinsics. list RetTypes = ret_types; @@ -339,6 +342,10 @@ list IntrProperties = intr_properties; let Properties = sd_properties; + // Disable applying IntrinsicProperties that are marked default with + // IntrinsicProperty<1> + bit DisableDefaultAttributes = disable_default_attributes; + bit isTarget = 0; } diff --git a/llvm/test/TableGen/intrin-side-effects.td b/llvm/test/TableGen/intrin-side-effects.td --- a/llvm/test/TableGen/intrin-side-effects.td +++ b/llvm/test/TableGen/intrin-side-effects.td @@ -11,7 +11,10 @@ def llvm_i32_ty : LLVMType; -class IntrinsicProperty; +class IntrinsicProperty { + bit IsDefault = is_default; +} + def IntrNoMem : IntrinsicProperty; def IntrHasSideEffects : IntrinsicProperty; @@ -27,6 +30,8 @@ list ParamTypes = param_types; list IntrProperties = intr_properties; let Properties = sd_properties; + bit DisableDefaultAttributes = 1; + bit isTarget = 0; } diff --git a/llvm/test/TableGen/intrinsic-long-name.td b/llvm/test/TableGen/intrinsic-long-name.td --- a/llvm/test/TableGen/intrinsic-long-name.td +++ b/llvm/test/TableGen/intrinsic-long-name.td @@ -1,7 +1,10 @@ // RUN: llvm-tblgen -gen-intrinsic-enums %s | FileCheck %s // XFAIL: vg_leak -class IntrinsicProperty; +class IntrinsicProperty { + bit IsDefault = is_default; +} + class SDNodeProperty; class ValueType { @@ -22,6 +25,7 @@ list ParamTypes = param_types; list IntrProperties = []; list Properties = []; + bit DisableDefaultAttributes = 1; } def iAny : ValueType<0, 253>; diff --git a/llvm/test/TableGen/intrinsic-pointer-to-any.td b/llvm/test/TableGen/intrinsic-pointer-to-any.td --- a/llvm/test/TableGen/intrinsic-pointer-to-any.td +++ b/llvm/test/TableGen/intrinsic-pointer-to-any.td @@ -6,7 +6,10 @@ // case, so TableGen would hit an assertion in EncodeFixedType that was checking // to ensure that the substitution being processed was correctly replaced. -class IntrinsicProperty; +class IntrinsicProperty { + bit IsDefault = is_default; +} + class SDNodeProperty; class ValueType { @@ -32,6 +35,7 @@ list IntrProperties = []; list Properties = []; bit isTarget = 0; + bit DisableDefaultAttributes = 1; } class LLVMQualPointerType diff --git a/llvm/test/TableGen/intrinsic-struct.td b/llvm/test/TableGen/intrinsic-struct.td --- a/llvm/test/TableGen/intrinsic-struct.td +++ b/llvm/test/TableGen/intrinsic-struct.td @@ -1,7 +1,10 @@ // RUN: llvm-tblgen -gen-intrinsic-enums %s | FileCheck %s // XFAIL: vg_leak -class IntrinsicProperty; +class IntrinsicProperty { + bit IsDefault = is_default; +} + class SDNodeProperty; class ValueType { @@ -22,6 +25,7 @@ list ParamTypes = []; list IntrProperties = []; list Properties = []; + bit DisableDefaultAttributes = 1; } def iAny : ValueType<0, 253>; diff --git a/llvm/test/TableGen/intrinsic-varargs.td b/llvm/test/TableGen/intrinsic-varargs.td --- a/llvm/test/TableGen/intrinsic-varargs.td +++ b/llvm/test/TableGen/intrinsic-varargs.td @@ -3,7 +3,9 @@ include "llvm/CodeGen/ValueTypes.td" -class IntrinsicProperty; +class IntrinsicProperty { + bit IsDefault = is_default; +} class SDNodeProperty; class LLVMType { @@ -18,6 +20,7 @@ list ParamTypes = param_types; list IntrProperties = []; list Properties = []; + bit DisableDefaultAttributes = 1; } def llvm_vararg_ty : LLVMType; // this means vararg here diff --git a/llvm/test/TableGen/searchabletables-intrinsic.td b/llvm/test/TableGen/searchabletables-intrinsic.td --- a/llvm/test/TableGen/searchabletables-intrinsic.td +++ b/llvm/test/TableGen/searchabletables-intrinsic.td @@ -3,7 +3,10 @@ include "llvm/TableGen/SearchableTable.td" -class IntrinsicProperty; +class IntrinsicProperty { + bit IsDefault = is_default; +} + class SDNodeProperty; class ValueType { @@ -24,6 +27,7 @@ list ParamTypes = param_types; list IntrProperties = []; list Properties = []; + bit DisableDefaultAttributes = 1; } def iAny : ValueType<0, 253>; diff --git a/llvm/utils/TableGen/CodeGenIntrinsics.h b/llvm/utils/TableGen/CodeGenIntrinsics.h --- a/llvm/utils/TableGen/CodeGenIntrinsics.h +++ b/llvm/utils/TableGen/CodeGenIntrinsics.h @@ -176,6 +176,13 @@ return Properties & (1 << Prop); } + /// Goes through all IntrProperties and sets to true ones that have IsDefault + /// value set to true. + void setDefaultProperties(Record *R); + + /// Helper function to set property \p Name to true; + void setProperty(Record *R); + /// Returns true if the parameter at \p ParamIdx is a pointer type. Returns /// false if the parameter is not a pointer, or \p ParamIdx is greater than /// the size of \p IS.ParamVTs. diff --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp --- a/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/llvm/utils/TableGen/CodeGenTarget.cpp @@ -766,6 +766,9 @@ IS.ParamTypeDefs.push_back(TyEl); } + // Set default properties to true. + setDefaultProperties(R); + // Parse the intrinsic properties. ListInit *PropList = R->getValueAsListInit("IntrProperties"); for (unsigned i = 0, e = PropList->size(); i != e; ++i) { @@ -773,68 +776,7 @@ assert(Property->isSubClassOf("IntrinsicProperty") && "Expected a property!"); - if (Property->getName() == "IntrNoMem") - ModRef = NoMem; - else if (Property->getName() == "IntrReadMem") - ModRef = ModRefBehavior(ModRef & ~MR_Mod); - else if (Property->getName() == "IntrWriteMem") - ModRef = ModRefBehavior(ModRef & ~MR_Ref); - else if (Property->getName() == "IntrArgMemOnly") - ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_ArgMem); - else if (Property->getName() == "IntrInaccessibleMemOnly") - ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_InaccessibleMem); - else if (Property->getName() == "IntrInaccessibleMemOrArgMemOnly") - ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_ArgMem | - MR_InaccessibleMem); - else if (Property->getName() == "Commutative") - isCommutative = true; - else if (Property->getName() == "Throws") - canThrow = true; - else if (Property->getName() == "IntrNoDuplicate") - isNoDuplicate = true; - else if (Property->getName() == "IntrConvergent") - isConvergent = true; - else if (Property->getName() == "IntrNoReturn") - isNoReturn = true; - else if (Property->getName() == "IntrNoSync") - isNoSync = true; - else if (Property->getName() == "IntrNoFree") - isNoFree = true; - else if (Property->getName() == "IntrWillReturn") - isWillReturn = true; - else if (Property->getName() == "IntrCold") - isCold = true; - else if (Property->getName() == "IntrSpeculatable") - isSpeculatable = true; - else if (Property->getName() == "IntrHasSideEffects") - hasSideEffects = true; - else if (Property->isSubClassOf("NoCapture")) { - unsigned ArgNo = Property->getValueAsInt("ArgNo"); - ArgumentAttributes.emplace_back(ArgNo, NoCapture, 0); - } else if (Property->isSubClassOf("NoAlias")) { - unsigned ArgNo = Property->getValueAsInt("ArgNo"); - ArgumentAttributes.emplace_back(ArgNo, NoAlias, 0); - } else if (Property->isSubClassOf("Returned")) { - unsigned ArgNo = Property->getValueAsInt("ArgNo"); - ArgumentAttributes.emplace_back(ArgNo, Returned, 0); - } else if (Property->isSubClassOf("ReadOnly")) { - unsigned ArgNo = Property->getValueAsInt("ArgNo"); - ArgumentAttributes.emplace_back(ArgNo, ReadOnly, 0); - } else if (Property->isSubClassOf("WriteOnly")) { - unsigned ArgNo = Property->getValueAsInt("ArgNo"); - ArgumentAttributes.emplace_back(ArgNo, WriteOnly, 0); - } else if (Property->isSubClassOf("ReadNone")) { - unsigned ArgNo = Property->getValueAsInt("ArgNo"); - ArgumentAttributes.emplace_back(ArgNo, ReadNone, 0); - } else if (Property->isSubClassOf("ImmArg")) { - unsigned ArgNo = Property->getValueAsInt("ArgNo"); - ArgumentAttributes.emplace_back(ArgNo, ImmArg, 0); - } else if (Property->isSubClassOf("Align")) { - unsigned ArgNo = Property->getValueAsInt("ArgNo"); - uint64_t Align = Property->getValueAsInt("Align"); - ArgumentAttributes.emplace_back(ArgNo, Alignment, Align); - } else - llvm_unreachable("Unknown property!"); + setProperty(Property); } // Also record the SDPatternOperator Properties. @@ -844,6 +786,84 @@ llvm::sort(ArgumentAttributes); } +void CodeGenIntrinsic::setDefaultProperties(Record *R) { + // opt-out of using default attributes. + if (R->getValueAsBit("DisableDefaultAttributes")) + return; + + std::vector Defs = + R->getRecords().getAllDerivedDefinitions("IntrinsicProperty"); + + for (Record *Rec : Defs) + if (Rec->getValueAsBit("IsDefault")) + setProperty(Rec); +} + +void CodeGenIntrinsic::setProperty(Record *R) { + if (R->getName() == "IntrNoMem") + ModRef = NoMem; + else if (R->getName() == "IntrReadMem") + ModRef = ModRefBehavior(ModRef & ~MR_Mod); + else if (R->getName() == "IntrWriteMem") + ModRef = ModRefBehavior(ModRef & ~MR_Ref); + else if (R->getName() == "IntrArgMemOnly") + ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_ArgMem); + else if (R->getName() == "IntrInaccessibleMemOnly") + ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_InaccessibleMem); + else if (R->getName() == "IntrInaccessibleMemOrArgMemOnly") + ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_ArgMem | + MR_InaccessibleMem); + else if (R->getName() == "Commutative") + isCommutative = true; + else if (R->getName() == "Throws") + canThrow = true; + else if (R->getName() == "IntrNoDuplicate") + isNoDuplicate = true; + else if (R->getName() == "IntrConvergent") + isConvergent = true; + else if (R->getName() == "IntrNoReturn") + isNoReturn = true; + else if (R->getName() == "IntrNoSync") + isNoSync = true; + else if (R->getName() == "IntrNoFree") + isNoFree = true; + else if (R->getName() == "IntrWillReturn") + isWillReturn = true; + else if (R->getName() == "IntrCold") + isCold = true; + else if (R->getName() == "IntrSpeculatable") + isSpeculatable = true; + else if (R->getName() == "IntrHasSideEffects") + hasSideEffects = true; + else if (R->isSubClassOf("NoCapture")) { + unsigned ArgNo = R->getValueAsInt("ArgNo"); + ArgumentAttributes.emplace_back(ArgNo, NoCapture, 0); + } else if (R->isSubClassOf("NoAlias")) { + unsigned ArgNo = R->getValueAsInt("ArgNo"); + ArgumentAttributes.emplace_back(ArgNo, NoAlias, 0); + } else if (R->isSubClassOf("Returned")) { + unsigned ArgNo = R->getValueAsInt("ArgNo"); + ArgumentAttributes.emplace_back(ArgNo, Returned, 0); + } else if (R->isSubClassOf("ReadOnly")) { + unsigned ArgNo = R->getValueAsInt("ArgNo"); + ArgumentAttributes.emplace_back(ArgNo, ReadOnly, 0); + } else if (R->isSubClassOf("WriteOnly")) { + unsigned ArgNo = R->getValueAsInt("ArgNo"); + ArgumentAttributes.emplace_back(ArgNo, WriteOnly, 0); + } else if (R->isSubClassOf("ReadNone")) { + unsigned ArgNo = R->getValueAsInt("ArgNo"); + ArgumentAttributes.emplace_back(ArgNo, ReadNone, 0); + } else if (R->isSubClassOf("ImmArg")) { + unsigned ArgNo = R->getValueAsInt("ArgNo"); + ArgumentAttributes.emplace_back(ArgNo, ImmArg, 0); + } else if (R->isSubClassOf("Align")) { + unsigned ArgNo = R->getValueAsInt("ArgNo"); + uint64_t Align = R->getValueAsInt("Align"); + ArgumentAttributes.emplace_back(ArgNo, Alignment, Align); + } else + llvm_unreachable("Unknown property!"); +} + bool CodeGenIntrinsic::isParamAPointer(unsigned ParamIdx) const { if (ParamIdx >= IS.ParamVTs.size()) return false;