Skip to content

Commit 87e05eb

Browse files
committed
Revert "Remove use of tuple for multiresult type storage"
This reverts commit 08f0764.
1 parent 283db5f commit 87e05eb

File tree

3 files changed

+39
-45
lines changed

3 files changed

+39
-45
lines changed

mlir/include/mlir/IR/Operation.h

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace mlir {
2727
/// 'Block' class.
2828
class alignas(8) Operation final
2929
: public llvm::ilist_node_with_parent<Operation, Block>,
30-
private llvm::TrailingObjects<Operation, BlockOperand, Region, Type,
30+
private llvm::TrailingObjects<Operation, BlockOperand, Region,
3131
detail::OperandStorage> {
3232
public:
3333
/// Create a new Operation with the specific fields.
@@ -651,7 +651,7 @@ class alignas(8) Operation final
651651

652652
/// Returns a pointer to the use list for the given trailing result.
653653
detail::TrailingOpResult *getTrailingResult(unsigned resultNumber) {
654-
// Trailing results are stored in reverse order after (before in memory) the
654+
// Trailing results are stored in reverse order after(before in memory) the
655655
// inline results.
656656
return reinterpret_cast<detail::TrailingOpResult *>(
657657
getInlineResult(OpResult::getMaxInlineResults() - 1)) -
@@ -695,18 +695,11 @@ class alignas(8) Operation final
695695
/// states recorded here:
696696
/// - 0 results : The type below is null.
697697
/// - 1 result : The single result type is held here.
698-
/// - N results : The type here is empty and instead the result types are held
699-
/// in trailing storage.
698+
/// - N results : The type here is a tuple holding the result types.
699+
/// Note: We steal a bit for 'hasSingleResult' from somewhere else so that we
700+
/// can use 'resultType` in an ArrayRef<Type>.
700701
bool hasSingleResult : 1;
701-
702-
/// Union representing either the Type of a single result operation (if
703-
/// hasSingleResult) or the number of result types for multi-result.
704-
union {
705-
// Type, set if single result Operation.
706-
Type type = nullptr;
707-
// Size, set if not a single result Operation.
708-
unsigned size;
709-
} resultTypeOrSize;
702+
Type resultType;
710703

711704
/// This holds the name of the operation.
712705
OperationName name;
@@ -727,15 +720,12 @@ class alignas(8) Operation final
727720
friend class llvm::ilist_node_with_parent<Operation, Block>;
728721

729722
// This stuff is used by the TrailingObjects template.
730-
friend llvm::TrailingObjects<Operation, BlockOperand, Region, Type,
723+
friend llvm::TrailingObjects<Operation, BlockOperand, Region,
731724
detail::OperandStorage>;
732725
size_t numTrailingObjects(OverloadToken<BlockOperand>) const {
733726
return numSuccs;
734727
}
735728
size_t numTrailingObjects(OverloadToken<Region>) const { return numRegions; }
736-
size_t numTrailingObjects(OverloadToken<Type>) const {
737-
return hasSingleResult ? 0 : resultTypeOrSize.size;
738-
}
739729
};
740730

741731
inline raw_ostream &operator<<(raw_ostream &os, Operation &op) {

mlir/lib/IR/Operation.cpp

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,8 @@ Operation *Operation::create(Location location, OperationName name,
123123
// into account the size of the operation, its trailing objects, and its
124124
// prefixed objects.
125125
size_t byteSize =
126-
totalSizeToAlloc<BlockOperand, Region, Type, detail::OperandStorage>(
127-
numSuccessors, numRegions,
128-
// Result type storage only needed if there is not 0 or 1 results.
129-
resultTypes.size() == 1 ? 0 : resultTypes.size(),
130-
needsOperandStorage ? 1 : 0) +
126+
totalSizeToAlloc<BlockOperand, Region, detail::OperandStorage>(
127+
numSuccessors, numRegions, needsOperandStorage ? 1 : 0) +
131128
detail::OperandStorage::additionalAllocSize(numOperands);
132129
size_t prefixByteSize = llvm::alignTo(
133130
Operation::prefixAllocSize(numTrailingResults, numInlineResults),
@@ -175,18 +172,13 @@ Operation::Operation(Location location, OperationName name,
175172
assert(attributes && "unexpected null attribute dictionary");
176173
assert(llvm::all_of(resultTypes, [](Type t) { return t; }) &&
177174
"unexpected null result type");
178-
if (resultTypes.empty()) {
179-
resultTypeOrSize.size = 0;
180-
} else {
181-
// If there is a single result it is stored in-place, otherwise use trailing
182-
// type storage.
175+
if (!resultTypes.empty()) {
176+
// If there is a single result it is stored in-place, otherwise use a tuple.
183177
hasSingleResult = resultTypes.size() == 1;
184-
if (hasSingleResult) {
185-
resultTypeOrSize.type = resultTypes.front();
186-
} else {
187-
resultTypeOrSize.size = resultTypes.size();
188-
llvm::copy(resultTypes, getTrailingObjects<Type>());
189-
}
178+
if (hasSingleResult)
179+
resultType = resultTypes.front();
180+
else
181+
resultType = TupleType::get(location->getContext(), resultTypes);
190182
}
191183
}
192184

@@ -553,15 +545,17 @@ void Operation::dropAllDefinedValueUses() {
553545

554546
/// Return the number of results held by this operation.
555547
unsigned Operation::getNumResults() {
556-
if (hasSingleResult)
557-
return 1;
558-
return resultTypeOrSize.size;
548+
if (!resultType)
549+
return 0;
550+
return hasSingleResult ? 1 : resultType.cast<TupleType>().size();
559551
}
560552

561553
auto Operation::getResultTypes() -> result_type_range {
554+
if (!resultType)
555+
return llvm::None;
562556
if (hasSingleResult)
563-
return resultTypeOrSize.type;
564-
return ArrayRef<Type>(getTrailingObjects<Type>(), resultTypeOrSize.size);
557+
return resultType;
558+
return resultType.cast<TupleType>().getTypes();
565559
}
566560

567561
void Operation::setSuccessor(Block *block, unsigned index) {

mlir/lib/IR/Value.cpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,31 @@ Type Value::getType() const {
3939
OpResult result = cast<OpResult>();
4040
Operation *owner = result.getOwner();
4141
if (owner->hasSingleResult)
42-
return owner->resultTypeOrSize.type;
43-
return owner->getResultTypes()[result.getResultNumber()];
42+
return owner->resultType;
43+
return owner->resultType.cast<TupleType>().getType(result.getResultNumber());
4444
}
4545

4646
/// Mutate the type of this Value to be of the specified type.
4747
void Value::setType(Type newType) {
4848
if (BlockArgument arg = dyn_cast<BlockArgument>())
4949
return arg.setType(newType);
50-
5150
OpResult result = cast<OpResult>();
51+
52+
// If the owner has a single result, simply update it directly.
5253
Operation *owner = result.getOwner();
53-
if (owner->hasSingleResult)
54-
owner->resultTypeOrSize.type = newType;
55-
else
56-
owner->getTrailingObjects<Type>()[result.getResultNumber()] = newType;
54+
if (owner->hasSingleResult) {
55+
owner->resultType = newType;
56+
return;
57+
}
58+
unsigned resultNo = result.getResultNumber();
59+
60+
// Otherwise, rebuild the tuple if the new type is different from the current.
61+
auto curTypes = owner->resultType.cast<TupleType>().getTypes();
62+
if (curTypes[resultNo] == newType)
63+
return;
64+
auto newTypes = llvm::to_vector<4>(curTypes);
65+
newTypes[resultNo] = newType;
66+
owner->resultType = TupleType::get(newType.getContext(), newTypes);
5767
}
5868

5969
/// If this value is the result of an Operation, return the operation that

0 commit comments

Comments
 (0)