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 @@ -29,7 +31,7 @@ // IntrNoSync - Threads executing the intrinsic will not synchronize using // memory or other means. -def IntrNoSync : IntrinsicProperty; +def IntrNoSync : IntrinsicProperty<1>; // IntrReadMem - This intrinsic only reads from memory. It does not write to // memory and has no other side effects. Therefore, it cannot be moved across @@ -331,13 +333,15 @@ list param_types = [], list intr_properties = [], string name = "", - list sd_properties = []> : SDPatternOperator { + list sd_properties = [], + list optout_intr_properties = []> : SDPatternOperator { string LLVMName = name; string TargetPrefix = ""; // Set to a prefix for target-specific intrinsics. list RetTypes = ret_types; list ParamTypes = param_types; list IntrProperties = intr_properties; let Properties = sd_properties; + list OptOutIntrProperties = optout_intr_properties; bit isTarget = 0; } @@ -571,7 +575,7 @@ llvm_i1_ty], [IntrWriteMem, IntrArgMemOnly, IntrWillReturn, NoCapture>, WriteOnly>, - ImmArg>]>; + ImmArg>], "", [], [IntrNoSync]>; // FIXME: Add version of these floating point intrinsics which allow non-default // rounding modes and FP exception handling. 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 @@ -754,6 +754,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) { @@ -761,68 +764,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. @@ -832,6 +774,98 @@ llvm::sort(ArgumentAttributes); } +void CodeGenIntrinsic::setDefaultProperties(Record *R) { + std::vector Defs = + R->getRecords().getAllDerivedDefinitions("IntrinsicProperty"); + + ListInit *OptOutPropList = R->getValueAsListInit("OptOutIntrProperties"); + for (Record *Rec : Defs) { + if (!Rec->getValueAsBit("IsDefault")) + continue; + + bool OptOut = false; + for (unsigned i = 0, e = OptOutPropList->size(); i != e; ++i) { + Record *Property = OptOutPropList->getElementAsRecord(i); + assert(Property->isSubClassOf("IntrinsicProperty") && + "Expected a property"); + + if (Property->getName() != Rec->getName()) + continue; + + OptOut = true; + } + + // If the user didn't opt-out of the default property, apply it. + if (!OptOut) + 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;