diff --git a/mlir/include/mlir/IR/BuiltinAttributes.h b/mlir/include/mlir/IR/BuiltinAttributes.h --- a/mlir/include/mlir/IR/BuiltinAttributes.h +++ b/mlir/include/mlir/IR/BuiltinAttributes.h @@ -560,6 +560,11 @@ /// same total number of elements as well as element type. DenseElementsAttr reshape(ShapedType newType); + /// Return a new DenseElementsAttr that has the same data as the current + /// attribute, but has bitcast elements to 'newElType'. The new type must have + /// the same bitwidth as the current element type. + DenseElementsAttr bitcast(Type newElType); + /// Generates a new DenseElementsAttr by mapping each int value to a new /// underlying APInt. The new values can represent either an integer or float. /// This underlying type must be an DenseIntElementsAttr. diff --git a/mlir/lib/Dialect/StandardOps/IR/Ops.cpp b/mlir/lib/Dialect/StandardOps/IR/Ops.cpp --- a/mlir/lib/Dialect/StandardOps/IR/Ops.cpp +++ b/mlir/lib/Dialect/StandardOps/IR/Ops.cpp @@ -512,16 +512,8 @@ Type resType = getResult().getType(); - if (auto denseAttr = operand.dyn_cast()) { - Type elType = getElementTypeOrSelf(resType); - return denseAttr.mapValues( - elType, [](const APFloat &f) { return f.bitcastToAPInt(); }); - } - if (auto denseAttr = operand.dyn_cast()) { - Type elType = getElementTypeOrSelf(resType); - // mapValues does its own bitcast to the target type. - return denseAttr.mapValues(elType, [](const APInt &i) { return i; }); - } + if (auto denseAttr = operand.dyn_cast()) + return denseAttr.bitcast(resType.cast().getElementType()); APInt bits; if (auto floatAttr = operand.dyn_cast()) diff --git a/mlir/lib/IR/BuiltinAttributes.cpp b/mlir/lib/IR/BuiltinAttributes.cpp --- a/mlir/lib/IR/BuiltinAttributes.cpp +++ b/mlir/lib/IR/BuiltinAttributes.cpp @@ -1024,7 +1024,6 @@ if (curType == newType) return *this; - (void)curType; assert(newType.getElementType() == curType.getElementType() && "expected the same element type"); assert(newType.getNumElements() == curType.getNumElements() && @@ -1032,6 +1031,23 @@ return DenseIntOrFPElementsAttr::getRaw(newType, getRawData(), isSplat()); } +/// Return a new DenseElementsAttr that has the same data as the current +/// attribute, but has bitcast elements such that it is now 'newType'. The new +/// type must have the same shape and element types of the same bitwidth as the +/// current type. +DenseElementsAttr DenseElementsAttr::bitcast(Type newElType) { + ShapedType curType = getType(); + Type curElType = curType.getElementType(); + if (curElType == newElType) + return *this; + + assert(getDenseElementBitWidth(newElType) == + getDenseElementBitWidth(curElType) && + "expected element types with the same bitwidth"); + return DenseIntOrFPElementsAttr::getRaw(curType.clone(newElType), + getRawData(), isSplat()); +} + DenseElementsAttr DenseElementsAttr::mapValues(Type newElementType, function_ref mapping) const {