Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
33115db
fix: add upper bound validation for num_segments in UnsortedSegmentRe…
Ashutosh0x Jun 3, 2026
82cb515
Cap num_segments bound by Index max to prevent int32 overflow
Ashutosh0x Jul 25, 2026
12b2fed
Copy num_segments before validation and apply clang-format
Ashutosh0x Jul 26, 2026
9916bf6
Use absl::InvalidArgumentError and absl::StrCat for the new errors
Ashutosh0x Jul 29, 2026
218b09a
Apply SubtleMustCopy to the tensor reads, not the derived values
Ashutosh0x Jul 30, 2026
12ad001
Bound num_segments by kint32max for every index type
Ashutosh0x Jul 30, 2026
81285cf
Tighten the comment on the num_segments bound
Ashutosh0x Jul 30, 2026
4f88046
Make both ternary branches explicitly int64_t
Ashutosh0x Sep 2, 2026
bf50ce5
test(process_util): add negative thread test for NumInterOpThreadsFro…
Abhirup0 Aug 25, 2026
081a82a
Validate non-negative values in fractional max pool
dynamo-pentester Sep 6, 2026
c3bf3b3
fix: validate output signatures in LookupTableExportOp to prevent cra…
adi-IL Aug 21, 2026
6d8039e
Fix out-of-bounds access in GPU SparseSegment*Grad kernels
gauravarun Sep 16, 2026
4b11885
Address review: guard nouter==0 and avoid full-array D2H copies
gauravarun Sep 16, 2026
da78f1a
Reject nouter that doesn't fit in int32 before bounds-check kernel
gauravarun Sep 17, 2026
f448a3e
[XLA:GPU] Add collective memory space to layout and use it as collect…
PatriosTheGreat Sep 24, 2026
3445433
PR #49314: Bump astral-sh/setup-uv from 10.0.1 to 10.1.0
dependabot[bot] Sep 24, 2026
2dd5ba0
PR #49372: [ROCm]Enable vectorization.hlo check on ROCm mi200 and mi350.
linchen1-robot Sep 24, 2026
f64587a
Update TensorIR to v0.1.4.
chsigg Sep 24, 2026
c21d28e
Merge pull request #125856 from adi-IL:fix/lookup-table-export-signat…
tensorflower-gardener Sep 25, 2026
d2a201a
[XLA:GPU] Include device failure details in PlatformUtil::GetStreamEx…
PatriosTheGreat Sep 24, 2026
6dc9dc2
PR #49033: [ROCm]Add ROCm HSACO compile-then-pack coverage and fix cl…
linchen1-robot Sep 24, 2026
435c4e8
Automated Code Change
tensorflower-gardener Sep 24, 2026
57dbb88
[XLA] Use root `native_custom_call_handler_allowlist` in non-GPU XLA …
beckerhe Sep 24, 2026
f9fab1c
Merge pull request #127480 from gauravarun:fix-sparsesegment-grad-gpu…
tensorflower-gardener Sep 25, 2026
8c9cfc9
[XLA:CPU] Legalize narrow float vector memory operations in CPU xtile.
pifon2a Sep 24, 2026
d9ecfe9
Reverts 84df1268af5c065ada6aea0704152d5de6b2f47d
ekayaaslan Sep 24, 2026
de517cb
Add defensive checks for P2P symmetric memory support and null windows.
chsigg Sep 24, 2026
6d4756c
[XLA:GPU] Add cuDNN scaled dot device test suite.
loislo Sep 24, 2026
712767c
Merge pull request #126091 from Abhirup0:fix-inter-op-threads-crash
tensorflower-gardener Sep 25, 2026
e7a7327
[XLA:GPU] Require bitcasts to keep bitwidth in CopyFusion
akuegel Sep 24, 2026
9b12b73
Document XLA:GPU compiler/runtime compatibility requirements.
EusebioDM Sep 24, 2026
277107e
[XLA] Update TODO comments on closed duplicate bugs to active canonic…
toli-y Sep 24, 2026
8a022e7
[XLA:GPU] simplify multiple expressions in tiling space
metaflow Sep 24, 2026
1d4cc1b
Parse split-proto merge records from a riegeli::Chain without flatten…
EusebioDM Sep 24, 2026
b08a6e3
Write `ExecutableAndOptionsProto` records uncompressed.
EusebioDM Sep 24, 2026
9c7723c
Return a ready empty vector from typed JoinFutures on empty input
Moerafaat Sep 24, 2026
bf98845
Add update_goldens.py to regenerate AOT compatibility goldens
khasanovaa Sep 24, 2026
615d5ee
Split collective_ops AOT goldens into per-arch directories
khasanovaa Sep 24, 2026
dfa4939
[XLA:GPU]: Implement cufunction record for GPU backend.
sohaibiftikhar Sep 24, 2026
eaedaed
[XLA][HLO Value Tracking] Maintain OriginalValue consistency across w…
jcai19 Sep 24, 2026
a1ae4db
[XLA:GPU]: Fix caching issue with kernels when unrolling while loops
sohaibiftikhar Sep 24, 2026
6eb71e6
Merge pull request #120176 from Ashutosh0x:fix/unsorted-segment-sum-o…
tensorflower-gardener Sep 25, 2026
659f756
[Mosaic TPU] Add some fold rules for the transpose op.
yueshengys Sep 24, 2026
5442ef5
Add blockwise support in the litert converter.
majiddadashi Sep 24, 2026
0668dfb
[XLA:FFI] Make `//xla/ffi:api` an alias of `//xla/ffi/api:api`
beckerhe Sep 24, 2026
8bebdff
[PJRT:CPU] Use separate bounded thread pools for compilation, executi…
junwhanahn Sep 24, 2026
7a33d59
Add first-class kShuffle instruction and builder API across HLO and p…
ZMCodi Sep 24, 2026
26e6f35
Update shardy commit.
ybaturina Sep 24, 2026
e3f6b57
Replace IFRT mock usage with real client in //third_party/tensorflow/…
junwhanahn Sep 24, 2026
159f4e5
Merge pull request #126911 from dynamo-pentester:patch-1
tensorflower-gardener Sep 25, 2026
fadb2ca
Add algebraic simplification logic for kShuffle::kRotate.
ZMCodi Sep 24, 2026
4fa7af7
Clear sharding annotations on entry parameters at the end of GSPMD pa…
bixia1 Sep 24, 2026
b5d8801
[XLA][HLO Value Tracking] Maintain OriginalValue consistency in Memor…
jcai19 Sep 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@

### Major Features and Improvements

* <MAJOR FEATURES GO HERE>
* `tf.lite`
* Adds blockwise quantization support in the converter and `quant_spec` metadata in `FullyConnectedOptions`.

### Bug Fixes and Other Changes

Expand Down
2 changes: 2 additions & 0 deletions tensorflow/compiler/mlir/lite/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,7 @@ cc_library(
"@llvm-project//mlir:IR",
"@llvm-project//mlir:Pass",
"@llvm-project//mlir:Support",
"@llvm-project//mlir:TransformUtils",
],
)

Expand Down Expand Up @@ -1552,6 +1553,7 @@ cc_library(
srcs = [
"transforms/decompose_hybrid_quantization.cc",
"transforms/default_quant_params.cc",
"transforms/fold_stablehlo_constant_transforms_pass.cc",
"transforms/generated_post_quantize.inc",
"transforms/generated_quantize.inc",
"transforms/lower_quant_annotations_helper.cc",
Expand Down
127 changes: 71 additions & 56 deletions tensorflow/compiler/mlir/lite/converter_gen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ llvm::cl::opt<ActionType> action(
"Generate TFLite runtime verifiers")));

// Returns the associated option name for the given op definition.
static inline std::string GetOperatorOptionName(const Record &def) {
static inline std::string GetOperatorOptionName(const Record& def) {
assert(def.getName().starts_with("TFL_") && "unexpected op prefix");
assert(def.getName().ends_with("Op") && "unexpected op suffix");

auto *custom_option = dyn_cast<StringInit>(def.getValueInit("customOption"));
auto* custom_option = dyn_cast<StringInit>(def.getValueInit("customOption"));
std::ostringstream oss;
if (custom_option)
oss << custom_option->getValue().str();
Expand All @@ -90,7 +90,7 @@ static inline bool IsLstmOp(const StringRef op_name) {
return op_name.take_back(6) == "LSTMOp";
}

static int HasOptions(const Record &def) {
static int HasOptions(const Record& def) {
if (def.getValueAsBit("hasOptions")) {
return 1;
}
Expand All @@ -100,13 +100,13 @@ static int HasOptions(const Record &def) {
return 0;
}

static void EmitOptionBuilders(const RecordKeeper &record_keeper,
const std::vector<const Record *> &defs,
raw_ostream *ostream) {
raw_ostream &os = *ostream;
static void EmitOptionBuilders(const RecordKeeper& record_keeper,
const std::vector<const Record*>& defs,
raw_ostream* ostream) {
raw_ostream& os = *ostream;

const auto attr_type = record_keeper.getClass("Attr");
for (const auto *def : defs) {
for (const auto* def : defs) {
const int has_options = HasOptions(*def);
// TFLite ops without options are skipped over.
if (!has_options) {
Expand All @@ -125,11 +125,11 @@ static void EmitOptionBuilders(const RecordKeeper &record_keeper,
// Construct all the builder option needed.
SmallVector<std::string, 8> options;
// Add options due to attributes (not-derived).
auto *arg_values = def->getValueAsDag("arguments");
auto* arg_values = def->getValueAsDag("arguments");
mlir::tblgen::Operator op(*def);
for (unsigned i = 0, e = arg_values->getNumArgs(); i != e; ++i) {
auto arg = arg_values->getArg(i);
const auto *arg_def = dyn_cast<DefInit>(arg);
const auto* arg_def = dyn_cast<DefInit>(arg);
if (!arg_def) continue;
if (arg_def->getDef()->isSubClassOf(attr_type)) {
// This binds the name of the attribute in the TD file with the name
Expand All @@ -156,8 +156,8 @@ static void EmitOptionBuilders(const RecordKeeper &record_keeper,
}

// Add options due to derived attributes.
for (const auto &val : def->getValues()) {
if (auto *record = dyn_cast<RecordRecTy>(val.getType())) {
for (const auto& val : def->getValues()) {
if (auto* record = dyn_cast<RecordRecTy>(val.getType())) {
if (record->isSubClassOf(attr_type)) {
if (record->getClasses().size() != 1) {
PrintFatalError(
Expand All @@ -174,7 +174,7 @@ static void EmitOptionBuilders(const RecordKeeper &record_keeper,
}

os << " tflite::" << tflite_option_name << "Builder b(*fbb);\n";
for (const auto &option : options)
for (const auto& option : options)
os << formatv(" b.add_{0}(std::move({0}));\n", option);
os << " return b.Finish();\n}\n";
}
Expand All @@ -187,11 +187,11 @@ static void EmitOptionBuilders(const RecordKeeper &record_keeper,
// arguments that depend on op definitions should be auto-generated and then
// operator should be built by the caller because it does not require
// auto-generation.
static void EmitOperatorBuilders(const std::vector<const Record *> &defs,
raw_ostream *ostream) {
raw_ostream &os = *ostream;
static void EmitOperatorBuilders(const std::vector<const Record*>& defs,
raw_ostream* ostream) {
raw_ostream& os = *ostream;

for (const auto *def : defs) {
for (const auto* def : defs) {
StringRef op_name = def->getName().drop_front(4);

const bool has_intermediates = op_name.take_back(6) == "LSTMOp";
Expand Down Expand Up @@ -257,7 +257,7 @@ static void EmitOperatorBuilders(const std::vector<const Record *> &defs,
}
}

static inline std::string GetOperatorName(const Record &def) {
static inline std::string GetOperatorName(const Record& def) {
auto name = def.getValueAsString("opName");
// Special case for basic_lstm.
if (name == "basic_lstm") {
Expand All @@ -275,14 +275,14 @@ static inline std::string GetOperatorName(const Record &def) {
//
// TODO(hinsu): Consider converting this to a static constant associative
// container instead of a series of if conditions, if required.
static void EmitGetBuiltinOpCode(const std::vector<const Record *> &defs,
raw_ostream *ostream) {
raw_ostream &os = *ostream;
static void EmitGetBuiltinOpCode(const std::vector<const Record*>& defs,
raw_ostream* ostream) {
raw_ostream& os = *ostream;

os << "std::optional<tflite::BuiltinOperator> "
"mlir::GetBuiltinOpCode(mlir::Operation* op) {\n";

for (const auto *def : defs) {
for (const auto* def : defs) {
StringRef op_name = def->getName().drop_front(4);
auto operator_name = GetOperatorName(*def);
os << " if (isa<mlir::TFL::" << op_name << ">(op))\n"
Expand All @@ -304,20 +304,20 @@ static void EmitGetBuiltinOpCode(const std::vector<const Record *> &defs,
// ...
// return {0, 0};
// }
static void EmitOperandNumbers(const RecordKeeper &record_keeper,
const std::vector<const Record *> &defs,
raw_ostream *ostream) {
raw_ostream &os = *ostream;
static void EmitOperandNumbers(const RecordKeeper& record_keeper,
const std::vector<const Record*>& defs,
raw_ostream* ostream) {
raw_ostream& os = *ostream;
const auto attr_type = record_keeper.getClass("Attr");
const auto optional_tensor = record_keeper.getClass("TFL_TensorOfOrNone");
os << "llvm::MinMax mlir::OperandNumbersMinMax(llvm::StringRef op_name) {\n";
for (const auto *def : defs) {
for (const auto* def : defs) {
auto op_name = def->getValueAsString("opName");
int tail_optional_tensor = 0, tensor_number_max = 0;
auto *arg_values = def->getValueAsDag("arguments");
auto* arg_values = def->getValueAsDag("arguments");
for (int i = 0, e = arg_values->getNumArgs(); i < e; ++i) {
auto arg = arg_values->getArg(i);
auto *arg_def = dyn_cast<DefInit>(arg);
auto* arg_def = dyn_cast<DefInit>(arg);
if (!arg_def) continue;
if (!arg_def->getDef()->isSubClassOf(attr_type)) {
tensor_number_max++;
Expand Down Expand Up @@ -351,9 +351,9 @@ static void EmitOperandNumbers(const RecordKeeper &record_keeper,
// const std::vector<int32_t>& intermediates,
// flatbuffers::FlatBufferBuilder *fbb,
// std::optional<int> debug_metadata_index);
static void EmitBuildOperator(const std::vector<const Record *> &defs,
raw_ostream *ostream) {
raw_ostream &os = *ostream;
static void EmitBuildOperator(const std::vector<const Record*>& defs,
raw_ostream* ostream) {
raw_ostream& os = *ostream;

// Signature
os << "std::optional<flatbuffers::Offset<tflite::Operator>>\n"
Expand All @@ -365,7 +365,7 @@ static void EmitBuildOperator(const std::vector<const Record *> &defs,
"flatbuffers::FlatBufferBuilder *fbb,"
"std::optional<int> debug_metadata_index) {\n";

for (const auto *def : defs) {
for (const auto* def : defs) {
StringRef op_name = def->getName().drop_front(4);

// Try to cast to each op case and call the corresponding op builder
Expand All @@ -391,9 +391,9 @@ static void EmitBuildOperator(const std::vector<const Record *> &defs,
// where id is an empty string if builtin_options_id is 1, or builtin_options_id
// otherwise.
static void EmitBuiltinOptionsToAttributes(
const RecordKeeper &record_keeper, const std::vector<const Record *> &defs,
raw_ostream *ostream, const int builtin_options_id) {
raw_ostream &os = *ostream;
const RecordKeeper& record_keeper, const std::vector<const Record*>& defs,
raw_ostream* ostream, const int builtin_options_id) {
raw_ostream& os = *ostream;

const std::string builtin_options_suffix = [&] {
switch (builtin_options_id) {
Expand All @@ -415,7 +415,7 @@ static void EmitBuiltinOptionsToAttributes(
"llvm::SmallVectorImpl<mlir::NamedAttribute> &attributes) {\n";

const auto attr_type = record_keeper.getClass("Attr");
for (const auto *def : defs) {
for (const auto* def : defs) {
const int has_options = HasOptions(*def);
if (has_options != builtin_options_id) {
continue;
Expand All @@ -429,10 +429,10 @@ static void EmitBuiltinOptionsToAttributes(
os << formatv(" if(const auto *op = op_union.As{0}()) {{\n", option_name);

// We only care about options that are in arguments
auto *arg_values = def->getValueAsDag("arguments");
auto* arg_values = def->getValueAsDag("arguments");
for (unsigned i = 0, e = arg_values->getNumArgs(); i != e; ++i) {
auto arg = arg_values->getArg(i);
const auto *arg_def = dyn_cast<DefInit>(arg);
const auto* arg_def = dyn_cast<DefInit>(arg);
if (!arg_def) continue;
if (arg_def->getDef()->isSubClassOf(attr_type)) {
StringRef arg_name = arg_values->getArgNameStr(i);
Expand All @@ -449,6 +449,21 @@ static void EmitBuiltinOptionsToAttributes(
}
}

for (const auto& val : def->getValues()) {
if (auto* record = dyn_cast<RecordRecTy>(val.getType())) {
if (record->isSubClassOf(attr_type) &&
record->getClasses().size() == 1 &&
record->getClasses()[0]->getName() == "DerivedQuantSpecAttr") {
os << formatv(
" if (auto attr = BuildDerivedQuantSpecAttr(op->{0}, "
"builder))\n"
" attributes.emplace_back(builder.getNamedAttr("
"mlir::TFL::kQuantSpecAttrName, attr));\n",
val.getName());
}
}
}

os << " return;\n";
os << " }\n";
}
Expand All @@ -463,14 +478,14 @@ static void EmitBuiltinOptionsToAttributes(
// The function below has a non-constant reference as that is required by LLVM's
// TableGenMain.
// NOLINTNEXTLINE
static bool OperatorWritersMain(raw_ostream &os, const RecordKeeper &records) {
static bool OperatorWritersMain(raw_ostream& os, const RecordKeeper& records) {
emitSourceFileHeader("MLIR TFLite FlatBuffer Builders", os);

// Retrieve all the definitions derived from TFL_Op and sort by record name.
std::vector<const Record *> defs = records.getAllDerivedDefinitions("TFL_Op");
std::vector<const Record*> defs = records.getAllDerivedDefinitions("TFL_Op");
llvm::sort(defs, LessRecord());

for (const auto *def : defs) {
for (const auto* def : defs) {
// TFLite ops in the .td file are expected to follow the naming convention:
// TFL_<OpName>Op.
// The generated TFLite op C++ class should be TFL::<OpName>Op.
Expand Down Expand Up @@ -501,15 +516,15 @@ static bool OperatorWritersMain(raw_ostream &os, const RecordKeeper &records) {
return false;
}

static void GenOperandResultVerifier(raw_ostream &os,
llvm::ArrayRef<const llvm::Init *> values,
static void GenOperandResultVerifier(raw_ostream& os,
llvm::ArrayRef<const llvm::Init*> values,
StringRef valueKind) {
mlir::tblgen::FmtContext fctx;

bool first = true;
for (const auto &static_value : llvm::enumerate(values)) {
auto *definit = llvm::cast<llvm::DefInit>(static_value.value());
auto *val = definit->getDef()->getValue("tflRuntimeTypePredicate");
for (const auto& static_value : llvm::enumerate(values)) {
auto* definit = llvm::cast<llvm::DefInit>(static_value.value());
auto* val = definit->getDef()->getValue("tflRuntimeTypePredicate");
if (!val) continue;

// Create code block on first type to verify.
Expand Down Expand Up @@ -550,16 +565,16 @@ static void GenOperandResultVerifier(raw_ostream &os,
}

// NOLINTNEXTLINE
static bool RuntimeVerifierWriterMain(raw_ostream &os,
const RecordKeeper &records) {
static bool RuntimeVerifierWriterMain(raw_ostream& os,
const RecordKeeper& records) {
emitSourceFileHeader("MLIR TFLite Runtime Verifiers", os);

// Retrieve all the definitions derived from TFL_Op and sort by record name.
std::vector<const Record *> defs = records.getAllDerivedDefinitions("Op");
std::vector<const Record*> defs = records.getAllDerivedDefinitions("Op");
llvm::sort(defs, LessRecord());

// Iterate through all the ops defined.
for (const auto *def : defs) {
for (const auto* def : defs) {
mlir::tblgen::Operator op(*def);
if (!op.getTrait("TflRuntimeVerifyOpInterface::Trait")) continue;

Expand All @@ -571,15 +586,15 @@ static bool RuntimeVerifierWriterMain(raw_ostream &os,
verify_ctx.addSubst("_op", "(*op)");

for (int i = 0, e = op.getNumOperands(); i < e; ++i) {
auto &value = op.getOperand(i);
auto& value = op.getOperand(i);
// Skip from first variadic operands for now. Else getOperand index used
// below doesn't match.
if (value.isVariableLength()) break;
if (!value.name.empty())
verify_ctx.addSubst(value.name, formatv("op->getOperand({0})", i));
}
for (int i = 0, e = op.getNumResults(); i < e; ++i) {
auto &value = op.getResult(i);
auto& value = op.getResult(i);
// Skip from first variadic results for now. Else getResult index used
// below doesn't match.
if (value.isVariableLength()) break;
Expand All @@ -591,7 +606,7 @@ static bool RuntimeVerifierWriterMain(raw_ostream &os,
GenOperandResultVerifier(os, def->getValueAsDag("results")->getArgs(),
"result");

for (auto &trait : op.getTraits()) {
for (auto& trait : op.getTraits()) {
if (!trait.getDef().isSubClassOf("GenInternalOpTrait")) {
continue;
}
Expand All @@ -600,7 +615,7 @@ static bool RuntimeVerifierWriterMain(raw_ostream &os,
continue;
}

auto *val = trait.getDef().getValue("tflRuntimePredicate");
auto* val = trait.getDef().getValue("tflRuntimePredicate");
if (!val) continue;

auto desc = trait.getDef().getValueAsString("tflRuntimeDescription");
Expand Down Expand Up @@ -643,7 +658,7 @@ static bool RuntimeVerifierWriterMain(raw_ostream &os,
return false;
}

int main(int argc, char **argv) {
int main(int argc, char** argv) {
llvm::InitLLVM y(argc, argv);
llvm::cl::ParseCommandLineOptions(argc, argv);
if (action == ActionType::OpConv)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1871,6 +1871,11 @@ absl::Status ParseFullyConnected(const Operator* op,
schema_params->asymmetric_quantize_inputs();
TFL_FILE_ENSURE_STATUS(ConvertTensorType(
schema_params->quantized_bias_type(), &params->quantized_bias_type));
if (const auto* quant_spec = schema_params->quant_spec()) {
// Borrowed from the model buffer; see TfLiteFullyConnectedParams.
params->quant_spec = quant_spec->data();
params->quant_spec_size = static_cast<int>(quant_spec->size());
}
switch (schema_params->weights_format()) {
case FullyConnectedOptionsWeightsFormat_DEFAULT:
params->weights_format = kTfLiteFullyConnectedWeightsFormatDefault;
Expand Down
12 changes: 12 additions & 0 deletions tensorflow/compiler/mlir/lite/core/c/builtin_op_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,18 @@ typedef struct {
// Parameters for FullyConnected version 10 or above.
// Used to determine the default value for the quantized bias.
TfLiteType quantized_bias_type;

// Parameters for FullyConnected version 15 or above.
//
// Opaque, flexbuffers-encoded description of a non-standard quantization
// contract; see `FullyConnectedOptions.quant_spec` in schema.fbs. Null when
// the op uses standard FullyConnected quantization semantics.
//
// This points into the model's buffer and is only valid for as long as the
// model is, in the same way as `TfLiteNode::custom_initial_data`. It is not
// owned by this struct.
const uint8_t* quant_spec;
int quant_spec_size;
} TfLiteFullyConnectedParams;

typedef enum {
Expand Down
Loading
Loading