================
@@ -3140,18 +3137,53 @@ void CodeGenFunction::EmitPPCAIXMultiVersionResolver(
     assert(RO.Features.size() == 1 &&
            "for now one feature requirement per version");
 
-    assert(RO.Features[0].starts_with("cpu="));
-    StringRef CPU = RO.Features[0].split("=").second.trim();
-    StringRef Feature = llvm::StringSwitch<StringRef>(CPU)
-                            .Case("pwr7", "arch_2_06")
-                            .Case("pwr8", "arch_2_07")
-                            .Case("pwr9", "arch_3_00")
-                            .Case("pwr10", "arch_3_1")
-                            .Case("pwr11", "arch_3_1")
-                            .Default("error");
-
-    llvm::Value *Condition = EmitPPCBuiltinCpu(
-        Builtin::BI__builtin_cpu_supports, Builder.getInt1Ty(), Feature);
+    StringRef FeatureStr = RO.Features[0];
+    StringRef BuiltinCpuSupportsArg;
+    bool IsNegated = false;
+
+    if (FeatureStr.starts_with("cpu=")) {
+      // CPU specification - map to ISA level
+      StringRef CPU = FeatureStr.split("=").second.trim();
+      BuiltinCpuSupportsArg = llvm::StringSwitch<StringRef>(CPU)
+#define PPC_AIX_CLONES_CPU(CPU_NAME, AIX_BUILTIN_CPU_SUPPORTS_NAME, _) \
+  .Case(CPU_NAME, AIX_BUILTIN_CPU_SUPPORTS_NAME)
+#include "llvm/TargetParser/PPCTargetParser.def"
+                                  .Default("error");
+    } else {
+      // Feature strings arrive here already normalized:
+      // - Positive features: just the name (e.g., "altivec")
+      // - Negated features: "no-" prefix (e.g., "no-altivec")
+      if (FeatureStr.starts_with("no-")) {
+        IsNegated = true;
+        FeatureStr = FeatureStr.drop_front(3);
+      }
----------------
w2yehia wrote:

@diggerlin suggested that negative features should have highest priority.
I think in the absence of a priority field (RISC-V has 
[one](https://github.com/riscv-non-isa/riscv-c-api-doc/blob/main/src/c-api.adoc#__attribute__target_clonestarget-clones-attr-string-)),
 it makes sense to treat a negative feature requirement as a correctness 
requirement which should take higher precedence than selecting for performance.

Thinking about this more, you can divide features into 3 categories:
1) non-CPU properties (e.g. `invariant-function-descriptors`); those cannot be 
tested at runtime, and are currently excluded from the list of valid 
target_clones.
2) CPU properties that cannot be disabled (e.g. mma); you obviously cannot 
enable a feature on a CPU that doesn't physically support it, so those features 
can map to CPUs directly.
   `+feature` => `__builtin_cpu_supports("<minimum-cpu>")` => true for CPU 
`<minimum-cpu>` and above.
   `-feature` => `!__builtin_cpu_supports("<minimum-cpu>")` => true for CPU 
`<minimum-cpu-minus-one>` and below.
3) CPU properties that can be disabled (e.g. vsx); those can map to CPUs 
directly for the positive requirement (same as (2); for the negative 
requirement checking the CPU is incorrect, and there needs to be a way to check 
the property directly. So we should only support `-feature` for the ones that 
can be tested, and for now it is `vsx`, `altivec`, and `htm` from my 
investigation.

This still leaves the following scenario broken if at runtime both features are 
disabled but each clone only has one of the two features disabled and the other 
enabled. 
```
__attribute__((target_clones("no-htm","no-vsx,"default")))
int foo(void) { return 4; }
```
You can argue this is a limitation as a result of limiting the clone to one 
requirement.
Expanding to multiple requirements is another discussion for future work.

I will implement the above. 
@diggerlin what do you think?

https://github.com/llvm/llvm-project/pull/206786
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to