Integrate LLVM at llvm/llvm-project@7189c4bb83d9 (#2945)
diff --git a/build_tools/llvm_version.txt b/build_tools/llvm_version.txt
index 2f585f1..a66a072 100644
--- a/build_tools/llvm_version.txt
+++ b/build_tools/llvm_version.txt
@@ -1 +1 @@
-2cf353b5e8560723409f3f9164bddec76f499963
+7189c4bb83d90c383741a9480fceca9c7bf74b27
diff --git a/docs/generated/chlo.md b/docs/generated/chlo.md
index 631f037..ade2255 100755
--- a/docs/generated/chlo.md
+++ b/docs/generated/chlo.md
@@ -1778,6 +1778,7 @@
<table>
<tr><th>Attribute</th><th>MLIR Type</th><th>Description</th></tr>
<tr><td><code>dimension</code></td><td>::mlir::IntegerAttr</td><td>64-bit signless integer attribute whose value is non-negative</td></tr>
+<tr><td><code>scan_dim_size</code></td><td>::mlir::IntegerAttr</td><td>64-bit signless integer attribute whose value is non-negative</td></tr>
<tr><td><code>is_reverse</code></td><td>::mlir::BoolAttr</td><td>bool attribute</td></tr>
<tr><td><code>is_associative</code></td><td>::mlir::BoolAttr</td><td>bool attribute</td></tr>
</table>
diff --git a/stablehlo/dialect/ChloOps.cpp b/stablehlo/dialect/ChloOps.cpp
index fd2df07..637f424 100644
--- a/stablehlo/dialect/ChloOps.cpp
+++ b/stablehlo/dialect/ChloOps.cpp
@@ -805,6 +805,9 @@
// output dimension size will be dynamic as well.
int64_t dim = adaptor.getDimension();
int64_t dimSize = ShapedType::kDynamic;
+ if (adaptor.getScanDimSize().has_value()) {
+ dimSize = adaptor.getScanDimSize().value();
+ }
for (auto [i, type] : llvm::enumerate(adaptor.getInputs().getTypes())) {
auto inputType = dyn_cast<RankedTensorType>(type);
if (!inputType) {
@@ -814,9 +817,8 @@
return emitOptionalError(location, "scan dimension of operand ", i,
" is out of bounds");
}
- dimSize = inputType.getDimSize(dim);
if (dimSize == ShapedType::kDynamic) {
- break;
+ dimSize = inputType.getDimSize(dim);
}
}
@@ -837,34 +839,6 @@
return success();
}
-LogicalResult ScanOp::reifyReturnTypeShapes(
- OpBuilder& builder, ValueRange operands,
- SmallVectorImpl<Value>& reifiedReturnShapes) {
- ScanOp::Adaptor adaptor(operands, getOperation()->getAttrDictionary(),
- getOperation()->getPropertiesStorage());
- auto inputs = adaptor.getInputs();
- size_t k = adaptor.getInits().size();
- size_t numResults = getOperation()->getNumResults();
- size_t numOutputs = numResults - k;
-
- for (size_t i = 0; i < numOutputs; ++i) {
- size_t inputIdx = i;
- Value inputVal = (inputIdx < inputs.size()) ? inputs[inputIdx] : inputs[0];
- if (failed(hlo::deriveShapeFromOperand(&builder, getOperation(), inputVal,
- &reifiedReturnShapes))) {
- return failure();
- }
- }
-
- for (auto init : adaptor.getInits()) {
- if (failed(hlo::deriveShapeFromOperand(&builder, getOperation(), init,
- &reifiedReturnShapes))) {
- return failure();
- }
- }
- return success();
-}
-
LogicalResult ScanOp::verify() {
if (getInputs().empty() && getOutputs().empty()) {
return emitOpError() << "at least one of inputs or outputs must be present";
@@ -873,7 +847,7 @@
// Check that the scan dimension is in bounds for all operands. Also check
// that all operands have the same scan dimension size.
int64_t dim = getDimension();
- int64_t dimSize = ShapedType::kDynamic;
+ std::optional<uint64_t> dimSize = getScanDimSize();
for (auto [i, type] : llvm::enumerate(getInputs().getTypes())) {
auto inputType = dyn_cast<RankedTensorType>(type);
if (!inputType) {
@@ -886,13 +860,11 @@
if (inputType.isDynamicDim(dim)) {
continue;
}
- dimSize = inputType.getDimSize(dim);
- if (dimSize != ShapedType::kDynamic &&
- dimSize != inputType.getDimSize(dim)) {
- return emitOpError() << "scan dimension size of operand " << i
- << " does not match previous operands";
+ uint64_t currentDimSize = inputType.getDimSize(dim);
+ if (dimSize.has_value() && dimSize.value() != currentDimSize) {
+ return emitOpError() << "invalid scan dimension size of operand " << i;
}
- dimSize = inputType.getDimSize(dim);
+ dimSize = currentDimSize;
}
Block& bodyBlock = getBody().front();
@@ -936,20 +908,22 @@
parser.parseKeyword("inits") ||
parser.parseOperandList(inits, OpAsmParser::Delimiter::Paren) ||
parser.parseKeyword("dimension") || parser.parseEqual() ||
- parser.parseInteger(dimension) || parser.parseRegion(*body) ||
- parser.parseOptionalAttrDict(result.attributes) ||
- parser.parseColonType(funcType)) {
+ parser.parseInteger(dimension) ||
+ parser.parseOptionalAttrDictWithKeyword(result.attributes) ||
+ parser.parseRegion(*body) || parser.parseColonType(funcType)) {
return failure();
}
- size_t numInputs = inputs.size();
- size_t numCarries = inits.size();
- if (funcType.getInputs().size() != numInputs + numCarries) {
+ int32_t numInputs = inputs.size();
+ int32_t numCarries = inits.size();
+ int32_t numOutputs = funcType.getNumResults() - numCarries;
+ if (static_cast<int64_t>(funcType.getInputs().size()) !=
+ static_cast<int64_t>(numInputs + numCarries)) {
return parser.emitError(
parser.getNameLoc(),
"operand types must match the number of inputs and inits");
}
- if (funcType.getResults().size() < numCarries) {
+ if (numOutputs < 0) {
return parser.emitError(
parser.getNameLoc(),
"not enough result types to cover the required carries");
@@ -968,13 +942,10 @@
Builder& builder = parser.getBuilder();
result.addAttribute(ScanOp::getDimensionAttrName(result.name),
builder.getI64IntegerAttr(dimension));
- result.addAttribute(
- ScanOp::getOperandSegmentSizeAttr(),
- builder.getDenseI32ArrayAttr({(int32_t)numInputs, (int32_t)numCarries}));
- size_t numOutputs = funcType.getNumResults() - numCarries;
- result.addAttribute(
- ScanOp::getResultSegmentSizeAttr(),
- builder.getDenseI32ArrayAttr({(int32_t)numOutputs, (int32_t)numCarries}));
+ result.addAttribute(ScanOp::getOperandSegmentSizeAttr(),
+ builder.getDenseI32ArrayAttr({numInputs, numCarries}));
+ result.addAttribute(ScanOp::getResultSegmentSizeAttr(),
+ builder.getDenseI32ArrayAttr({numOutputs, numCarries}));
return success();
}
@@ -985,10 +956,12 @@
p << ") inits (";
p.printOperands(getInits());
p << ") dimension=" << getDimension() << " ";
+ p.printOptionalAttrDictWithKeyword(
+ getOperation()->getAttrs(),
+ /*elidedAttrs=*/{"dimension", "operandSegmentSizes",
+ "resultSegmentSizes"});
+ p << " ";
p.printRegion(getBody(), /*printEntryBlockArgs=*/true);
- p.printOptionalAttrDict(getOperation()->getAttrs(),
- /*elidedAttrs=*/{"dimension", "operandSegmentSizes",
- "resultSegmentSizes"});
p << " : ";
p.printFunctionalType(*this);
}
diff --git a/stablehlo/dialect/ChloOps.td b/stablehlo/dialect/ChloOps.td
index 7defd25..676e7a0 100644
--- a/stablehlo/dialect/ChloOps.td
+++ b/stablehlo/dialect/ChloOps.td
@@ -938,7 +938,7 @@
def CHLO_ScanOp : CHLO_Op<"scan", [
AttrSizedOperandSegments,
AttrSizedResultSegments,
- InferTensorTypeWithReify,
+ InferTensorType,
IsolatedFromAbove,
OpAsmOpInterface,
RecursiveMemoryEffects,
@@ -961,6 +961,7 @@
Variadic<HLO_AnyTensor>:$inputs,
Variadic<HLO_AnyTensor>:$inits,
ConfinedAttr<I64Attr, [IntNonNegative]>:$dimension,
+ OptionalAttr<ConfinedAttr<I64Attr, [IntNonNegative]>>:$scan_dim_size,
DefaultValuedOptionalAttr<BoolAttr, "false">:$is_reverse,
OptionalAttr<BoolAttr>:$is_associative
);
diff --git a/stablehlo/dialect/TypeInference.cpp b/stablehlo/dialect/TypeInference.cpp
index ca0ba28..8203ea3 100644
--- a/stablehlo/dialect/TypeInference.cpp
+++ b/stablehlo/dialect/TypeInference.cpp
@@ -2110,11 +2110,22 @@
inferredBounds[dim] = inferredDimAndBound.second;
}
}
+ Attribute witnessEncoding;
+ for (auto inputType : inputTypes) {
+ if (auto rankedType = dyn_cast<RankedTensorType>(inputType)) {
+ if (rankedType.getEncoding()) {
+ witnessEncoding = rankedType.getEncoding();
+ break;
+ }
+ }
+ }
+ if (!witnessEncoding) witnessEncoding = witnessType.getEncoding();
+
// concatenate_c5, concatenate_c6
inferredReturnTypes.push_back(RankedTensorType::get(
inferredSizes, witnessType.getElementType(),
boundsToEncoding(
- witnessType.getEncoding(),
+ witnessEncoding,
// Empty array as argument is an indicator to boundsToEncoding()
// that there are no bounds at all in inputs, thus sparsity
// attributes will be included in the return type
diff --git a/stablehlo/dialect/VhloAttrs.td b/stablehlo/dialect/VhloAttrs.td
index a8d3cc0..1d21552 100644
--- a/stablehlo/dialect/VhloAttrs.td
+++ b/stablehlo/dialect/VhloAttrs.td
@@ -127,16 +127,13 @@
}
// Corresponds to TensorConstant from the StableHLO spec.
-def VHLO_TensorDataV1 : AttrParameter<"::llvm::ArrayRef<char>", ""> {
- let allocator = "$_dst = $_allocator.copyInto($_self);";
-}
def VHLO_TensorAttrV1 : VHLO_AttrDef<"TensorV1", "0.9.0", "current"> {
let mnemonic = "tensor_v1";
- let parameters = (ins "::mlir::Type":$type, VHLO_TensorDataV1:$data);
+ let parameters = (ins "::mlir::Type":$type, "DenseElementsAttr":$data);
let genVerifyDecl = 1;
let extraClassDefinition = [{
LogicalResult TensorV1Attr::verify(
- llvm::function_ref<mlir::InFlightDiagnostic ()> errFn, mlir::Type type, ArrayRef<char>) {
+ llvm::function_ref<mlir::InFlightDiagnostic ()> errFn, mlir::Type type, DenseElementsAttr) {
if (!isFromVhlo(type)) errFn() << "expected VHLO type";
return success();
}
diff --git a/stablehlo/dialect/VhloBytecode.cpp b/stablehlo/dialect/VhloBytecode.cpp
index 01e18c7..73fa509 100644
--- a/stablehlo/dialect/VhloBytecode.cpp
+++ b/stablehlo/dialect/VhloBytecode.cpp
@@ -1049,13 +1049,13 @@
static void writeVhloTensorV1Attr(DialectBytecodeWriter& writer,
vhlo::TensorV1Attr attr) {
if (!isBooleanType(attr.getType())) {
- writer.writeOwnedBlob(attr.getData());
+ writer.writeOwnedBlob(attr.getData().getRawData());
return;
}
// Pack the data if i1
SmallVector<char> data;
- ArrayRef<char> rawData = attr.getData();
+ ArrayRef<char> rawData = attr.getData().getRawData();
auto numElements = cast<RankedTensorV1Type>(attr.getType()).getNumElements();
// If the attribute is a splat, we can just splat the value directly.
@@ -1085,7 +1085,18 @@
if (failed(reader.readType(type)) ||
failed(readVhloTensorV1Attr(reader, type, blob)))
return TensorV1Attr();
- return TensorV1Attr::get(getContext(), type, blob);
+ struct VhloToBuiltinPrintConverter : VhloTypeConverter {
+ VhloToBuiltinPrintConverter() : VhloTypeConverter() {
+ addVhloToBuiltinConversions();
+ }
+ Attribute convertEncoding(Attribute attr) const override { return attr; }
+ };
+
+ VhloToBuiltinPrintConverter conv;
+ auto builtinType = cast<ShapedType>(conv.convertType(type));
+ return TensorV1Attr::get(
+ getContext(), type,
+ DenseElementsAttr::getFromRawBuffer(builtinType, blob));
}
void VhloBytecodeInterface::write(TensorV1Attr attr,
diff --git a/stablehlo/dialect/VhloOps.cpp b/stablehlo/dialect/VhloOps.cpp
index 53ed964..886b47a 100644
--- a/stablehlo/dialect/VhloOps.cpp
+++ b/stablehlo/dialect/VhloOps.cpp
@@ -185,12 +185,7 @@
}
void TensorV1Attr::print(mlir::AsmPrinter& odsPrinter) const {
- odsPrinter << '<'
- << DenseTypedElementsAttr::getFromRawBuffer(
- llvm::cast<ShapedType>(
- convertTypeToBuiltinForPrint(getType())),
- getData())
- << '>';
+ odsPrinter << '<' << getData() << '>';
}
// Parse tensor elements using DenseTypedElementsAttr printing.
@@ -201,8 +196,7 @@
return TensorV1Attr();
}
return TensorV1Attr::get(parser.getContext(),
- convertTypeToVhloForParse(attr.getType()),
- attr.getRawData());
+ convertTypeToVhloForParse(attr.getType()), attr);
}
void printEscapedString(AsmPrinter& p, llvm::StringRef value) {
diff --git a/stablehlo/integrations/c/StablehloAttributes.cpp b/stablehlo/integrations/c/StablehloAttributes.cpp
index 3be3dd2..473e316 100644
--- a/stablehlo/integrations/c/StablehloAttributes.cpp
+++ b/stablehlo/integrations/c/StablehloAttributes.cpp
@@ -754,3 +754,136 @@
llvm::cast<mlir::stablehlo::ResultAccuracyAttr>(unwrap(attr)).getMode();
return wrap(modeAttr);
}
+
+//===----------------------------------------------------------------------===//
+// SubAxisInfo
+//===----------------------------------------------------------------------===//
+
+MlirAttribute stablehloSubAxisInfoAttrGet(MlirContext ctx, int64_t preSize,
+ int64_t size) {
+ return wrap(
+ mlir::stablehlo::SubAxisInfoAttr::get(unwrap(ctx), preSize, size));
+}
+
+bool stablehloAttributeIsASubAxisInfoAttr(MlirAttribute attr) {
+ return llvm::isa<mlir::stablehlo::SubAxisInfoAttr>(unwrap(attr));
+}
+
+int64_t stablehloSubAxisInfoAttrGetPreSize(MlirAttribute attr) {
+ return llvm::cast<mlir::stablehlo::SubAxisInfoAttr>(unwrap(attr))
+ .getPreSize();
+}
+
+int64_t stablehloSubAxisInfoAttrGetSize(MlirAttribute attr) {
+ return llvm::cast<mlir::stablehlo::SubAxisInfoAttr>(unwrap(attr)).getSize();
+}
+
+//===----------------------------------------------------------------------===//
+// AxisRef
+//===----------------------------------------------------------------------===//
+
+MlirAttribute stablehloAxisRefAttrGet(MlirContext ctx, MlirStringRef name,
+ MlirAttribute subAxisInfo) {
+ return wrap(mlir::stablehlo::AxisRefAttr::get(
+ unwrap(ctx), unwrap(name),
+ llvm::cast_or_null<mlir::stablehlo::SubAxisInfoAttr>(
+ unwrap(subAxisInfo))));
+}
+
+bool stablehloAttributeIsAnAxisRefAttr(MlirAttribute attr) {
+ return llvm::isa<mlir::stablehlo::AxisRefAttr>(unwrap(attr));
+}
+
+MlirStringRef stablehloAxisRefAttrGetName(MlirAttribute attr) {
+ return wrap(llvm::cast<mlir::stablehlo::AxisRefAttr>(unwrap(attr)).getName());
+}
+
+MlirAttribute stablehloAxisRefAttrGetSubAxisInfo(MlirAttribute attr) {
+ return wrap(
+ llvm::cast<mlir::stablehlo::AxisRefAttr>(unwrap(attr)).getSubAxisInfo());
+}
+
+//===----------------------------------------------------------------------===//
+// ReplicaGroupMeshAxes
+//===----------------------------------------------------------------------===//
+
+MlirAttribute stablehloReplicaGroupMeshAxesAttrGet(MlirContext ctx,
+ MlirAttribute mesh,
+ MlirAttribute axes) {
+ return wrap(mlir::stablehlo::ReplicaGroupMeshAxesAttr::get(
+ unwrap(ctx), unwrap(mesh), llvm::cast<mlir::ArrayAttr>(unwrap(axes))));
+}
+
+bool stablehloAttributeIsAReplicaGroupMeshAxesAttr(MlirAttribute attr) {
+ return llvm::isa<mlir::stablehlo::ReplicaGroupMeshAxesAttr>(unwrap(attr));
+}
+
+MlirAttribute stablehloReplicaGroupMeshAxesAttrGetMesh(MlirAttribute attr) {
+ return wrap(
+ llvm::cast<mlir::stablehlo::ReplicaGroupMeshAxesAttr>(unwrap(attr))
+ .getMesh());
+}
+
+MlirAttribute stablehloReplicaGroupMeshAxesAttrGetAxes(MlirAttribute attr) {
+ return wrap(
+ llvm::cast<mlir::stablehlo::ReplicaGroupMeshAxesAttr>(unwrap(attr))
+ .getAxes());
+}
+
+//===----------------------------------------------------------------------===//
+// MeshAxis
+//===----------------------------------------------------------------------===//
+
+MlirAttribute stablehloMeshAxisAttrGet(MlirContext ctx, MlirStringRef name,
+ int64_t size) {
+ return wrap(
+ mlir::stablehlo::MeshAxisAttr::get(unwrap(ctx), unwrap(name), size));
+}
+
+bool stablehloAttributeIsAMeshAxisAttr(MlirAttribute attr) {
+ return llvm::isa<mlir::stablehlo::MeshAxisAttr>(unwrap(attr));
+}
+
+MlirStringRef stablehloMeshAxisAttrGetName(MlirAttribute attr) {
+ return wrap(
+ llvm::cast<mlir::stablehlo::MeshAxisAttr>(unwrap(attr)).getName());
+}
+
+int64_t stablehloMeshAxisAttrGetSize(MlirAttribute attr) {
+ return llvm::cast<mlir::stablehlo::MeshAxisAttr>(unwrap(attr)).getSize();
+}
+
+//===----------------------------------------------------------------------===//
+// Mesh
+//===----------------------------------------------------------------------===//
+
+MlirAttribute stablehloMeshAttrGet(MlirContext ctx, MlirAttribute axes,
+ MlirAttribute deviceIds) {
+ auto axesAttr = llvm::cast<mlir::ArrayAttr>(unwrap(axes));
+ llvm::SmallVector<mlir::stablehlo::MeshAxisAttr> meshAxes;
+ for (auto attr : axesAttr) {
+ meshAxes.push_back(llvm::cast<mlir::stablehlo::MeshAxisAttr>(attr));
+ }
+ return wrap(mlir::stablehlo::MeshAttr::get(
+ unwrap(ctx), meshAxes,
+ llvm::cast_or_null<mlir::DenseIntElementsAttr>(unwrap(deviceIds))));
+}
+
+bool stablehloAttributeIsAMeshAttr(MlirAttribute attr) {
+ return llvm::isa<mlir::stablehlo::MeshAttr>(unwrap(attr));
+}
+
+MlirAttribute stablehloMeshAttrGetAxes(MlirAttribute attr) {
+ auto meshAttr = llvm::cast<mlir::stablehlo::MeshAttr>(unwrap(attr));
+ llvm::SmallVector<mlir::Attribute> attrs;
+ for (auto axis : meshAttr.getAxes()) {
+ attrs.push_back(axis);
+ }
+ return wrap(mlir::ArrayAttr::get(meshAttr.getContext(), attrs));
+}
+
+MlirAttribute stablehloMeshAttrGetDeviceIds(MlirAttribute attr) {
+ auto deviceIds =
+ llvm::cast<mlir::stablehlo::MeshAttr>(unwrap(attr)).getDeviceIds();
+ return wrap(deviceIds);
+}
diff --git a/stablehlo/integrations/c/StablehloAttributes.h b/stablehlo/integrations/c/StablehloAttributes.h
index 8ea0653..8ac2328 100644
--- a/stablehlo/integrations/c/StablehloAttributes.h
+++ b/stablehlo/integrations/c/StablehloAttributes.h
@@ -413,6 +413,73 @@
MLIR_CAPI_EXPORTED MlirAttribute
stablehloResultAccuracyAttrGetMode(MlirAttribute attr);
+//===----------------------------------------------------------------------===//
+// SubAxisInfo
+//===----------------------------------------------------------------------===//
+
+MLIR_CAPI_EXPORTED MlirAttribute stablehloSubAxisInfoAttrGet(MlirContext ctx,
+ int64_t preSize,
+ int64_t size);
+
+MLIR_CAPI_EXPORTED bool stablehloAttributeIsASubAxisInfoAttr(
+ MlirAttribute attr);
+MLIR_CAPI_EXPORTED int64_t
+stablehloSubAxisInfoAttrGetPreSize(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int64_t stablehloSubAxisInfoAttrGetSize(MlirAttribute attr);
+
+//===----------------------------------------------------------------------===//
+// AxisRef
+//===----------------------------------------------------------------------===//
+
+MLIR_CAPI_EXPORTED MlirAttribute stablehloAxisRefAttrGet(
+ MlirContext ctx, MlirStringRef name, MlirAttribute subAxisInfo);
+
+MLIR_CAPI_EXPORTED bool stablehloAttributeIsAnAxisRefAttr(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirStringRef
+stablehloAxisRefAttrGetName(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirAttribute
+stablehloAxisRefAttrGetSubAxisInfo(MlirAttribute attr);
+
+//===----------------------------------------------------------------------===//
+// ReplicaGroupMeshAxes
+//===----------------------------------------------------------------------===//
+
+MLIR_CAPI_EXPORTED MlirAttribute stablehloReplicaGroupMeshAxesAttrGet(
+ MlirContext ctx, MlirAttribute mesh, MlirAttribute axes);
+
+MLIR_CAPI_EXPORTED bool stablehloAttributeIsAReplicaGroupMeshAxesAttr(
+ MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirAttribute
+stablehloReplicaGroupMeshAxesAttrGetMesh(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirAttribute
+stablehloReplicaGroupMeshAxesAttrGetAxes(MlirAttribute attr);
+
+//===----------------------------------------------------------------------===//
+// MeshAxis
+//===----------------------------------------------------------------------===//
+
+MLIR_CAPI_EXPORTED MlirAttribute stablehloMeshAxisAttrGet(MlirContext ctx,
+ MlirStringRef name,
+ int64_t size);
+
+MLIR_CAPI_EXPORTED bool stablehloAttributeIsAMeshAxisAttr(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirStringRef
+stablehloMeshAxisAttrGetName(MlirAttribute attr);
+MLIR_CAPI_EXPORTED int64_t stablehloMeshAxisAttrGetSize(MlirAttribute attr);
+
+//===----------------------------------------------------------------------===//
+// Mesh
+//===----------------------------------------------------------------------===//
+
+MLIR_CAPI_EXPORTED MlirAttribute stablehloMeshAttrGet(MlirContext ctx,
+ MlirAttribute axes,
+ MlirAttribute deviceIds);
+
+MLIR_CAPI_EXPORTED bool stablehloAttributeIsAMeshAttr(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirAttribute stablehloMeshAttrGetAxes(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirAttribute
+stablehloMeshAttrGetDeviceIds(MlirAttribute attr);
+
#ifdef __cplusplus
}
#endif
diff --git a/stablehlo/integrations/python/StablehloModule.cpp b/stablehlo/integrations/python/StablehloModule.cpp
index ecd3975..7cd0fd1 100644
--- a/stablehlo/integrations/python/StablehloModule.cpp
+++ b/stablehlo/integrations/python/StablehloModule.cpp
@@ -663,6 +663,121 @@
});
mlir::python::nanobind_adaptors::mlir_attribute_subclass(
+ m, "SubAxisInfoAttr", stablehloAttributeIsASubAxisInfoAttr)
+ .def_classmethod(
+ "get",
+ [](nb::object cls, int64_t preSize, int64_t size, MlirContext ctx) {
+ return cls(stablehloSubAxisInfoAttrGet(ctx, preSize, size));
+ },
+ nb::arg("cls"), nb::arg("pre_size"), nb::arg("size"),
+ nb::arg("context").none() = nb::none(),
+ "Creates a SubAxisInfoAttr with the given pre_size and size.")
+ .def_property_readonly("pre_size",
+ [](MlirAttribute self) {
+ return stablehloSubAxisInfoAttrGetPreSize(self);
+ })
+ .def_property_readonly("size", [](MlirAttribute self) {
+ return stablehloSubAxisInfoAttrGetSize(self);
+ });
+
+ mlir::python::nanobind_adaptors::mlir_attribute_subclass(
+ m, "AxisRefAttr", stablehloAttributeIsAnAxisRefAttr)
+ .def_classmethod(
+ "get",
+ [](nb::object cls, const std::string& name,
+ std::optional<MlirAttribute> subAxisInfo, MlirContext ctx) {
+ return cls(stablehloAxisRefAttrGet(
+ ctx, mlirStringRefCreate(name.c_str(), name.size()),
+ subAxisInfo.has_value() ? *subAxisInfo
+ : MlirAttribute{nullptr}));
+ },
+ nb::arg("cls"), nb::arg("name"),
+ nb::arg("sub_axis_info").none() = nb::none(),
+ nb::arg("context").none() = nb::none(),
+ "Creates an AxisRefAttr with the given name and optional "
+ "sub_axis_info.")
+ .def_property_readonly(
+ "name",
+ [](MlirAttribute self) {
+ return toPyString(stablehloAxisRefAttrGetName(self));
+ })
+ .def_property_readonly("sub_axis_info", [](MlirAttribute self) {
+ MlirAttribute subAxisInfo = stablehloAxisRefAttrGetSubAxisInfo(self);
+ if (mlirAttributeIsNull(subAxisInfo)) {
+ return nb::cast(std::optional<MlirAttribute>(std::nullopt));
+ }
+ return nb::cast(std::optional<MlirAttribute>(subAxisInfo));
+ });
+
+ mlir::python::nanobind_adaptors::mlir_attribute_subclass(
+ m, "ReplicaGroupMeshAxesAttr",
+ stablehloAttributeIsAReplicaGroupMeshAxesAttr)
+ .def_classmethod(
+ "get",
+ [](nb::object cls, MlirAttribute mesh, MlirAttribute axes,
+ MlirContext ctx) {
+ return cls(stablehloReplicaGroupMeshAxesAttrGet(ctx, mesh, axes));
+ },
+ nb::arg("cls"), nb::arg("mesh"), nb::arg("axes"),
+ nb::arg("context").none() = nb::none(),
+ "Creates a ReplicaGroupMeshAxesAttr with the given mesh and "
+ "axes.")
+ .def_property_readonly(
+ "mesh",
+ [](MlirAttribute self) {
+ return stablehloReplicaGroupMeshAxesAttrGetMesh(self);
+ })
+ .def_property_readonly("axes", [](MlirAttribute self) {
+ return stablehloReplicaGroupMeshAxesAttrGetAxes(self);
+ });
+
+ mlir::python::nanobind_adaptors::mlir_attribute_subclass(
+ m, "MeshAxisAttr", stablehloAttributeIsAMeshAxisAttr)
+ .def_classmethod(
+ "get",
+ [](nb::object cls, const std::string& name, int64_t size,
+ MlirContext ctx) {
+ return cls(stablehloMeshAxisAttrGet(
+ ctx, mlirStringRefCreate(name.c_str(), name.size()), size));
+ },
+ nb::arg("cls"), nb::arg("name"), nb::arg("size"),
+ nb::arg("context").none() = nb::none(),
+ "Creates a MeshAxisAttr with the given name and size.")
+ .def_property_readonly(
+ "name",
+ [](MlirAttribute self) {
+ return toPyString(stablehloMeshAxisAttrGetName(self));
+ })
+ .def_property_readonly("size", [](MlirAttribute self) {
+ return stablehloMeshAxisAttrGetSize(self);
+ });
+
+ mlir::python::nanobind_adaptors::mlir_attribute_subclass(
+ m, "MeshAttr", stablehloAttributeIsAMeshAttr)
+ .def_classmethod(
+ "get",
+ [](nb::object cls, MlirAttribute axes,
+ std::optional<MlirAttribute> deviceIds, MlirContext ctx) {
+ return cls(stablehloMeshAttrGet(
+ ctx, axes,
+ deviceIds.has_value() ? *deviceIds : MlirAttribute{nullptr}));
+ },
+ nb::arg("cls"), nb::arg("axes"),
+ nb::arg("device_ids").none() = nb::none(),
+ nb::arg("context").none() = nb::none(),
+ "Creates a MeshAttr with the given axes and optional device_ids.")
+ .def_property_readonly(
+ "axes",
+ [](MlirAttribute self) { return stablehloMeshAttrGetAxes(self); })
+ .def_property_readonly("device_ids", [](MlirAttribute self) {
+ MlirAttribute deviceIds = stablehloMeshAttrGetDeviceIds(self);
+ if (mlirAttributeIsNull(deviceIds)) {
+ return nb::cast(std::optional<MlirAttribute>(std::nullopt));
+ }
+ return nb::cast(std::optional<MlirAttribute>(deviceIds));
+ });
+
+ mlir::python::nanobind_adaptors::mlir_attribute_subclass(
m, "ResultAccuracyModeAttr", stablehloAttributeIsAResultAccuracyModeAttr)
.def_classmethod(
"get",
diff --git a/stablehlo/integrations/python/tests/stablehlo.py b/stablehlo/integrations/python/tests/stablehlo.py
index ae0cdbd..a91902a 100644
--- a/stablehlo/integrations/python/tests/stablehlo.py
+++ b/stablehlo/integrations/python/tests/stablehlo.py
@@ -264,6 +264,41 @@
@run
+def test_replica_group_mesh_axes_attr():
+ sub_axis = stablehlo.SubAxisInfoAttr.get(pre_size=2, size=4)
+ assert sub_axis is not None
+ assert str(sub_axis) == "#stablehlo<sub_axis_info(2)4>"
+ assert sub_axis.pre_size == 2
+ assert sub_axis.size == 4
+
+ axis_ref = stablehlo.AxisRefAttr.get(name="x", sub_axis_info=sub_axis)
+ assert axis_ref is not None
+ assert (
+ str(axis_ref) == '#stablehlo.axis_ref<name = "x", sub_axis_info = (2)4>'
+ )
+ assert axis_ref.name == "x"
+ assert axis_ref.sub_axis_info == sub_axis
+
+ axis_ref_simple = stablehlo.AxisRefAttr.get(name="y")
+ assert axis_ref_simple is not None
+ assert str(axis_ref_simple) == '#stablehlo.axis_ref<name = "y">'
+ assert axis_ref_simple.name == "y"
+
+ mesh_name = ir.FlatSymbolRefAttr.get("mesh")
+ axes = ir.ArrayAttr.get([axis_ref, axis_ref_simple])
+ rg_attr = stablehlo.ReplicaGroupMeshAxesAttr.get(mesh=mesh_name, axes=axes)
+ assert rg_attr is not None
+ assert rg_attr.mesh == mesh_name
+ assert rg_attr.axes == axes
+ assert (
+ str(rg_attr)
+ == "#stablehlo.replica_group_mesh_axes<mesh = @mesh, axes ="
+ ' [#stablehlo.axis_ref<name = "x", sub_axis_info = (2)4>,'
+ ' #stablehlo.axis_ref<name = "y">]>'
+ )
+
+
+@run
def test_api_version():
api_version = stablehlo.get_api_version()
assert type(api_version) == int
@@ -271,7 +306,7 @@
def is_semver_format(version_str):
- return re.match("^\d+\.\d+\.\d+$", version_str)
+ return re.match(r"^\d+\.\d+\.\d+$", version_str)
@run
@@ -462,17 +497,18 @@
metadata_file
), f"Metadata file not found: {metadata_file}"
+
# Disabling to avoid jax dependency.
-#@run
-#def test_reference_api_with_probe():
+# @run
+# def test_reference_api_with_probe():
# from jax.interpreters import mlir
# import jax.numpy as jnp
# """Tests that probe files are created in the specified directory."""
# _run_probe_test("f32", np.asarray(2, np.float32))
# Disabling to avoid jax dependency.
-#@run
-#def test_reference_api_with_probe_bf16():
+# @run
+# def test_reference_api_with_probe_bf16():
# from jax.interpreters import mlir
# import jax.numpy as jnp
# """Tests that probe files are created for bf16 tensors."""
diff --git a/stablehlo/tests/infer_stablehlo.mlir b/stablehlo/tests/infer_stablehlo.mlir
index fea50ae..0730740 100644
--- a/stablehlo/tests/infer_stablehlo.mlir
+++ b/stablehlo/tests/infer_stablehlo.mlir
@@ -2076,3 +2076,15 @@
%1 = "hlo_test_infer.reify_return_type_shapes"(%0) : (tensor<?x?x?x?xf32>) -> tensor<4xindex>
func.return %1 : tensor<4xindex>
}
+
+// CHECK-LABEL: @concat_bounds_mixed_static_first
+func.func @concat_bounds_mixed_static_first(
+ %arg0: tensor<5x2xi32>,
+ %arg1: tensor<5x?xi32, #stablehlo.bounds<?, 4>>) -> tensor<?x?xindex> {
+ %result = "stablehlo.concatenate"(%arg0, %arg1) { dimension = 1 : i64 } : (
+ tensor<5x2xi32>,
+ tensor<5x?xi32, #stablehlo.bounds<?, 4>>) -> tensor<?x?xi32>
+ // CHECK: types0 = tensor<5x?xi32, #stablehlo.bounds<?, 6>>
+ %1 = "hlo_test_infer.get_return_types"(%result) : (tensor<?x?xi32>) -> tensor<?x?xindex>
+ func.return %1 : tensor<?x?xindex>
+}
diff --git a/stablehlo/tests/ops_chlo.mlir b/stablehlo/tests/ops_chlo.mlir
index 0886643..75d6f0a 100644
--- a/stablehlo/tests/ops_chlo.mlir
+++ b/stablehlo/tests/ops_chlo.mlir
@@ -423,7 +423,49 @@
// CHECK-LABEL: func @scan
func.func @scan(%arg0: tensor<2x3xf32>, %arg1: tensor<3xf32>) -> tensor<2x3xf32> {
// CHECK: chlo.scan
- %0, %1 = chlo.scan (%arg0) inits (%arg1) dimension = 0 {
+ %0, %1 = chlo.scan (%arg0) inits (%arg1) dimension = 0 attributes {} {
+ ^bb0(%input0: tensor<3xf32>, %carry0: tensor<3xf32>):
+ %2 = stablehlo.add %input0, %carry0 : tensor<3xf32>
+ stablehlo.return %2, %2 : tensor<3xf32>, tensor<3xf32>
+ } : (tensor<2x3xf32>, tensor<3xf32>) -> (tensor<2x3xf32>, tensor<3xf32>)
+ func.return %0 : tensor<2x3xf32>
+}
+
+// -----
+
+// CHECK-LABEL: func @scan_explicit_size
+func.func @scan_explicit_size(%arg0: tensor<2x3xf32>, %arg1: tensor<3xf32>) -> tensor<2x3xf32> {
+ // CHECK: chlo.scan
+ // CHECK: scan_dim_size = 2 : i64
+ %0, %1 = chlo.scan (%arg0) inits (%arg1) dimension = 0 attributes { scan_dim_size = 2 : i64 } {
+ ^bb0(%input0: tensor<3xf32>, %carry0: tensor<3xf32>):
+ %2 = stablehlo.add %input0, %carry0 : tensor<3xf32>
+ stablehlo.return %2, %2 : tensor<3xf32>, tensor<3xf32>
+ } : (tensor<2x3xf32>, tensor<3xf32>) -> (tensor<2x3xf32>, tensor<3xf32>)
+ func.return %0 : tensor<2x3xf32>
+}
+
+// -----
+
+// CHECK-LABEL: func @scan_is_reverse
+func.func @scan_is_reverse(%arg0: tensor<2x3xf32>, %arg1: tensor<3xf32>) -> tensor<2x3xf32> {
+ // CHECK: chlo.scan
+ // CHECK: is_reverse = true
+ %0, %1 = chlo.scan (%arg0) inits (%arg1) dimension = 0 attributes { is_reverse = true } {
+ ^bb0(%input0: tensor<3xf32>, %carry0: tensor<3xf32>):
+ %2 = stablehlo.add %input0, %carry0 : tensor<3xf32>
+ stablehlo.return %2, %2 : tensor<3xf32>, tensor<3xf32>
+ } : (tensor<2x3xf32>, tensor<3xf32>) -> (tensor<2x3xf32>, tensor<3xf32>)
+ func.return %0 : tensor<2x3xf32>
+}
+
+// -----
+
+// CHECK-LABEL: func @scan_is_associative
+func.func @scan_is_associative(%arg0: tensor<2x3xf32>, %arg1: tensor<3xf32>) -> tensor<2x3xf32> {
+ // CHECK: chlo.scan
+ // CHECK: is_associative = true
+ %0, %1 = chlo.scan (%arg0) inits (%arg1) dimension = 0 attributes { is_associative = true } {
^bb0(%input0: tensor<3xf32>, %carry0: tensor<3xf32>):
%2 = stablehlo.add %input0, %carry0 : tensor<3xf32>
stablehlo.return %2, %2 : tensor<3xf32>, tensor<3xf32>
@@ -447,6 +489,18 @@
// -----
+func.func @scan_explicit_size_mismatch(%arg0: tensor<2x3xf32>, %arg1: tensor<3xf32>) -> tensor<2x3xf32> {
+ // expected-error @+1 {{'chlo.scan' op invalid scan dimension size of operand 0}}
+ %0, %1 = chlo.scan (%arg0) inits (%arg1) dimension = 0 attributes { scan_dim_size = 3 : i64 } {
+ ^bb0(%input0: tensor<3xf32>, %carry0: tensor<3xf32>):
+ %2 = stablehlo.add %input0, %carry0 : tensor<3xf32>
+ stablehlo.return %2, %2 : tensor<3xf32>, tensor<3xf32>
+ } : (tensor<2x3xf32>, tensor<3xf32>) -> (tensor<2x3xf32>, tensor<3xf32>)
+ func.return %0 : tensor<2x3xf32>
+}
+
+// -----
+
func.func @scan_size_mismatch(%arg0: tensor<2x3xf32>, %arg1: tensor<3xf32>) -> tensor<2x3xf32> {
// expected-error @+1 {{'chlo.scan' op expects 1 arguments in the body, but got 2}}
%0 = chlo.scan(%arg0) inits () dimension = 0 {
diff --git a/stablehlo/tests/ops_stablehlo_quantized.mlir b/stablehlo/tests/ops_stablehlo_quantized.mlir
index f15d073..1de2d2c 100644
--- a/stablehlo/tests/ops_stablehlo_quantized.mlir
+++ b/stablehlo/tests/ops_stablehlo_quantized.mlir
@@ -437,7 +437,7 @@
// -----
func.func @negative_clamp_quantization(%arg0: tensor<1x!quant.uniform<ui8:f32:0, {0.1:-30}>>) -> tensor<1x!quant.uniform<ui8:f32:0, {0.1:-30}>> {
- // expected-error-re@+1 {{operand #0 must be ranked tensor of {{.*}}, but got 'tensor<1x!quant.uniform<u8:f32:0, {1.000000e-01:-30}>>'}}
+ // expected-error-re@+1 {{operand #0 must be ranked tensor of {{.*}}, but got 'tensor<1x!quant.uniform<ui8:f32:0, {1.000000e-01:-30}>>'}}
%0 = "stablehlo.clamp"(%arg0, %arg0, %arg0) : (tensor<1x!quant.uniform<ui8:f32:0, {0.1:-30}>>, tensor<1x!quant.uniform<ui8:f32:0, {0.1:-30}>>, tensor<1x!quant.uniform<ui8:f32:0, {0.1:-30}>>) -> tensor<1x!quant.uniform<ui8:f32:0, {0.1:-30}>>
func.return %0: tensor<1x!quant.uniform<ui8:f32:0, {0.1:-30}>>
}
@@ -888,7 +888,7 @@
// -----
func.func @illegal_storage_type_for_quantized_element_type(%arg0: tensor<4x!quant.uniform<si8:f32, 1.000000e+00>>) -> tensor<4xf32> {
- // expected-error-re@+1 {{operand #0 must be ranked tensor of {{.*}}, but got 'tensor<4x!quant.uniform<i8:f32, 1.000000e+00>>}}
+ // expected-error-re@+1 {{operand #0 must be ranked tensor of {{.*}}, but got 'tensor<4x!quant.uniform<si8:f32, 1.000000e+00>>}}
%0 = "stablehlo.uniform_dequantize"(%arg0) : (tensor<4x!quant.uniform<si8:f32, 1.000000e+00>>) -> tensor<4xf32>
func.return %0 : tensor<4xf32>
}
diff --git a/stablehlo/tests/transforms/stablehlo_legalize_qdq_to_quantized_op.mlir b/stablehlo/tests/transforms/stablehlo_legalize_qdq_to_quantized_op.mlir
index fba9aed..912b229 100644
--- a/stablehlo/tests/transforms/stablehlo_legalize_qdq_to_quantized_op.mlir
+++ b/stablehlo/tests/transforms/stablehlo_legalize_qdq_to_quantized_op.mlir
@@ -3,8 +3,8 @@
// -----
// CHECK-LABEL @compose_quantized_abs_op
-// CHECK: %[[abs0:.*]] = stablehlo.abs %arg0 : tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>>
-// CHECK-NEXT: return %[[abs0]] : tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>>
+// CHECK: %[[abs0:.*]] = stablehlo.abs %arg0 : tensor<16x16x!quant.uniform<ui8:f32, 3.400000e+01:16>>
+// CHECK-NEXT: return %[[abs0]] : tensor<16x16x!quant.uniform<ui8:f32, 3.400000e+01:16>>
func.func @compose_quantized_abs_op(%arg0: tensor<16x16x!quant.uniform<ui8:f32, 34.0:16>>) -> tensor<16x16x!quant.uniform<ui8:f32, 34.0:16>> {
%0 = stablehlo.uniform_dequantize %arg0 : (tensor<16x16x!quant.uniform<ui8:f32, 34.0:16>>) -> tensor<16x16xf32>
%1 = stablehlo.abs %0 : tensor<16x16xf32>
@@ -15,8 +15,8 @@
// -----
// CHECK-LABEL @failed_to_match_uniform_quant_op_operand_not_defined_by_op
-// CHECK: %0 = stablehlo.uniform_quantize %arg0 : (tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>>
-// CHECK-NEXT: return %0 : tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>>
+// CHECK: %0 = stablehlo.uniform_quantize %arg0 : (tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<ui8:f32, 3.400000e+01:16>>
+// CHECK-NEXT: return %0 : tensor<16x16x!quant.uniform<ui8:f32, 3.400000e+01:16>>
func.func @failed_to_match_uniform_quant_op_operand_not_defined_by_op(%arg0: tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<ui8:f32, 34.0:16>> {
%0 = stablehlo.uniform_quantize %arg0 : (tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<ui8:f32, 34.0:16>>
func.return %0 : tensor<16x16x!quant.uniform<ui8:f32, 34.0:16>>
@@ -30,8 +30,8 @@
// CHECK-NEXT: %2 = stablehlo.add %arg1, %arg2 : tensor<f32>
// CHECK-NEXT: stablehlo.return %2 : tensor<f32>
// CHECK-NEXT: }) : (tensor<4xf32>) -> tensor<4xf32>
-// CHECK-NEXT: %1 = stablehlo.uniform_quantize %0 : (tensor<4xf32>) -> tensor<4x!quant.uniform<u8:f32, 3.400000e+01:16>>
-// CHECK-NEXT: return %1 : tensor<4x!quant.uniform<u8:f32, 3.400000e+01:16>>
+// CHECK-NEXT: %1 = stablehlo.uniform_quantize %0 : (tensor<4xf32>) -> tensor<4x!quant.uniform<ui8:f32, 3.400000e+01:16>>
+// CHECK-NEXT: return %1 : tensor<4x!quant.uniform<ui8:f32, 3.400000e+01:16>>
func.func @failed_to_match_op_with_region(%operand0 : tensor<4xf32>) -> (tensor<4x!quant.uniform<ui8:f32, 34.0:16>>) {
%0 = stablehlo.uniform_quantize %operand0 : (tensor<4xf32>) -> tensor<4x!quant.uniform<ui8:f32, 34.0:16>>
@@ -51,13 +51,13 @@
// -----
// CHECK-LABEL failed_to_match_varidic_op
-// CHECK: %0 = stablehlo.uniform_quantize %arg0 : (tensor<8x2xf32>) -> tensor<8x2x!quant.uniform<u8:f32, 3.400000e+01:16>>
-// CHECK-NEXT: %1 = stablehlo.uniform_dequantize %0 : (tensor<8x2x!quant.uniform<u8:f32, 3.400000e+01:16>>) -> tensor<8x2xf32>
-// CHECK-NEXT: %2 = stablehlo.uniform_quantize %arg1 : (tensor<2x2xf32>) -> tensor<2x2x!quant.uniform<u8:f32, 3.400000e+01:16>>
-// CHECK-NEXT: %3 = stablehlo.uniform_dequantize %2 : (tensor<2x2x!quant.uniform<u8:f32, 3.400000e+01:16>>) -> tensor<2x2xf32>
+// CHECK: %0 = stablehlo.uniform_quantize %arg0 : (tensor<8x2xf32>) -> tensor<8x2x!quant.uniform<ui8:f32, 3.400000e+01:16>>
+// CHECK-NEXT: %1 = stablehlo.uniform_dequantize %0 : (tensor<8x2x!quant.uniform<ui8:f32, 3.400000e+01:16>>) -> tensor<8x2xf32>
+// CHECK-NEXT: %2 = stablehlo.uniform_quantize %arg1 : (tensor<2x2xf32>) -> tensor<2x2x!quant.uniform<ui8:f32, 3.400000e+01:16>>
+// CHECK-NEXT: %3 = stablehlo.uniform_dequantize %2 : (tensor<2x2x!quant.uniform<ui8:f32, 3.400000e+01:16>>) -> tensor<2x2xf32>
// CHECK-NEXT: %4:2 = "stablehlo.all_gather"(%1, %3) {{.*}} : (tensor<8x2xf32>, tensor<2x2xf32>) -> (tensor<8x8xf32>, tensor<2x4xf32>)
-// CHECK-NEXT: %5 = stablehlo.uniform_quantize %4#0 : (tensor<8x8xf32>) -> tensor<8x8x!quant.uniform<u8:f32, 3.400000e+01:16>>
-// CHECK-NEXT: return %5, %4#1 : tensor<8x8x!quant.uniform<u8:f32, 3.400000e+01:16>>, tensor<2x4xf32>
+// CHECK-NEXT: %5 = stablehlo.uniform_quantize %4#0 : (tensor<8x8xf32>) -> tensor<8x8x!quant.uniform<ui8:f32, 3.400000e+01:16>>
+// CHECK-NEXT: return %5, %4#1 : tensor<8x8x!quant.uniform<ui8:f32, 3.400000e+01:16>>, tensor<2x4xf32>
func.func @failed_to_match_varidic_op(%arg0: tensor<8x2xf32>, %arg1: tensor<2x2xf32>) -> (tensor<8x8x!quant.uniform<ui8:f32, 34.0:16>>, tensor<2x4xf32>) {
%0 = stablehlo.uniform_quantize %arg0 : (tensor<8x2xf32>) -> tensor<8x2x!quant.uniform<ui8:f32, 34.0:16>>
%1 = stablehlo.uniform_dequantize %0 : (tensor<8x2x!quant.uniform<ui8:f32, 34.0:16>>) -> tensor<8x2xf32>
@@ -75,12 +75,12 @@
// -----
// CHECK-LABEL @failed_to_match_operand_of_compute_op_already_quantized
-// CHECK: %0 = stablehlo.uniform_quantize %arg0 : (tensor<1x8x8x207xf32>) -> tensor<1x8x8x207x!quant.uniform<u8:f32, 3.400000e+01:16>>
-// CHECK-NEXT: %1 = stablehlo.uniform_dequantize %0 : (tensor<1x8x8x207x!quant.uniform<u8:f32, 3.400000e+01:16>>) -> tensor<1x8x8x207xf32>
+// CHECK: %0 = stablehlo.uniform_quantize %arg0 : (tensor<1x8x8x207xf32>) -> tensor<1x8x8x207x!quant.uniform<ui8:f32, 3.400000e+01:16>>
+// CHECK-NEXT: %1 = stablehlo.uniform_dequantize %0 : (tensor<1x8x8x207x!quant.uniform<ui8:f32, 3.400000e+01:16>>) -> tensor<1x8x8x207xf32>
// CHECK-NEXT: %2 = stablehlo.abs %arg1 : tensor<3x3x207x16x!quant.uniform<i8:f32, 5.000000e+00:20>>
// CHECK-NEXT: %3 = stablehlo.convolution(%1, %2) {{.*}} : (tensor<1x8x8x207xf32>, tensor<3x3x207x16x!quant.uniform<i8:f32, 5.000000e+00:20>>) -> tensor<1x8x8x16xf32>
-// CHECK-NEXT: %4 = stablehlo.uniform_quantize %3 : (tensor<1x8x8x16xf32>) -> tensor<1x8x8x16x!quant.uniform<u8:f32, 3.400000e+01:16>>
-// CHECK-NEXT: return %4 : tensor<1x8x8x16x!quant.uniform<u8:f32, 3.400000e+01:16>>
+// CHECK-NEXT: %4 = stablehlo.uniform_quantize %3 : (tensor<1x8x8x16xf32>) -> tensor<1x8x8x16x!quant.uniform<ui8:f32, 3.400000e+01:16>>
+// CHECK-NEXT: return %4 : tensor<1x8x8x16x!quant.uniform<ui8:f32, 3.400000e+01:16>>
func.func @failed_to_match_operand_of_compute_op_already_quantized(%arg0: tensor<1x8x8x207xf32>, %arg1: tensor<3x3x207x16x!quant.uniform<i8:f32, 5.0:20>>) -> tensor<1x8x8x16x!quant.uniform<ui8:f32, 34.0:16>> {
%0 = stablehlo.uniform_quantize %arg0 : (tensor<1x8x8x207xf32>) -> tensor<1x8x8x207x!quant.uniform<ui8:f32, 34.0:16>>
%1 = stablehlo.uniform_dequantize %0 : (tensor<1x8x8x207x!quant.uniform<ui8:f32, 34.0:16>>) -> tensor<1x8x8x207xf32>
@@ -97,11 +97,11 @@
// -----
// CHECK-LABEL @failed_to_match_operand_not_defined_by_op
-// CHECK: %0 = stablehlo.uniform_quantize %arg1 : (tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>>
-// CHECK-NEXT: %1 = stablehlo.uniform_dequantize %0 : (tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>>) -> tensor<16x16xf32>
+// CHECK: %0 = stablehlo.uniform_quantize %arg1 : (tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<ui8:f32, 3.400000e+01:16>>
+// CHECK-NEXT: %1 = stablehlo.uniform_dequantize %0 : (tensor<16x16x!quant.uniform<ui8:f32, 3.400000e+01:16>>) -> tensor<16x16xf32>
// CHECK-NEXT: %2 = stablehlo.add %arg0, %1 : tensor<16x16xf32>
-// CHECK-NEXT: %3 = stablehlo.uniform_quantize %2 : (tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>>
-// CHECK-NEXT: return %3 : tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>>
+// CHECK-NEXT: %3 = stablehlo.uniform_quantize %2 : (tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<ui8:f32, 3.400000e+01:16>>
+// CHECK-NEXT: return %3 : tensor<16x16x!quant.uniform<ui8:f32, 3.400000e+01:16>>
func.func @failed_to_match_operand_not_defined_by_op(%arg0: tensor<16x16xf32>, %arg1: tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<ui8:f32, 34.0:16>> {
%1 = stablehlo.uniform_quantize %arg1 : (tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<ui8:f32, 34.0:16>>
%2 = stablehlo.uniform_dequantize %1 : (tensor<16x16x!quant.uniform<ui8:f32, 34.0:16>>) -> tensor<16x16xf32>
@@ -114,11 +114,11 @@
// CHECK-LABEL @failed_to_match_defining_op_is_not_a_uniform_dequantized_op
// CHECK: %0 = stablehlo.abs %arg0 : tensor<16x16xf32>
-// CHECK-NEXT: %1 = stablehlo.uniform_quantize %arg1 : (tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>>
-// CHECK-NEXT: %2 = stablehlo.uniform_dequantize %1 : (tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>>) -> tensor<16x16xf32>
+// CHECK-NEXT: %1 = stablehlo.uniform_quantize %arg1 : (tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<ui8:f32, 3.400000e+01:16>>
+// CHECK-NEXT: %2 = stablehlo.uniform_dequantize %1 : (tensor<16x16x!quant.uniform<ui8:f32, 3.400000e+01:16>>) -> tensor<16x16xf32>
// CHECK-NEXT: %3 = stablehlo.add %0, %2 : tensor<16x16xf32>
-// CHECK-NEXT: %4 = stablehlo.uniform_quantize %3 : (tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>>
-// CHECK-NEXT: return %4 : tensor<16x16x!quant.uniform<u8:f32, 3.400000e+01:16>>
+// CHECK-NEXT: %4 = stablehlo.uniform_quantize %3 : (tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<ui8:f32, 3.400000e+01:16>>
+// CHECK-NEXT: return %4 : tensor<16x16x!quant.uniform<ui8:f32, 3.400000e+01:16>>
func.func @failed_to_match_defining_op_is_not_a_uniform_dequantized_op(%arg0: tensor<16x16xf32>, %arg1: tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<ui8:f32, 34.0:16>> {
%0 = stablehlo.abs %arg0 : tensor<16x16xf32>
%1 = stablehlo.uniform_quantize %arg1 : (tensor<16x16xf32>) -> tensor<16x16x!quant.uniform<ui8:f32, 34.0:16>>
diff --git a/stablehlo/transforms/StablehloLegalizeToVhlo.cpp b/stablehlo/transforms/StablehloLegalizeToVhlo.cpp
index 372535e..a00cac5 100644
--- a/stablehlo/transforms/StablehloLegalizeToVhlo.cpp
+++ b/stablehlo/transforms/StablehloLegalizeToVhlo.cpp
@@ -252,8 +252,8 @@
auto vhloType = typeConverter->convertType(attr.getType());
LLVM_DEBUG(llvm::dbgs() << "Converted " << vhloType << '\n');
if (!vhloType) return {};
- return vhlo::TensorV1Attr::get(attr.getContext(), vhloType,
- attr.getRawData());
+
+ return vhlo::TensorV1Attr::get(attr.getContext(), vhloType, attr);
}
if (auto attr = dyn_cast<DenseI64ArrayAttr>(stablehloAttr)) {
// Leverage the serialization for DenseElements.
diff --git a/stablehlo/transforms/VhloLegalizeToStablehlo.cpp b/stablehlo/transforms/VhloLegalizeToStablehlo.cpp
index 5f9d550..d3a0f9d 100644
--- a/stablehlo/transforms/VhloLegalizeToStablehlo.cpp
+++ b/stablehlo/transforms/VhloLegalizeToStablehlo.cpp
@@ -25,6 +25,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/IR/AttrTypeSubElements.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinOps.h"
@@ -173,8 +174,7 @@
auto builtinType =
cast<ShapedType>(typeConverter->convertType(attr.getType()));
if (!builtinType) return {};
- return DenseTypedElementsAttr::getFromRawBuffer(builtinType,
- attr.getData());
+ return attr.getData();
}
if (auto attr = dyn_cast<vhlo::TransposeV1Attr>(vhloAttr)) {
RETURN_CONVERTED_ENUM_ATTR(Transpose, V1);
@@ -619,7 +619,8 @@
typeConverter->convertType(tensorAttr.getType()));
if (!type) return specialFailure();
- auto elems = DenseElementsAttr::getFromRawBuffer(type, tensorAttr.getData());
+ auto elems = DenseElementsAttr::getFromRawBuffer(
+ type, tensorAttr.getData().getRawData());
stablehloAttrs.emplace_back(
vhloName, DenseArrayAttr::get(vhloAttr.getContext(),
@@ -806,7 +807,7 @@
bool isEmptyTensor(Attribute vhloAttr) {
auto attr = dyn_cast_or_null<vhlo::TensorV1Attr>(vhloAttr);
- return attr && attr.getData().empty();
+ return attr && attr.getData().getRawData().empty();
}
bool isEnum(Attribute vhloAttr, Attribute value) { return vhloAttr == value; }
@@ -1158,10 +1159,28 @@
}
void runOnOperation() override {
- // Upgraded VHLO should always be convertible to StableHLO.
- // Arbitrary VHLO might not be convertible if it uses deprecated features
- // which are no longer available in StableHLO.
- if (failed(applyPartialConversion(getOperation(), *target, patterns))) {
+ // Upgraded VHLO types should always be convertible to StableHLO.
+ mlir::AttrTypeReplacer replacer;
+ replacer.addReplacement([&](Type type) -> std::optional<Type> {
+ Type newType = converter.convertType(type);
+ if (newType && newType != type) return newType;
+ return std::nullopt;
+ });
+ // Only types are updated here, as attribute creation with StableHLO types
+ // would trigger VHLO assertion. This is used to avoid need for signature
+ // conversion which results in invalidating the blocks and triggering
+ // recomputing the order of operations, as well as inserting many
+ // unrealized conversion casts.
+ replacer.recursivelyReplaceElementsIn(getOperation(),
+ /*replaceAttrs=*/false,
+ /*replaceLocs=*/false,
+ /*replaceTypes=*/true);
+
+ ConversionConfig config;
+ config.allowPatternRollback = false;
+ config.foldingMode = mlir::DialectConversionFoldingMode::Never;
+ if (failed(applyPartialConversion(getOperation(), *target, patterns,
+ config))) {
return signalPassFailure();
}
diff --git a/stablehlo/transforms/VhloToVersion.cpp b/stablehlo/transforms/VhloToVersion.cpp
index c3c15d2..1d0fea2 100644
--- a/stablehlo/transforms/VhloToVersion.cpp
+++ b/stablehlo/transforms/VhloToVersion.cpp
@@ -365,12 +365,15 @@
auto shape = vhlo::RankedTensorV1Type::get(
builder.getContext(), {0},
vhlo::IntegerSI64V1Type::get(builder.getContext()), {});
- return vhlo::TensorV1Attr::get(builder.getContext(), shape, {});
+ auto denseElements = DenseIntElementsAttr::get(
+ RankedTensorType::get({0}, builder.getI64Type()),
+ llvm::ArrayRef<int64_t>{});
+ return vhlo::TensorV1Attr::get(builder.getContext(), shape, denseElements);
}
bool isEmptyTensor(Attribute attr) {
auto tensor = dyn_cast<TensorV1Attr>(attr);
- if (tensor) return tensor.getData().empty();
+ if (tensor) return tensor.getData().getRawData().empty();
return false;
}
@@ -401,7 +404,7 @@
RankedTensorV1Type::get(builder.getContext(), paddingShape,
IntegerSI64V1Type::get(builder.getContext()),
nullptr),
- denseElements.getRawData());
+ denseElements);
}
bool isDefaultResultAccuracy(Attribute attr) {
diff --git a/stablehlo/transforms/optimization/StablehloAggressiveFolder.cpp b/stablehlo/transforms/optimization/StablehloAggressiveFolder.cpp
index 2dac7e3..622f23c 100644
--- a/stablehlo/transforms/optimization/StablehloAggressiveFolder.cpp
+++ b/stablehlo/transforms/optimization/StablehloAggressiveFolder.cpp
@@ -209,11 +209,13 @@
Attribute res;
if (isa<IntegerType>(elemTy))
- res = constFoldBinaryOp<IntegerAttr, IntegerAttr::ValueType, void,
- IntResultType>(operands, resultType, folder);
+ res = constFoldBinaryOp<IntegerAttr, IntegerAttr, IntegerAttr::ValueType,
+ IntegerAttr::ValueType, void, IntResultType>(
+ operands, resultType, folder);
if (isa<FloatType>(elemTy))
- res = constFoldBinaryOp<FloatAttr, FloatAttr::ValueType, void,
- FloatResultType>(operands, resultType, folder);
+ res = constFoldBinaryOp<FloatAttr, FloatAttr, FloatAttr::ValueType,
+ FloatAttr::ValueType, void, FloatResultType>(
+ operands, resultType, folder);
if (res) return cast<TypedAttr>(res);
return nullptr;
diff --git a/third_party/llvm/build.patch b/third_party/llvm/build.patch
index a886a42..70c0216 100644
--- a/third_party/llvm/build.patch
+++ b/third_party/llvm/build.patch
@@ -1,5 +1,5 @@
diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
-index a7e652c..5b8ac5e 100644
+index 3df64d8a483f..aa3643bd4a2c 100644
--- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
@@ -234,19 +234,19 @@ write_file(
@@ -34,7 +34,7 @@
)
BLAKE3_x86_64_ASM_SOURCE_PATTERNS = [
-@@ -308,7 +308,8 @@ cc_library(
+@@ -307,7 +307,8 @@ cc_library(
"@platforms//cpu:aarch64": [
"lib/Support/BLAKE3/blake3_neon.c",
],
@@ -44,7 +44,7 @@
"//conditions:default": [
],
}),
-@@ -337,8 +338,9 @@ cc_library(
+@@ -336,8 +337,9 @@ cc_library(
],
"//conditions:default": ["BLAKE3_USE_NEON=0"],
}) + select({
@@ -56,3 +56,17 @@
"//conditions:default": [
"BLAKE3_NO_AVX2",
"BLAKE3_NO_AVX512",
+@@ -4679,6 +4681,13 @@ cc_library(
+ srcs = glob(["lib/HTTP/*.cpp"]),
+ hdrs = glob(["include/llvm/HTTP/*.h"]),
+ includes = ["include"],
++ linkopts = select({
++ "@platforms//os:windows": [
++ "crypt32.lib",
++ "winhttp.lib",
++ ],
++ "//conditions:default": [],
++ }),
+ deps = [":Support"],
+ )
+
diff --git a/third_party/llvm/generated.patch b/third_party/llvm/generated.patch
index c6a2aaa..509398d 100644
--- a/third_party/llvm/generated.patch
+++ b/third_party/llvm/generated.patch
@@ -1,293 +1 @@
Auto generated patch. Do not edit or delete it, even if empty.
-diff -ruN --strip-trailing-cr a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
---- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
-+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
-@@ -5882,21 +5882,26 @@
- BackedgeVal,
- match_fn(m_VPInstruction<VPInstruction::ComputeReductionResult>())));
-
-- // If IV is an expression to sink, create a new select that tracks the
-- // underlying IV directly and update the backedge value.
-- if (IVOfExpressionToSink) {
-- auto *OrigFindLastSelectR = FindLastSelect->getDefiningRecipe();
-- VPBuilder LoopBuilder(OrigFindLastSelectR);
-- DebugLoc DL = OrigFindLastSelectR->getDebugLoc();
-- VPValue *SelectCond = OrigFindLastSelectR->getOperand(0);
-- if (OrigFindLastSelectR->getOperand(1) == PhiR) {
-- FindLastSelect = LoopBuilder.createSelect(SelectCond, PhiR,
-- IVOfExpressionToSink, DL);
-- } else {
-- assert(OrigFindLastSelectR->getOperand(2) == PhiR &&
-- "PhiR expected as operand 1 or 2");
-- FindLastSelect = LoopBuilder.createSelect(
-- SelectCond, IVOfExpressionToSink, PhiR, DL);
-+ VPValue *NewFindLastSelect = BackedgeVal;
-+ VPValue *SelectCond = Cond;
-+ if (!SentinelVal || IVOfExpressionToSink) {
-+ // When we need to create a new select, normalize the condition so that
-+ // PhiR is the last operand and include the header mask if needed.
-+ DebugLoc DL = FindLastSelect->getDefiningRecipe()->getDebugLoc();
-+ VPBuilder LoopBuilder(FindLastSelect->getDefiningRecipe());
-+ if (FindLastSelect->getDefiningRecipe()->getOperand(1) == PhiR)
-+ SelectCond = LoopBuilder.createNot(SelectCond);
-+
-+ // When tail folding, mask the condition with the header mask to prevent
-+ // propagating poison from inactive lanes in the last vector iteration.
-+ if (HeaderMask)
-+ SelectCond = LoopBuilder.createLogicalAnd(HeaderMask, SelectCond);
-+
-+ if (SelectCond != Cond || IVOfExpressionToSink) {
-+ NewFindLastSelect = LoopBuilder.createSelect(
-+ SelectCond,
-+ IVOfExpressionToSink ? IVOfExpressionToSink : FindLastExpression,
-+ PhiR, DL);
- }
- }
-
-@@ -5908,8 +5913,9 @@
- FastMathFlags());
- DebugLoc ExitDL = RdxResult->getDebugLoc();
- VPBuilder MiddleBuilder(RdxResult);
-- VPValue *ReducedIV = MiddleBuilder.createNaryOp(
-- VPInstruction::ComputeReductionResult, FindLastSelect, Flags, ExitDL);
-+ VPValue *ReducedIV =
-+ MiddleBuilder.createNaryOp(VPInstruction::ComputeReductionResult,
-+ NewFindLastSelect, Flags, ExitDL);
-
- // If IVOfExpressionToSink is an expression to sink, sink it now.
- VPValue *VectorRegionExitingVal = ReducedIV;
-@@ -5939,10 +5945,7 @@
- AnyOfPhi->insertAfter(PhiR);
-
- VPBuilder LoopBuilder(BackedgeVal->getDefiningRecipe());
-- VPValue *AnyOfCond = Cond;
-- if (FindLastSelect->getOperand(1) == PhiR)
-- AnyOfCond = LoopBuilder.createNot(Cond);
-- VPValue *OrVal = LoopBuilder.createOr(AnyOfPhi, AnyOfCond);
-+ VPValue *OrVal = LoopBuilder.createOr(AnyOfPhi, SelectCond);
- AnyOfPhi->setOperand(1, OrVal);
-
- VPIRFlags OrFlags(RecurKind::Or, /*IsOrdered=*/false,
-@@ -5963,7 +5966,7 @@
-
- auto *NewPhiR = new VPReductionPHIRecipe(
- cast<PHINode>(PhiR->getUnderlyingInstr()), RecurKind::FindIV, *StartVPV,
-- *FindLastSelect, RdxUnordered{1}, {},
-+ *NewFindLastSelect, RdxUnordered{1}, {},
- PhiR->hasUsesOutsideReductionChain());
- NewPhiR->insertBefore(PhiR);
- PhiR->replaceAllUsesWith(NewPhiR);
-diff -ruN --strip-trailing-cr a/llvm/test/Transforms/LoopVectorize/find-last-iv-sinkable-expr.ll b/llvm/test/Transforms/LoopVectorize/find-last-iv-sinkable-expr.ll
---- a/llvm/test/Transforms/LoopVectorize/find-last-iv-sinkable-expr.ll
-+++ b/llvm/test/Transforms/LoopVectorize/find-last-iv-sinkable-expr.ll
-@@ -73,7 +73,8 @@
- ; TF-NEXT: [[TMP1:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[INDEX]]
- ; TF-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <4 x i64> @llvm.masked.load.v4i64.p0(ptr align 8 [[TMP1]], <4 x i1> [[TMP0]], <4 x i64> poison)
- ; TF-NEXT: [[TMP2:%.*]] = icmp eq <4 x i64> [[WIDE_MASKED_LOAD]], splat (i64 42)
--; TF-NEXT: [[TMP3]] = select <4 x i1> [[TMP2]], <4 x i64> [[VEC_IND]], <4 x i64> [[VEC_PHI]]
-+; TF-NEXT: [[TMP9:%.*]] = select <4 x i1> [[TMP0]], <4 x i1> [[TMP2]], <4 x i1> zeroinitializer
-+; TF-NEXT: [[TMP3]] = select <4 x i1> [[TMP9]], <4 x i64> [[VEC_IND]], <4 x i64> [[VEC_PHI]]
- ; TF-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4
- ; TF-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], splat (i64 4)
- ; TF-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
-@@ -174,7 +175,8 @@
- ; TF-NEXT: [[TMP1:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[INDEX]]
- ; TF-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <4 x i64> @llvm.masked.load.v4i64.p0(ptr align 8 [[TMP1]], <4 x i1> [[TMP0]], <4 x i64> poison)
- ; TF-NEXT: [[TMP2:%.*]] = icmp eq <4 x i64> [[WIDE_MASKED_LOAD]], splat (i64 42)
--; TF-NEXT: [[TMP3]] = select <4 x i1> [[TMP2]], <4 x i64> [[VEC_IND]], <4 x i64> [[VEC_PHI]]
-+; TF-NEXT: [[TMP9:%.*]] = select <4 x i1> [[TMP0]], <4 x i1> [[TMP2]], <4 x i1> zeroinitializer
-+; TF-NEXT: [[TMP3]] = select <4 x i1> [[TMP9]], <4 x i64> [[VEC_IND]], <4 x i64> [[VEC_PHI]]
- ; TF-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4
- ; TF-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], splat (i64 4)
- ; TF-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
-@@ -392,7 +394,8 @@
- ; TF-NEXT: [[TMP1:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[INDEX]]
- ; TF-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <4 x i64> @llvm.masked.load.v4i64.p0(ptr align 8 [[TMP1]], <4 x i1> [[TMP0]], <4 x i64> poison)
- ; TF-NEXT: [[TMP2:%.*]] = icmp eq <4 x i64> [[WIDE_MASKED_LOAD]], splat (i64 42)
--; TF-NEXT: [[TMP3]] = select <4 x i1> [[TMP2]], <4 x i64> [[VEC_IND]], <4 x i64> [[VEC_PHI]]
-+; TF-NEXT: [[TMP9:%.*]] = select <4 x i1> [[TMP0]], <4 x i1> [[TMP2]], <4 x i1> zeroinitializer
-+; TF-NEXT: [[TMP3]] = select <4 x i1> [[TMP9]], <4 x i64> [[VEC_IND]], <4 x i64> [[VEC_PHI]]
- ; TF-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4
- ; TF-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], splat (i64 4)
- ; TF-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
-@@ -513,7 +516,7 @@
- ; TF: [[VECTOR_BODY]]:
- ; TF-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[PRED_LOAD_CONTINUE8:.*]] ]
- ; TF-NEXT: [[VEC_IND:%.*]] = phi <4 x i64> [ <i64 10, i64 12, i64 14, i64 16>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[PRED_LOAD_CONTINUE8]] ]
--; TF-NEXT: [[VEC_PHI:%.*]] = phi <4 x i64> [ zeroinitializer, %[[VECTOR_PH]] ], [ [[TMP31:%.*]], %[[PRED_LOAD_CONTINUE8]] ]
-+; TF-NEXT: [[VEC_PHI:%.*]] = phi <4 x i64> [ zeroinitializer, %[[VECTOR_PH]] ], [ [[TMP36:%.*]], %[[PRED_LOAD_CONTINUE8]] ]
- ; TF-NEXT: [[TMP3:%.*]] = mul i64 [[INDEX]], 2
- ; TF-NEXT: [[OFFSET_IDX:%.*]] = add i64 10, [[TMP3]]
- ; TF-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <4 x i64> poison, i64 [[INDEX]], i64 0
-@@ -562,13 +565,14 @@
- ; TF-NEXT: [[TMP28:%.*]] = phi <4 x i64> [ [[TMP22]], %[[PRED_LOAD_CONTINUE6]] ], [ [[TMP27]], %[[PRED_LOAD_IF7]] ]
- ; TF-NEXT: [[TMP29:%.*]] = icmp eq <4 x i64> [[TMP28]], splat (i64 42)
- ; TF-NEXT: [[TMP30:%.*]] = add <4 x i64> [[VEC_IND]], splat (i64 100)
--; TF-NEXT: [[TMP31]] = select <4 x i1> [[TMP29]], <4 x i64> [[TMP30]], <4 x i64> [[VEC_PHI]]
-+; TF-NEXT: [[TMP31:%.*]] = select <4 x i1> [[TMP29]], <4 x i64> [[TMP30]], <4 x i64> [[VEC_PHI]]
-+; TF-NEXT: [[TMP36]] = select <4 x i1> [[TMP4]], <4 x i64> [[TMP31]], <4 x i64> [[VEC_PHI]]
- ; TF-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4
- ; TF-NEXT: [[VEC_IND_NEXT]] = add nuw nsw <4 x i64> [[VEC_IND]], splat (i64 8)
- ; TF-NEXT: [[TMP32:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
- ; TF-NEXT: br i1 [[TMP32]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]]
- ; TF: [[MIDDLE_BLOCK]]:
--; TF-NEXT: [[TMP33:%.*]] = call i64 @llvm.vector.reduce.umax.v4i64(<4 x i64> [[TMP31]])
-+; TF-NEXT: [[TMP33:%.*]] = call i64 @llvm.vector.reduce.umax.v4i64(<4 x i64> [[TMP36]])
- ; TF-NEXT: [[TMP34:%.*]] = icmp ne i64 [[TMP33]], 0
- ; TF-NEXT: [[TMP35:%.*]] = select i1 [[TMP34]], i64 [[TMP33]], i64 -1
- ; TF-NEXT: br label %[[DONE:.*]]
-@@ -1213,7 +1217,8 @@
- ; TF-NEXT: [[TMP7:%.*]] = getelementptr i64, ptr [[TMP6]], i64 -3
- ; TF-NEXT: [[WIDE_MASKED_LOAD8:%.*]] = call <4 x i64> @llvm.masked.load.v4i64.p0(ptr align 8 [[TMP7]], <4 x i1> [[REVERSE]], <4 x i64> poison)
- ; TF-NEXT: [[REVERSE9:%.*]] = shufflevector <4 x i64> [[WIDE_MASKED_LOAD8]], <4 x i64> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
--; TF-NEXT: [[TMP8:%.*]] = icmp sle <4 x i64> [[REVERSE6]], [[REVERSE9]]
-+; TF-NEXT: [[TMP16:%.*]] = icmp sle <4 x i64> [[REVERSE6]], [[REVERSE9]]
-+; TF-NEXT: [[TMP8:%.*]] = select <4 x i1> [[TMP2]], <4 x i1> [[TMP16]], <4 x i1> zeroinitializer
- ; TF-NEXT: [[TMP9]] = select <4 x i1> [[TMP8]], <4 x i64> [[VEC_IND]], <4 x i64> [[VEC_PHI]]
- ; TF-NEXT: [[TMP10]] = or <4 x i1> [[VEC_PHI3]], [[TMP8]]
- ; TF-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4
-@@ -1321,7 +1326,8 @@
- ; TF-NEXT: [[TMP1:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[INDEX]]
- ; TF-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <4 x i64> @llvm.masked.load.v4i64.p0(ptr align 8 [[TMP1]], <4 x i1> [[TMP0]], <4 x i64> poison)
- ; TF-NEXT: [[TMP2:%.*]] = icmp eq <4 x i64> [[WIDE_MASKED_LOAD]], splat (i64 42)
--; TF-NEXT: [[TMP3]] = select <4 x i1> [[TMP2]], <4 x i64> [[VEC_IND]], <4 x i64> [[VEC_PHI]]
-+; TF-NEXT: [[TMP9:%.*]] = select <4 x i1> [[TMP0]], <4 x i1> [[TMP2]], <4 x i1> zeroinitializer
-+; TF-NEXT: [[TMP3]] = select <4 x i1> [[TMP9]], <4 x i64> [[VEC_IND]], <4 x i64> [[VEC_PHI]]
- ; TF-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4
- ; TF-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], splat (i64 4)
- ; TF-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
-@@ -1424,7 +1430,8 @@
- ; TF-NEXT: [[TMP1:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[INDEX]]
- ; TF-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <4 x i64> @llvm.masked.load.v4i64.p0(ptr align 8 [[TMP1]], <4 x i1> [[TMP0]], <4 x i64> poison)
- ; TF-NEXT: [[TMP2:%.*]] = icmp eq <4 x i64> [[WIDE_MASKED_LOAD]], splat (i64 42)
--; TF-NEXT: [[TMP3]] = select <4 x i1> [[TMP2]], <4 x i64> [[VEC_IND]], <4 x i64> [[VEC_PHI]]
-+; TF-NEXT: [[TMP9:%.*]] = select <4 x i1> [[TMP0]], <4 x i1> [[TMP2]], <4 x i1> zeroinitializer
-+; TF-NEXT: [[TMP3]] = select <4 x i1> [[TMP9]], <4 x i64> [[VEC_IND]], <4 x i64> [[VEC_PHI]]
- ; TF-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4
- ; TF-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], splat (i64 4)
- ; TF-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
-diff -ruN --strip-trailing-cr a/llvm/test/Transforms/LoopVectorize/iv-select-cmp-decreasing.ll b/llvm/test/Transforms/LoopVectorize/iv-select-cmp-decreasing.ll
---- a/llvm/test/Transforms/LoopVectorize/iv-select-cmp-decreasing.ll
-+++ b/llvm/test/Transforms/LoopVectorize/iv-select-cmp-decreasing.ll
-@@ -330,11 +330,15 @@
- ; IC4VF4-NEXT: [[TMP77:%.*]] = select <4 x i1> [[TMP101]], <4 x i16> <i16 7, i16 6, i16 5, i16 4>, <4 x i16> splat (i16 32767)
- ; IC4VF4-NEXT: [[TMP70:%.*]] = select <4 x i1> [[TMP102]], <4 x i16> <i16 3, i16 2, i16 1, i16 0>, <4 x i16> splat (i16 32767)
- ; IC4VF4-NEXT: [[TMP71:%.*]] = select <4 x i1> [[TMP103]], <4 x i16> <i16 -1, i16 -2, i16 -3, i16 -4>, <4 x i16> splat (i16 32767)
-+; IC4VF4-NEXT: [[TMP82:%.*]] = select <4 x i1> splat (i1 true), <4 x i16> [[TMP76]], <4 x i16> splat (i16 32767)
-+; IC4VF4-NEXT: [[TMP83:%.*]] = select <4 x i1> splat (i1 true), <4 x i16> [[TMP77]], <4 x i16> splat (i16 32767)
-+; IC4VF4-NEXT: [[TMP88:%.*]] = select <4 x i1> splat (i1 true), <4 x i16> [[TMP70]], <4 x i16> splat (i16 32767)
-+; IC4VF4-NEXT: [[TMP89:%.*]] = select <4 x i1> zeroinitializer, <4 x i16> [[TMP71]], <4 x i16> splat (i16 32767)
- ; IC4VF4-NEXT: br label %[[MIDDLE_BLOCK:.*]]
- ; IC4VF4: [[MIDDLE_BLOCK]]:
--; IC4VF4-NEXT: [[RDX_MINMAX:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[TMP76]], <4 x i16> [[TMP77]])
--; IC4VF4-NEXT: [[RDX_MINMAX45:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[RDX_MINMAX]], <4 x i16> [[TMP70]])
--; IC4VF4-NEXT: [[RDX_MINMAX46:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[RDX_MINMAX45]], <4 x i16> [[TMP71]])
-+; IC4VF4-NEXT: [[RDX_MINMAX:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[TMP82]], <4 x i16> [[TMP83]])
-+; IC4VF4-NEXT: [[RDX_MINMAX31:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[RDX_MINMAX]], <4 x i16> [[TMP88]])
-+; IC4VF4-NEXT: [[RDX_MINMAX46:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[RDX_MINMAX31]], <4 x i16> [[TMP89]])
- ; IC4VF4-NEXT: [[TMP116:%.*]] = call i16 @llvm.vector.reduce.smin.v4i16(<4 x i16> [[RDX_MINMAX46]])
- ; IC4VF4-NEXT: [[RDX_SELECT_CMP:%.*]] = icmp ne i16 [[TMP116]], 32767
- ; IC4VF4-NEXT: [[RDX_SELECT:%.*]] = select i1 [[RDX_SELECT_CMP]], i16 [[TMP116]], i16 0
-@@ -592,11 +596,15 @@
- ; IC4VF4-NEXT: [[TMP77:%.*]] = select <4 x i1> [[TMP101]], <4 x i16> <i16 7, i16 6, i16 5, i16 4>, <4 x i16> splat (i16 32767)
- ; IC4VF4-NEXT: [[TMP70:%.*]] = select <4 x i1> [[TMP102]], <4 x i16> <i16 3, i16 2, i16 1, i16 0>, <4 x i16> splat (i16 32767)
- ; IC4VF4-NEXT: [[TMP71:%.*]] = select <4 x i1> [[TMP103]], <4 x i16> <i16 -1, i16 -2, i16 -3, i16 -4>, <4 x i16> splat (i16 32767)
-+; IC4VF4-NEXT: [[TMP82:%.*]] = select <4 x i1> splat (i1 true), <4 x i16> [[TMP76]], <4 x i16> splat (i16 32767)
-+; IC4VF4-NEXT: [[TMP83:%.*]] = select <4 x i1> splat (i1 true), <4 x i16> [[TMP77]], <4 x i16> splat (i16 32767)
-+; IC4VF4-NEXT: [[TMP88:%.*]] = select <4 x i1> splat (i1 true), <4 x i16> [[TMP70]], <4 x i16> splat (i16 32767)
-+; IC4VF4-NEXT: [[TMP89:%.*]] = select <4 x i1> zeroinitializer, <4 x i16> [[TMP71]], <4 x i16> splat (i16 32767)
- ; IC4VF4-NEXT: br label %[[MIDDLE_BLOCK:.*]]
- ; IC4VF4: [[MIDDLE_BLOCK]]:
--; IC4VF4-NEXT: [[RDX_MINMAX:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[TMP76]], <4 x i16> [[TMP77]])
--; IC4VF4-NEXT: [[RDX_MINMAX45:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[RDX_MINMAX]], <4 x i16> [[TMP70]])
--; IC4VF4-NEXT: [[RDX_MINMAX46:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[RDX_MINMAX45]], <4 x i16> [[TMP71]])
-+; IC4VF4-NEXT: [[RDX_MINMAX:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[TMP82]], <4 x i16> [[TMP83]])
-+; IC4VF4-NEXT: [[RDX_MINMAX31:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[RDX_MINMAX]], <4 x i16> [[TMP88]])
-+; IC4VF4-NEXT: [[RDX_MINMAX46:%.*]] = call <4 x i16> @llvm.smin.v4i16(<4 x i16> [[RDX_MINMAX31]], <4 x i16> [[TMP89]])
- ; IC4VF4-NEXT: [[TMP116:%.*]] = call i16 @llvm.vector.reduce.smin.v4i16(<4 x i16> [[RDX_MINMAX46]])
- ; IC4VF4-NEXT: [[RDX_SELECT_CMP:%.*]] = icmp ne i16 [[TMP116]], 32767
- ; IC4VF4-NEXT: [[RDX_SELECT:%.*]] = select i1 [[RDX_SELECT_CMP]], i16 [[TMP116]], i16 0
-diff -ruN --strip-trailing-cr a/llvm/test/Transforms/LoopVectorize/iv-select-cmp-fold-tail.ll b/llvm/test/Transforms/LoopVectorize/iv-select-cmp-fold-tail.ll
---- a/llvm/test/Transforms/LoopVectorize/iv-select-cmp-fold-tail.ll
-+++ b/llvm/test/Transforms/LoopVectorize/iv-select-cmp-fold-tail.ll
-@@ -59,3 +59,80 @@
- exit:
- ret i32 %rdx.next
- }
-+
-+define i64 @select_decreasing_induction_icmp_non_const_start(ptr %a, ptr %b, i64 %rdx.start, i64 %n) {
-+; CHECK-LABEL: define i64 @select_decreasing_induction_icmp_non_const_start(
-+; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]], i64 [[RDX_START:%.*]], i64 [[N:%.*]]) {
-+; CHECK-NEXT: [[ENTRY:.*:]]
-+; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N]], 1
-+; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[N]], i64 1)
-+; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[TMP0]], [[UMIN]]
-+; CHECK-NEXT: br label %[[VECTOR_PH:.*]]
-+; CHECK: [[VECTOR_PH]]:
-+; CHECK-NEXT: [[N_RND_UP:%.*]] = add i64 [[TMP1]], 3
-+; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N_RND_UP]], 4
-+; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N_RND_UP]], [[N_MOD_VF]]
-+; CHECK-NEXT: [[TRIP_COUNT_MINUS_1:%.*]] = sub i64 [[TMP1]], 1
-+; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i64> poison, i64 [[TRIP_COUNT_MINUS_1]], i64 0
-+; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i64> [[BROADCAST_SPLATINSERT]], <4 x i64> poison, <4 x i32> zeroinitializer
-+; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <4 x i64> poison, i64 [[N]], i64 0
-+; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <4 x i64> [[BROADCAST_SPLATINSERT1]], <4 x i64> poison, <4 x i32> zeroinitializer
-+; CHECK-NEXT: [[INDUCTION:%.*]] = add nsw <4 x i64> [[BROADCAST_SPLAT2]], <i64 0, i64 -1, i64 -2, i64 -3>
-+; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
-+; CHECK: [[VECTOR_BODY]]:
-+; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
-+; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i64> [ [[INDUCTION]], %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[VECTOR_BODY]] ]
-+; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i64> [ splat (i64 9223372036854775807), %[[VECTOR_PH]] ], [ [[TMP52:%.*]], %[[VECTOR_BODY]] ]
-+; CHECK-NEXT: [[VEC_PHI3:%.*]] = phi <4 x i1> [ zeroinitializer, %[[VECTOR_PH]] ], [ [[TMP50:%.*]], %[[VECTOR_BODY]] ]
-+; CHECK-NEXT: [[OFFSET_IDX:%.*]] = sub i64 [[N]], [[INDEX]]
-+; CHECK-NEXT: [[BROADCAST_SPLATINSERT4:%.*]] = insertelement <4 x i64> poison, i64 [[INDEX]], i64 0
-+; CHECK-NEXT: [[BROADCAST_SPLAT5:%.*]] = shufflevector <4 x i64> [[BROADCAST_SPLATINSERT4]], <4 x i64> poison, <4 x i32> zeroinitializer
-+; CHECK-NEXT: [[VEC_IV:%.*]] = add <4 x i64> [[BROADCAST_SPLAT5]], <i64 0, i64 1, i64 2, i64 3>
-+; CHECK-NEXT: [[TMP2:%.*]] = icmp ule <4 x i64> [[VEC_IV]], [[BROADCAST_SPLAT]]
-+; CHECK-NEXT: [[TMP38:%.*]] = add nsw i64 [[OFFSET_IDX]], -1
-+; CHECK-NEXT: [[TMP39:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[TMP38]]
-+; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i64, ptr [[TMP39]], i64 -3
-+; CHECK-NEXT: [[REVERSE:%.*]] = shufflevector <4 x i1> [[TMP2]], <4 x i1> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-+; CHECK-NEXT: [[WIDE_MASKED_LOAD:%.*]] = call <4 x i64> @llvm.masked.load.v4i64.p0(ptr align 8 [[TMP5]], <4 x i1> [[REVERSE]], <4 x i64> poison)
-+; CHECK-NEXT: [[TMP46:%.*]] = shufflevector <4 x i64> [[WIDE_MASKED_LOAD]], <4 x i64> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-+; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i64, ptr [[B]], i64 [[TMP38]]
-+; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i64, ptr [[TMP6]], i64 -3
-+; CHECK-NEXT: [[WIDE_MASKED_LOAD8:%.*]] = call <4 x i64> @llvm.masked.load.v4i64.p0(ptr align 8 [[TMP7]], <4 x i1> [[REVERSE]], <4 x i64> poison)
-+; CHECK-NEXT: [[TMP47:%.*]] = shufflevector <4 x i64> [[WIDE_MASKED_LOAD8]], <4 x i64> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
-+; CHECK-NEXT: [[TMP48:%.*]] = icmp sgt <4 x i64> [[TMP46]], [[TMP47]]
-+; CHECK-NEXT: [[TMP49:%.*]] = select <4 x i1> [[TMP2]], <4 x i1> [[TMP48]], <4 x i1> zeroinitializer
-+; CHECK-NEXT: [[TMP52]] = select <4 x i1> [[TMP49]], <4 x i64> [[VEC_IND]], <4 x i64> [[VEC_PHI]]
-+; CHECK-NEXT: [[TMP50]] = or <4 x i1> [[VEC_PHI3]], [[TMP49]]
-+; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4
-+; CHECK-NEXT: [[VEC_IND_NEXT]] = add nsw <4 x i64> [[VEC_IND]], splat (i64 -4)
-+; CHECK-NEXT: [[TMP51:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
-+; CHECK-NEXT: br i1 [[TMP51]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]]
-+; CHECK: [[MIDDLE_BLOCK]]:
-+; CHECK-NEXT: [[TMP53:%.*]] = call i64 @llvm.vector.reduce.smin.v4i64(<4 x i64> [[TMP52]])
-+; CHECK-NEXT: [[TMP54:%.*]] = add nsw i64 [[TMP53]], -1
-+; CHECK-NEXT: [[TMP56:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP50]])
-+; CHECK-NEXT: [[TMP57:%.*]] = freeze i1 [[TMP56]]
-+; CHECK-NEXT: [[RDX_SELECT:%.*]] = select i1 [[TMP57]], i64 [[TMP54]], i64 [[RDX_START]]
-+; CHECK-NEXT: br label %[[EXIT:.*]]
-+; CHECK: [[EXIT]]:
-+; CHECK-NEXT: ret i64 [[RDX_SELECT]]
-+;
-+entry:
-+ br label %loop
-+
-+loop:
-+ %iv = phi i64 [ %iv.next, %loop ], [ %n, %entry ]
-+ %rdx = phi i64 [ %cond, %loop ], [ %rdx.start, %entry ]
-+ %iv.next = add nsw i64 %iv, -1
-+ %gep.a.iv = getelementptr inbounds i64, ptr %a, i64 %iv.next
-+ %ld.a = load i64, ptr %gep.a.iv, align 8
-+ %gep.b.iv = getelementptr inbounds i64, ptr %b, i64 %iv.next
-+ %ld.b = load i64, ptr %gep.b.iv, align 8
-+ %cmp.a.b = icmp sgt i64 %ld.a, %ld.b
-+ %cond = select i1 %cmp.a.b, i64 %iv.next, i64 %rdx
-+ %exit.cond = icmp ugt i64 %iv, 1
-+ br i1 %exit.cond, label %loop, label %exit
-+
-+exit:
-+ ret i64 %cond
-+}
diff --git a/third_party/llvm/workspace.bzl b/third_party/llvm/workspace.bzl
index f220caa..8ee1b2c 100644
--- a/third_party/llvm/workspace.bzl
+++ b/third_party/llvm/workspace.bzl
@@ -4,8 +4,8 @@
def repo(name):
"""Imports LLVM."""
- LLVM_COMMIT = "2cf353b5e8560723409f3f9164bddec76f499963"
- LLVM_SHA256 = "3a9b33b701b9ebd4110ef795d23be54fb5d762ca4e190480c4a06d71b7aa8064"
+ LLVM_COMMIT = "7189c4bb83d90c383741a9480fceca9c7bf74b27"
+ LLVM_SHA256 = "dd652f7b4e46001614ea3c1e10cbb117a73199f2d8f7e95c66f233bd0111fbd4"
tf_http_archive(
name = name,