authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-27 00:50:23-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-27 00:50:23-07:00
log45739725c1beec9515892890169ac58085138cb7
tree4461b2b2eb8890ee247f22050a3e8124498d437b
parent03de5ec6dd572ee9601fef6ee5d527c310fb726c

tools/update_cpu_features: prune redundant features

When a CPU feature implies that another one must be present, avoid redundantly specifying the other one.

1 files changed, 67 insertions(+), 14 deletions(-)

tools/update_cpu_features.zig+67-14
......@@ -197,7 +197,7 @@ pub fn main() anyerror!void {
197197 .llvm_tblgen_exe = llvm_tblgen_exe,
198198 .llvm_src_root = llvm_src_root,
199199 .zig_src_dir = zig_src_dir,
200 .root_progress = &root_progress,
200 .root_progress = root_progress,
201201 .llvm_target = llvm_target,
202202 });
203203 }
......@@ -385,11 +385,19 @@ fn processOneTarget(job: Job) anyerror!void {
385385 },
386386 );
387387 const implies = obj.get("Implies").?.Array;
388 var dependencies = std.ArrayList(*json.ObjectMap).init(arena);
388 var deps_set = std.StringHashMap(void).init(arena);
389389 for (implies.items) |imply| {
390390 const other_key = imply.Object.get("def").?.String;
391 const other_obj = &root_map.getEntry(other_key).?.value.Object;
392 try dependencies.append(other_obj);
391 try deps_set.put(other_key, {});
392 }
393 try pruneFeatures(arena, root_map, &deps_set);
394 var dependencies = std.ArrayList(*json.ObjectMap).init(arena);
395 {
396 var it = deps_set.iterator();
397 while (it.next()) |entry| {
398 const other_obj = &root_map.getEntry(entry.key).?.value.Object;
399 try dependencies.append(other_obj);
400 }
393401 }
394402 std.sort.sort(*json.ObjectMap, dependencies.items, {}, objectLessThan);
395403
......@@ -427,24 +435,29 @@ fn processOneTarget(job: Job) anyerror!void {
427435 );
428436
429437 for (all_cpus.items) |obj| {
430 var cpu_features = std.ArrayList(*json.ObjectMap).init(arena);
431
432438 const llvm_name = obj.get("Name").?.String;
439 var deps_set = std.StringHashMap(void).init(arena);
440
433441 const features = obj.get("Features").?.Array;
434442 for (features.items) |feature| {
435443 const feature_key = feature.Object.get("def").?.String;
436 const feature_obj = &root_map.getEntry(feature_key).?.value.Object;
437 const feature_llvm_name = feature_obj.get("Name").?.String;
438 if (feature_llvm_name.len == 0) continue;
439 try cpu_features.append(feature_obj);
444 try deps_set.put(feature_key, {});
440445 }
441446 const tune_features = obj.get("TuneFeatures").?.Array;
442447 for (tune_features.items) |feature| {
443448 const feature_key = feature.Object.get("def").?.String;
444 const feature_obj = &root_map.getEntry(feature_key).?.value.Object;
445 const feature_llvm_name = feature_obj.get("Name").?.String;
446 if (feature_llvm_name.len == 0) continue;
447 try cpu_features.append(feature_obj);
449 try deps_set.put(feature_key, {});
450 }
451 try pruneFeatures(arena, root_map, &deps_set);
452 var cpu_features = std.ArrayList(*json.ObjectMap).init(arena);
453 {
454 var it = deps_set.iterator();
455 while (it.next()) |entry| {
456 const feature_obj = &root_map.getEntry(entry.key).?.value.Object;
457 const feature_llvm_name = feature_obj.get("Name").?.String;
458 if (feature_llvm_name.len == 0) continue;
459 try cpu_features.append(feature_obj);
460 }
448461 }
449462 std.sort.sort(*json.ObjectMap, cpu_features.items, {}, objectLessThan);
450463 const zig_cpu_name = try llvmNameToZigName(arena, llvm_target, llvm_name);
......@@ -494,6 +507,8 @@ fn usageAndExit(file: fs.File, arg0: []const u8, code: u8) noreturn {
494507 \\
495508 \\Prints to stdout Zig code which you can use to replace the file src/clang_options_data.zig.
496509 \\
510 \\On a less beefy system, or when debugging, compile with --single-threaded.
511 \\
497512 , .{arg0}) catch std.process.exit(1);
498513 std.process.exit(code);
499514}
......@@ -533,3 +548,41 @@ fn hasSuperclass(obj: *json.ObjectMap, class_name: []const u8) bool {
533548 }
534549 return false;
535550}
551
552fn pruneFeatures(
553 arena: *mem.Allocator,
554 root_map: *const json.ObjectMap,
555 deps_set: *std.StringHashMap(void),
556) !void {
557 // For each element, recursively iterate over the dependencies and add
558 // everything we find to a "deletion set".
559 // Then, iterate over the deletion set and delete all that stuff from `deps_set`.
560 var deletion_set = std.StringHashMap(void).init(arena);
561 {
562 var it = deps_set.iterator();
563 while (it.next()) |entry| {
564 const other_obj = &root_map.getEntry(entry.key).?.value.Object;
565 try walkFeatures(root_map, &deletion_set, other_obj);
566 }
567 }
568 {
569 var it = deletion_set.iterator();
570 while (it.next()) |entry| {
571 _ = deps_set.remove(entry.key);
572 }
573 }
574}
575
576fn walkFeatures(
577 root_map: *const json.ObjectMap,
578 deletion_set: *std.StringHashMap(void),
579 feature: *json.ObjectMap,
580) error{OutOfMemory}!void {
581 const implies = feature.get("Implies").?.Array;
582 for (implies.items) |imply| {
583 const other_key = imply.Object.get("def").?.String;
584 try deletion_set.put(other_key, {});
585 const other_obj = &root_map.getEntry(other_key).?.value.Object;
586 try walkFeatures(root_map, deletion_set, other_obj);
587 }
588}