Skip to content

[RISCV] Update TargetAttr target-cpu override rule #75804

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 30 additions & 0 deletions clang/lib/Basic/Targets/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this here is confusing because it is possible to specify a CPU that gets overridden if there is a full arch string. I think this drops the scheduler model which was not intended?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The scheduler model should come from Tune shouldn't it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like RISCVProcessorModel takes a name n which I think corresponds to the mcpu name, and a SchedMachineModel m which I thought was the SchedModel. But I also see that RISCVTuneProcessorModel seems to tie the SchedModel to the Tune. So maybe the answer is that it can come from both?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RISCVProcessorModel defines names that can be used for -mcpu and -mtune. RISCVTuneProcessorModel defines name that can only be used for -mtune. These just associate scheduler models with strings. You need to look at C++ code to see how -mcpu and -mtune are propagated.

This code gets the TuneCPU from the tune-cpu function attribute if present. Otherwise its the same as the CPU. Where CPU either comes from the target-cpu attribute or the TargetCPU in TargetMachine. There is no TuneCPU in TargetMachine so it can only be set differently through the tune-cpu attribute.

const RISCVSubtarget *                                                           
RISCVTargetMachine::getSubtargetImpl(const Function &F) const {                  
  Attribute CPUAttr = F.getFnAttribute("target-cpu");                            
  Attribute TuneAttr = F.getFnAttribute("tune-cpu");                             
  Attribute FSAttr = F.getFnAttribute("target-features");                        
                                                                                 
  std::string CPU =                                                              
      CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;          
  std::string TuneCPU =                                                          
      TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;

The lookup function for the scheduler is here

void MCSubtargetInfo::InitMCProcessorInfo(StringRef CPU, StringRef TuneCPU,      
                                          StringRef FS) {                        
  FeatureBits = getFeatures(CPU, TuneCPU, FS, ProcDesc, ProcFeatures);           
  FeatureString = std::string(FS);                                               
                                                                                 
  if (!TuneCPU.empty())                                                          
    CPUSchedModel = &getSchedModelForCPU(TuneCPU);                               
  else                                                                           
    CPUSchedModel = &MCSchedModel::Default;                                      
} 

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for sharing this code. I was looking around for it but couldn't quite find it.

(this->getTriple().isRISCV32()) ? "generic-rv32" : "generic-rv64";

if (Ret.CPU == Ret.Tune)
Ret.Tune = "";
}
return Ret;
}
63 changes: 63 additions & 0 deletions clang/test/CodeGen/RISCV/riscv-func-attr-target-mcpu-rv32.c
Original file line number Diff line number Diff line change
@@ -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" }
63 changes: 63 additions & 0 deletions clang/test/CodeGen/RISCV/riscv-func-attr-target-mcpu-rv64.c
Original file line number Diff line number Diff line change
@@ -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" }
10 changes: 5 additions & 5 deletions clang/test/CodeGen/RISCV/riscv-func-attr-target.c
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
36 changes: 36 additions & 0 deletions llvm/test/CodeGen/RISCV/riscv-func-target-feature-mcpu-override.ll
Original file line number Diff line number Diff line change
@@ -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
}