[llvm-commits] [LLVMdev] Simplifing the handling of pre-legalize vector nodes
Chris Lattner
clattner at apple.com
Wed May 23 23:15:09 PDT 2007
On May 23, 2007, at 8:56 AM, Dan Gohman wrote:
> Ok, I now have a patch that implements this. It's a work in
> progress, and
> still rough in some areas (some details below), but it works well
> enough
> to allow the LLVM regression tests to pass on x86. I'm posting it
> now so
> that people can see what I'm up to.
Cool!
> On Wed, May 23, 2007 at 12:03:30AM -0700, Chris Lattner wrote:
>> On Mon, 21 May 2007, Dan Gohman wrote:
>>> It seems that a number of things would be considerably simpler if
>>> the
>>> pre-legalize nodes could use the same node kinds as post-
>>> legalize; the only
>>> thing preventing that is that the MVT::ValueType enum isn't able
>>> to describe
>>> vector types with arbitrarily long vector lengths.
>>
>> Yep, I'm sure you know this, but this is to support generic
>> vectors. For
>> example, if you had an input .ll that operated on 128-wide
>> vectors, we
>> want to be able to split that up to use 4-wide vectors if your target
>> supports them.
>
> Last time I tried this it caused an impressive amount of register
> pressure;
> long-vector loads/stores require special ScheduleDAG dependencies,
> but LLVM
> was forcing long-vector dependencies on all the operators so that
> operations
> on the individual sub-vectors couldn't be scheduled around to
> reduce register
> pressure. But that's a different topic :-).
In theory -combiner-alias-analysis should fix this, or at least help
it, by making the stores independent of each other so they can be
reordered. It isn't on by default because of its compile time hit.
At some point, we should finish it up.
>> Going forward, we will also likely have to do something similar to
>> this
>> for integer types, in order to handle stuff like i47 that gets
>> legalized
>> into 2 x i32 or something. I am not looking forward to
>> duplicating all of
>> the arithmetic nodes for IADD variants etc (urk, imagine vectors of
>> strange-sized-integers! VIADD??)
>
> urk indeed...
>
> My current patch is specific to vectors, as the table elements for
> extended
> types are std::pairs of vector lengths and element types. Perhaps
> the thing
> to do then is to make it a table of Type*. Then it would be usable
> for any
> machine-illegal type.
Sure, it makes sense to get a start, and extend it from there.
>>> I'm currently considering ways to make this possible. One idea is
>>> to rename
>>> the MVT::ValueType enum to something else and make MVT::ValueType
>>> a plain
>>> integer type. Values beyond the range of the original enum are
>>> interpreted
>>> as indices into a UniqueVector which holds pairs of vector
>>> lengths and
>>> element types.
>>
>> That is a very interesting idea. It handles the generality of
>> arbitrary
>> value types, but is nice and fast for the common code that doesn't
>> use the
>> craziness :). I like it!
>
> One downside is that debuggers no longer print MVT::ValueTypes with
> enum
> names.
Slightly annoying, but not a big deal.
>>> Before I do much more experimentation with this, I wanted to run
>>> the idea by
>>> the list to see what feedback it might get. Has anyone thought
>>> about doing
>>> this before? Are there other approaches that might be better?
>>
>> This approach sounds very sensible. Make sure the SelectionDAG
>> owns the
>> table though.
>
> I wasn't sure if it should go in the SelectionDAG or the
> TargetLowering.
It should be in SelectionDAG. The protocol is that the interfaces in
include/llvm/Target/* are immutable once created (though the
interfaces can hack on data structures passed in, like
SelectionDAGs). The classes instantiated from include/llvm/CodeGen
represent code as it is being hacked on. As such, CodeGen/
SelectionDAG is the right place to go.
> My current patch just uses a global table because it was easier and
> allowed
> me to get to the LegalizeDAG.cpp changes. But I'll definately clean
> this up.
Sounds good.
Some quick thoughts about the patch:
diff -u -r1.34 ValueTypes.h
--- include/llvm/CodeGen/ValueTypes.h
+++ include/llvm/CodeGen/ValueTypes.h
Meta-comment about this file: when the table is moved to not be
global, the 'simple' functions should stay, the complex ones should
move to be methods on SelectionDAG. Note that tools like tblgen use
ValueTypes.h (for simple VTs), but don't link the llvm libraries in.
// iPTR - An int value the size of the pointer of the current
// target. This should only be used internal to tblgen!
- iPTR = 255
+ iPTR = 255,
Can there be more than 255 elts in the table? If so, I'd suggest
turning this into ~0U or something.
- /// MVT::isInteger - Return true if this is a simple integer, or a
packed
+ typedef int ValueType;
Can these be negative? If not, plz use unsigned instead of int.
+ /// MVT::isExtendedIntegerVector - Test if the given ValueType is a
+ /// vector (simple or extended) with a floating-point element type.
+ bool isExtendedFloatingPointVector(ValueType VT);
comment pasto.
+ /// MVT::isVector - Return true if this is a simple vector value
+ /// type.
static inline bool isVector(ValueType VT) {
return VT >= FIRST_VECTOR_VALUETYPE && VT <=
LAST_VECTOR_VALUETYPE;
}
+
+ /// MVT::isAnyVector - This function is like isVector, except that it
+ /// is not limited to simple types.
+ bool isAnyVector(ValueType VT);
This is confusing - I'd expect isVector to return true for complex
types and have an 'isSimpleVector' function.
+ /// MVT::getSizeInBits - Return the size of the specified value
type in bits.
+ ///
+ static inline unsigned getSizeInBits(ValueType VT) {
+ return VT <= LAST_SIMPLE_VALUETYPE ?
+ getSimpleTypeSizeInBits(VT) :
+ getExtendedVectorSizeInBits(VT);
+ }
The other predicates, like isInteger/isFP could use the same
technique to avoid the function call in the common case..
+ /// MVT::getVectorBaseType - Given an extended vector type, return
the type of
+ /// each element.
+ ValueType getExtendedVectorBaseType(ValueType VT);
comment pasto
LegalizeAction getTypeAction(MVT::ValueType VT) const {
- return (LegalizeAction)((ValueTypeActions[VT>>4] >> ((2*VT) &
31)) & 3);
+ return VT <= MVT::LAST_SIMPLE_VALUETYPE ?
+ (LegalizeAction)((ValueTypeActions[VT>>4] >> ((2*VT) &
31)) & 3) :
+ Expand;
}
Cute :)
+// FIXME: Move this to SelectionDAG.
+static UniqueVector< std::pair<MVT::SimpleValueType, unsigned> > VTys;
+
I'd suggest using a real struct instead of a pair. This gives you
meaningful field names instead of first/second :)
/// MVT::getValueTypeString - This function returns value type as a
string,
/// e.g. "i32".
const char *MVT::getValueTypeString(MVT::ValueType VT) {
switch (VT) {
- default: assert(0 && "Invalid ValueType!");
+ default:
+ if (VT > MVT::LAST_SIMPLE_VALUETYPE) {
+ // FIXME: change the return type from char* to std::string so
+ // we can generate the apporpriate string.
+ return "vXtY";
+ }
+ assert(0 && "Invalid ValueType!");
It's a minor nit to pick, but an alternative approach would be to
build the std::string table on demand, handing out pointers to the
c_str() of the std::strings. This allows the method to return a
const char*, which makes the clients simpler. Also, SelectionDAG can
own this table, as it will have to eventually have this function as a
method anyway.
+bool MVT::isAnyVector(ValueType VT) {
+ return isVector(VT) || (VT > LAST_SIMPLE_VALUETYPE &&
+ isa<VectorType>(getTypeForValueType(VT)));
+}
This seems like a really expensive predicate (having to compute
getTypeForValueType, etc). I'd suggest just adding a discriminator
in the table, indicating that yes, these are vector entries. In the
future, when adding extended integer types, we can just set the
discriminator to "integer" instead of "vector"
+bool MVT::isExtendedIntegerVector(ValueType VT) {
+ return isAnyVector(VT) && isInteger(getVectorBaseType(VT));
+}
+
+/// MVT::isExtendedIntegerVector - Test if the given ValueType is a
+/// vector (simple or extended) with a floating-point element type.
comment pasto
+bool MVT::isExtendedFloatingPointVector(ValueType VT) {
+ return isAnyVector(VT) && isFloatingPoint(getVectorBaseType(VT));
+}
I suggest inlining the calls to isAnyVector/getVectorBaseType, as
they are both accessing the table element, and the code should stay
fairly simple.
--- utils/TableGen/DAGISelEmitter.cpp
+++ utils/TableGen/DAGISelEmitter.cpp
@@ -67,7 +67,7 @@
/// contains isInt or an integer value type.
static bool isExtIntegerInVTs(const std::vector<unsigned char>
&EVTs) {
assert(!EVTs.empty() && "Cannot check for integer in empty ExtVT
list!");
- return EVTs[0] == MVT::isInt || !(FilterEVTs(EVTs,
MVT::isInteger).empty());
+ return EVTs[0] == MVT::isInt || !(FilterEVTs(EVTs,
MVT::isSimpleInteger).empty());
}
exceeds 80 cols. likewise elsewhere in the file.
Overall, I really like the approach. The table does need to move to
SelectionDAG before this should be committed though.
See you on Friday,
-Chris
More information about the llvm-commits
mailing list