[clang] [llvm] [RISCV] Update TargetAttr target-cpu override rule (PR #75804)

Piyou Chen via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 28 08:20:37 PST 2023


https://github.com/BeMg updated https://github.com/llvm/llvm-project/pull/75804

>From 139ab4d26badc0d43c14fc94fe73db32342cfc1e Mon Sep 17 00:00:00 2001
From: Piyou Chen <piyou.chen at sifive.com>
Date: Sun, 17 Dec 2023 23:12:12 -0800
Subject: [PATCH 1/2] Make target-cpu override rule correct

---
 clang/lib/CodeGen/CodeGenModule.cpp           | 25 ++++++++
 .../RISCV/riscv-func-attr-target-mcpu-rv32.c  | 63 +++++++++++++++++++
 .../RISCV/riscv-func-attr-target-mcpu-rv64.c  | 63 +++++++++++++++++++
 .../CodeGen/RISCV/riscv-func-attr-target.c    | 10 +--
 ...riscv-func-target-feature-mcpu-override.ll | 36 +++++++++++
 5 files changed, 192 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/CodeGen/RISCV/riscv-func-attr-target-mcpu-rv32.c
 create mode 100644 clang/test/CodeGen/RISCV/riscv-func-attr-target-mcpu-rv64.c
 create mode 100644 llvm/test/CodeGen/RISCV/riscv-func-target-feature-mcpu-override.ll

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 7ad26ace328ab2..83a530f1fee45d 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2571,6 +2571,31 @@ bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD,
       if (!ParsedAttr.Tune.empty() &&
           getTarget().isValidCPUName(ParsedAttr.Tune))
         TuneCPU = ParsedAttr.Tune;
+
+      if (getTarget().getTriple().isRISCV()) {
+        // attr-cpu override march only if arch isn't present.
+        if (TD->getFeaturesStr().contains("arch=")) {
+          // Before drop attr-cpu, keep it in tune-cpu
+          if (!TargetCPU.empty() && TuneCPU.empty())
+            TuneCPU = TargetCPU;
+
+          // Reassign mcpu due to attr-arch=<Adding-Extension> need
+          // target-feature from mcpu/march.
+          // Use attr-cpu will affect target-feature.
+          TargetCPU = getTarget().getTargetOpts().CPU;
+
+          // arch=<full-arch-string> need keep target feature clean,
+          // use the baseline cpu.
+          if (llvm::find(ParsedAttr.Features,
+                         "__RISCV_TargetAttrNeedOverride") !=
+              ParsedAttr.Features.end())
+            TargetCPU = (getTarget().getTriple().isRISCV32()) ? "generic-rv32"
+                                                              : "generic-rv64";
+
+          if (TargetCPU == TuneCPU)
+            TuneCPU = "";
+        }
+      }
     }
 
     if (SD) {
diff --git a/clang/test/CodeGen/RISCV/riscv-func-attr-target-mcpu-rv32.c b/clang/test/CodeGen/RISCV/riscv-func-attr-target-mcpu-rv32.c
new file mode 100644
index 00000000000000..abbeb57f54faa3
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-func-attr-target-mcpu-rv32.c
@@ -0,0 +1,63 @@
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv32 -target-cpu sifive-e76 -target-feature +zifencei -target-feature +m \
+// RUN:  -target-feature +a -target-feature +save-restore -target-feature -zbb \
+// RUN:  -target-feature -relax -target-feature -zfa \
+// RUN:  -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: define dso_local void @testDefault() #0
+void testDefault() {}
+
+// CHECK: define dso_local void @testFullArchOnly() #1
+__attribute__((target("arch=rv32imac"))) void
+testFullArchOnly() {}
+
+// CHECK: define dso_local void @testFullArchAndCpu() #2
+__attribute__((target("arch=rv32imac;cpu=sifive-e34"))) void
+testFullArchAndCpu() {}
+
+// CHECK: define dso_local void @testFullArchAndTune() #2
+__attribute__((target("arch=rv32imac;tune=sifive-e34"))) void
+testFullArchAndTune() {}
+
+// CHECK: define dso_local void @testFullArchAndCpuAndTune() #2
+__attribute__((target("arch=rv32imac;cpu=sifive-e31;tune=sifive-e34"))) void
+testFullArchAndCpuAndTune() {}
+
+// CHECK: define dso_local void @testAddExtOnly() #3
+__attribute__((target("arch=+v"))) void
+testAddExtOnly() {}
+
+// CHECK: define dso_local void @testAddExtAndCpu() #4
+__attribute__((target("arch=+v;cpu=sifive-e31"))) void
+testAddExtAndCpu() {}
+
+// CHECK: define dso_local void @testAddExtAndTune() #4
+__attribute__((target("arch=+v;tune=sifive-e31"))) void
+testAddExtAndTune() {}
+
+// CHECK: define dso_local void @testAddExtAndCpuAndTune() #5
+__attribute__((target("arch=+v;cpu=sifive-e31;tune=sifive-e34"))) void
+testAddExtAndCpuAndTune() {}
+
+// CHECK: define dso_local void @testCpuOnly() #6
+__attribute__((target("cpu=sifive-e31"))) void
+testCpuOnly() {}
+
+// CHECK: define dso_local void @testCpuAndTune() #7
+__attribute__((target("cpu=sifive-e31;tune=sifive-e34"))) void
+testCpuAndTune() {}
+
+// CHECK: define dso_local void @testTuneOnly() #8
+__attribute__((target("tune=sifive-e34"))) void
+testTuneOnly() {}
+
+// .
+// CHECK: attributes #0 = { {{.*}}"target-cpu"="sifive-e76" "target-features"="+32bit,+a,+m,+save-restore,+zifencei,-relax,-zbb,-zfa" }
+// CHECK: attributes #1 = { {{.*}}"target-cpu"="generic-rv32" "target-features"="+32bit,+a,+c,+m,+save-restore,-relax,-zbb,-zfa" "tune-cpu"="sifive-e76" }
+// CHECK: attributes #2 = { {{.*}}"target-cpu"="generic-rv32" "target-features"="+32bit,+a,+c,+m,+save-restore,-relax,-zbb,-zfa" "tune-cpu"="sifive-e34" }
+// CHECK: attributes #3 = { {{.*}}"target-cpu"="sifive-e76" "target-features"="+32bit,+a,+d,+f,+m,+save-restore,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-relax,-zbb,-zfa" }
+// CHECK: attributes #4 = { {{.*}}"target-cpu"="sifive-e76" "target-features"="+32bit,+a,+d,+f,+m,+save-restore,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-relax,-zbb,-zfa" "tune-cpu"="sifive-e31" }
+// CHECK: attributes #5 = { {{.*}}"target-cpu"="sifive-e76" "target-features"="+32bit,+a,+d,+f,+m,+save-restore,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-relax,-zbb,-zfa" "tune-cpu"="sifive-e34" }
+// CHECK: attributes #6 = { {{.*}}"target-cpu"="sifive-e31" "target-features"="+32bit,+a,+c,+m,+save-restore,+zicsr,+zifencei,-relax,-zbb,-zfa" }
+// CHECK: attributes #7 = { {{.*}}"target-cpu"="sifive-e31" "target-features"="+32bit,+a,+c,+m,+save-restore,+zicsr,+zifencei,-relax,-zbb,-zfa" "tune-cpu"="sifive-e34" }
+// CHECK: attributes #8 = { {{.*}}"target-cpu"="sifive-e76" "target-features"="+32bit,+a,+m,+save-restore,+zifencei,-relax,-zbb,-zfa" "tune-cpu"="sifive-e34" }
diff --git a/clang/test/CodeGen/RISCV/riscv-func-attr-target-mcpu-rv64.c b/clang/test/CodeGen/RISCV/riscv-func-attr-target-mcpu-rv64.c
new file mode 100644
index 00000000000000..9cb12e85e84215
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-func-attr-target-mcpu-rv64.c
@@ -0,0 +1,63 @@
+// REQUIRES: riscv-registered-target
+// RUN: %clang_cc1 -triple riscv64 -target-cpu sifive-x280 -target-feature +zifencei -target-feature +m \
+// RUN:  -target-feature +a -target-feature +save-restore -target-feature -zbb \
+// RUN:  -target-feature -relax -target-feature -zfa \
+// RUN:  -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: define dso_local void @testDefault() #0
+void testDefault() {}
+
+// CHECK: define dso_local void @testFullArchOnly() #1
+__attribute__((target("arch=rv64imac"))) void
+testFullArchOnly() {}
+
+// CHECK: define dso_local void @testFullArchAndCpu() #2
+__attribute__((target("arch=rv64imac;cpu=sifive-u74"))) void
+testFullArchAndCpu() {}
+
+// CHECK: define dso_local void @testFullArchAndTune() #2
+__attribute__((target("arch=rv64imac;tune=sifive-u74"))) void
+testFullArchAndTune() {}
+
+// CHECK: define dso_local void @testFullArchAndCpuAndTune() #2
+__attribute__((target("arch=rv64imac;cpu=sifive-u54;tune=sifive-u74"))) void
+testFullArchAndCpuAndTune() {}
+
+// CHECK: define dso_local void @testAddExtOnly() #3
+__attribute__((target("arch=+v"))) void
+testAddExtOnly() {}
+
+// CHECK: define dso_local void @testAddExtAndCpu() #4
+__attribute__((target("arch=+v;cpu=sifive-u54"))) void
+testAddExtAndCpu() {}
+
+// CHECK: define dso_local void @testAddExtAndTune() #4
+__attribute__((target("arch=+v;tune=sifive-u54"))) void
+testAddExtAndTune() {}
+
+// CHECK: define dso_local void @testAddExtAndCpuAndTune() #5
+__attribute__((target("arch=+v;cpu=sifive-u54;tune=sifive-u74"))) void
+testAddExtAndCpuAndTune() {}
+
+// CHECK: define dso_local void @testCpuOnly() #6
+__attribute__((target("cpu=sifive-u54"))) void
+testCpuOnly() {}
+
+// CHECK: define dso_local void @testCpuAndTune() #7
+__attribute__((target("cpu=sifive-u54;tune=sifive-u74"))) void
+testCpuAndTune() {}
+
+// CHECK: define dso_local void @testTuneOnly() #8
+__attribute__((target("tune=sifive-u74"))) void
+testTuneOnly() {}
+
+// .
+// CHECK: attributes #0 = { {{.*}}"target-cpu"="sifive-x280" "target-features"="+64bit,+a,+m,+save-restore,+zifencei,-relax,-zbb,-zfa" }
+// CHECK: attributes #1 = { {{.*}}"target-cpu"="generic-rv64" "target-features"="+64bit,+a,+c,+m,+save-restore,-relax,-zbb,-zfa" "tune-cpu"="sifive-x280" }
+// CHECK: attributes #2 = { {{.*}}"target-cpu"="generic-rv64" "target-features"="+64bit,+a,+c,+m,+save-restore,-relax,-zbb,-zfa" "tune-cpu"="sifive-u74" }
+// CHECK: attributes #3 = { {{.*}}"target-cpu"="sifive-x280" "target-features"="+64bit,+a,+d,+f,+m,+save-restore,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-relax,-zbb,-zfa" }
+// CHECK: attributes #4 = { {{.*}}"target-cpu"="sifive-x280" "target-features"="+64bit,+a,+d,+f,+m,+save-restore,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-relax,-zbb,-zfa" "tune-cpu"="sifive-u54" }
+// CHECK: attributes #5 = { {{.*}}"target-cpu"="sifive-x280" "target-features"="+64bit,+a,+d,+f,+m,+save-restore,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-relax,-zbb,-zfa" "tune-cpu"="sifive-u74" }
+// CHECK: attributes #6 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zicsr,+zifencei,-relax,-zbb,-zfa" }
+// CHECK: attributes #7 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zicsr,+zifencei,-relax,-zbb,-zfa" "tune-cpu"="sifive-u74" }
+// CHECK: attributes #8 = { {{.*}}"target-cpu"="sifive-x280" "target-features"="+64bit,+a,+m,+save-restore,+zifencei,-relax,-zbb,-zfa" "tune-cpu"="sifive-u74" }
diff --git a/clang/test/CodeGen/RISCV/riscv-func-attr-target.c b/clang/test/CodeGen/RISCV/riscv-func-attr-target.c
index 506acaba687417..63d8205866d7b4 100644
--- a/clang/test/CodeGen/RISCV/riscv-func-attr-target.c
+++ b/clang/test/CodeGen/RISCV/riscv-func-attr-target.c
@@ -37,11 +37,11 @@ __attribute__((target("cpu=sifive-u54"))) void testAttrCpuOnly() {}
 
 //.
 // CHECK: attributes #0 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zifencei,-relax,-zbb,-zfa" }
-// CHECK: attributes #1 = { {{.*}}"target-cpu"="rocket-rv64" "target-features"="+64bit,+a,+d,+f,+m,+save-restore,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-relax,-zbb,-zfa" "tune-cpu"="generic-rv64" }
+// CHECK: attributes #1 = { {{.*}}"target-features"="+64bit,+a,+d,+f,+m,+save-restore,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-relax,-zbb,-zfa" "tune-cpu"="generic-rv64" }
 // CHECK: attributes #2 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zbb,+zifencei,-relax,-zfa" }
 // CHECK: attributes #3 = { {{.*}}"target-features"="+64bit,+a,+d,+experimental-zicond,+f,+m,+save-restore,+v,+zbb,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-relax,-zfa" }
-// CHECK: attributes #4 = { {{.*}}"target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zbb,+zicsr,+zifencei,-relax,-zfa" }
-// CHECK: attributes #5 = { {{.*}}"target-features"="+64bit,+m,+save-restore,-relax,-zbb,-zfa" }
-// CHECK: attributes #6 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+m,+save-restore,+zbb,+zifencei,-relax,-zfa" }
-// CHECK: attributes #7 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+m,+save-restore,-relax,-zbb,-zfa" }
+// CHECK: attributes #4 = { {{.*}}"target-cpu"="generic-rv64" "target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zbb,+zicsr,+zifencei,-relax,-zfa" }
+// CHECK: attributes #5 = { {{.*}}"target-cpu"="generic-rv64" "target-features"="+64bit,+m,+save-restore,-relax,-zbb,-zfa" }
+// CHECK: attributes #6 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zbb,+zifencei,-relax,-zfa" "tune-cpu"="sifive-u54" }
+// CHECK: attributes #7 = { {{.*}}"target-cpu"="generic-rv64" "target-features"="+64bit,+m,+save-restore,-relax,-zbb,-zfa" "tune-cpu"="sifive-u54" }
 // CHECK: attributes #8 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zicsr,+zifencei,-relax,-zbb,-zfa" }
diff --git a/llvm/test/CodeGen/RISCV/riscv-func-target-feature-mcpu-override.ll b/llvm/test/CodeGen/RISCV/riscv-func-target-feature-mcpu-override.ll
new file mode 100644
index 00000000000000..5057384d57cdf9
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/riscv-func-target-feature-mcpu-override.ll
@@ -0,0 +1,36 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
+; RUN: llc -mtriple=riscv64 -mcpu=sifive-x280 -verify-machineinstrs < %s | FileCheck %s
+
+define <2 x i16> @vwaddu_v2i16_without_custom_target_cpu(ptr %x, ptr %y) "target-feature"="+64bit,+a,+m,+c,+f" {
+; CHECK-LABEL: vwaddu_v2i16_without_custom_target_cpu:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vsetivli zero, 2, e8, mf8, ta, ma
+; CHECK-NEXT:    vle8.v v9, (a0)
+; CHECK-NEXT:    vle8.v v10, (a1)
+; CHECK-NEXT:    vwaddu.vv v8, v9, v10
+; CHECK-NEXT:    ret
+  %a = load <2 x i8>, ptr %x
+  %b = load <2 x i8>, ptr %y
+  %c = zext <2 x i8> %a to <2 x i16>
+  %d = zext <2 x i8> %b to <2 x i16>
+  %e = add <2 x i16> %c, %d
+  ret <2 x i16> %e
+}
+
+define <2 x i16> @vwaddu_v2i16_with_custom_target_cpu(ptr %x, ptr %y) "target-cpu"="generic-rv64" "target-feature"="+64bit,+a,+m,+c,+f" {
+; CHECK-LABEL: vwaddu_v2i16_with_custom_target_cpu:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lbu a2, 1(a0)
+; CHECK-NEXT:    lbu a0, 0(a0)
+; CHECK-NEXT:    lbu a3, 0(a1)
+; CHECK-NEXT:    lbu a1, 1(a1)
+; CHECK-NEXT:    add a0, a0, a3
+; CHECK-NEXT:    add a1, a2, a1
+; CHECK-NEXT:    ret
+  %a = load <2 x i8>, ptr %x
+  %b = load <2 x i8>, ptr %y
+  %c = zext <2 x i8> %a to <2 x i16>
+  %d = zext <2 x i8> %b to <2 x i16>
+  %e = add <2 x i16> %c, %d
+  ret <2 x i16> %e
+}

>From f509ad57c20e266ea6ec39adcf766a48a2c5e9a7 Mon Sep 17 00:00:00 2001
From: Piyou Chen <piyou.chen at sifive.com>
Date: Thu, 28 Dec 2023 08:15:52 -0800
Subject: [PATCH 2/2] Move logic into RISCVTargetInfo::parseTargetAttr

---
 clang/lib/Basic/Targets/RISCV.cpp   | 30 +++++++++++++++++++++++++++++
 clang/lib/CodeGen/CodeGenModule.cpp | 25 ------------------------
 2 files changed, 30 insertions(+), 25 deletions(-)

diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index 60a4e0ed69c34d..fcbc6101776c16 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -482,5 +482,35 @@ ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const {
       Ret.Tune = AttrString;
     }
   }
+
+  StringRef MCPU = this->getTargetOpts().CPU;
+  StringRef MTune = this->getTargetOpts().TuneCPU;
+
+  // attr-cpu override march only if arch isn't present.
+  if (FoundArch) {
+    // If tune-cpu infer from CPU, then try to keep it.
+    // Otherwise, just use current tune option.
+    if (Ret.Tune.empty() && MTune.empty()) {
+      if (!Ret.CPU.empty())
+        Ret.Tune = Ret.CPU; // Keep attr-cpu in tune-cpu
+      else if (!MCPU.empty())
+        Ret.Tune = MCPU; // Keep mcpu in tune-cpu
+    }
+
+    // Reassign mcpu due to attr-arch=<Adding-Extension> need
+    // target-feature from mcpu/march.
+    // Use attr-cpu will affect target-feature.
+    Ret.CPU = MCPU;
+
+    // arch=<full-arch-string> need keep target feature clean,
+    // use the baseline cpu.
+    if (llvm::find(Ret.Features, "__RISCV_TargetAttrNeedOverride") !=
+        Ret.Features.end())
+      Ret.CPU =
+          (this->getTriple().isRISCV32()) ? "generic-rv32" : "generic-rv64";
+
+    if (Ret.CPU == Ret.Tune)
+      Ret.Tune = "";
+  }
   return Ret;
 }
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 83a530f1fee45d..7ad26ace328ab2 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -2571,31 +2571,6 @@ bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD,
       if (!ParsedAttr.Tune.empty() &&
           getTarget().isValidCPUName(ParsedAttr.Tune))
         TuneCPU = ParsedAttr.Tune;
-
-      if (getTarget().getTriple().isRISCV()) {
-        // attr-cpu override march only if arch isn't present.
-        if (TD->getFeaturesStr().contains("arch=")) {
-          // Before drop attr-cpu, keep it in tune-cpu
-          if (!TargetCPU.empty() && TuneCPU.empty())
-            TuneCPU = TargetCPU;
-
-          // Reassign mcpu due to attr-arch=<Adding-Extension> need
-          // target-feature from mcpu/march.
-          // Use attr-cpu will affect target-feature.
-          TargetCPU = getTarget().getTargetOpts().CPU;
-
-          // arch=<full-arch-string> need keep target feature clean,
-          // use the baseline cpu.
-          if (llvm::find(ParsedAttr.Features,
-                         "__RISCV_TargetAttrNeedOverride") !=
-              ParsedAttr.Features.end())
-            TargetCPU = (getTarget().getTriple().isRISCV32()) ? "generic-rv32"
-                                                              : "generic-rv64";
-
-          if (TargetCPU == TuneCPU)
-            TuneCPU = "";
-        }
-      }
     }
 
     if (SD) {



More information about the llvm-commits mailing list