This is an archive of the discontinued LLVM Phabricator instance.

[RISCV] Support target attribute for function
ClosedPublic

Authored by BeMg on May 30 2023, 9:11 AM.

Details

Summary

The proposal of target attribute is https://github.com/riscv-non-isa/riscv-c-api-doc/pull/35

This patch implements it by emitting .option arch during codegen.

Diff Detail

Event Timeline

BeMg created this revision.May 30 2023, 9:11 AM
Herald added a project: Restricted Project. · View Herald TranscriptMay 30 2023, 9:11 AM
BeMg requested review of this revision.May 30 2023, 9:11 AM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptMay 30 2023, 9:11 AM
BeMg retitled this revision from [RISCV] Support target attribute for function to [WIP][RISCV] Support target attribute for function.May 30 2023, 9:16 AM
BeMg edited the summary of this revision. (Show Details)
craig.topper added inline comments.
clang/test/CodeGen/RISCV/riscv-func-attr-target.c
2

No test for tune=?

BeMg retitled this revision from [WIP][RISCV] Support target attribute for function to [RISCV] Support target attribute for function.May 31 2023, 3:46 AM
BeMg edited the summary of this revision. (Show Details)
BeMg added reviewers: asb, craig.topper, kito-cheng, jrtc27.

Testcase for backend?

BeMg updated this revision to Diff 527748.Jun 1 2023, 11:06 PM
  1. Update RTS's function name
  2. Add backend testcase
kito-cheng added inline comments.Jun 2 2023, 1:52 AM
clang/test/CodeGen/RISCV/riscv-func-attr-target.c
11

It's ext list or full arch, can't mixed together.

ARCH-ATTR   := 'arch=' EXTENSIONS-OR-FULLARCH
EXTENSIONS-OR-FULLARCH := <EXTENSIONS>
                        | <FULLARCHSTR>
35

The extension name is zihintntl not experimental-zihintntl, I would suggest either drop the experimental extension support or requiring the version number to be specified.

BeMg updated this revision to Diff 528390.Jun 5 2023, 5:58 AM
  1. Update testcase
  2. Support -<EXTENSION>
  3. Verfy extension version
BeMg updated this revision to Diff 529510.Jun 7 2023, 11:30 PM

Use isSupportedExtensionWithVersion to implement parseTargetAttr

MaskRay added inline comments.Jun 8 2023, 8:26 AM
clang/test/CodeGen/RISCV/riscv-func-attr-target.c
3

-target has been deprecated since Clang 3.x. Use --target= for new tests.

Prefer %clang_cc1 for non-Driver tests. Only use %clang in test/Driver

6

We don't format tests, so this annotation is unneeded.

craig.topper added inline comments.Jun 8 2023, 11:48 AM
clang/include/clang/Basic/TargetInfo.h
1401 ↗(On Diff #529510)

Is this needed for target attribute? The description to me reads like its for doing runtime dispatch with ifunc.

clang/lib/Basic/Targets/RISCV.cpp
313

UpdatedFeatures.insert(UpdatedFeatures.end(), ImpliedFeatures.begin(), ImpliedFeatures.end())

llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
247 ↗(On Diff #529510)

const auto &Feature

BeMg updated this revision to Diff 529906.Jun 9 2023, 4:16 AM
  1. Update testcase
  2. Remove supportsMultiVersioning for RISCV
craig.topper added inline comments.Jun 23 2023, 6:01 PM
clang/lib/Basic/Targets/RISCV.cpp
421

Attrstring -> AttrString

436

Why std::string, don't all 3 functions its passed to take a StringRef?

443

We can't write directly to llvm::errs(). It needs to go through clang's Diagnostics code.

BeMg updated this revision to Diff 534428.Jun 25 2023, 10:47 PM
  1. Attrstring -> AttrString
  2. using StringRef instead of string
  3. Append unsupported target feature Let follow-up procedure raise diagnostic code
BeMg updated this revision to Diff 535191.Jun 27 2023, 4:52 PM
BeMg marked 8 inline comments as done.

Add const

BeMg marked 2 inline comments as done.Jun 27 2023, 4:53 PM
craig.topper added inline comments.Jun 27 2023, 4:58 PM
clang/lib/Basic/Targets/RISCV.cpp
437

I wonder if we could encapsulate this if and the 3 calls into RISCVISAInfo into a single function in RISCVISAInfo?

Basically we want to know if an extension that may or may not have a version, is a valid extension and if so what is the target feature name for it. We could have one function that does all that and returns the target feature name or an empty string.

craig.topper added inline comments.Jun 28 2023, 10:48 PM
clang/lib/Basic/Targets/RISCV.cpp
437

I think I explained my idea poorly. I was wondering about having a function that allowed us to write

std::string TargetFeature = llvm::RISCVISAInfo::getTargetFeatureForExtension(ExtName);
if (!TargetFeature.empty())
  Ret.Features.push_back(Ext.front() + TargetFeature);
else
  Ret.Features.push_back(Ext.str());
BeMg added inline comments.Jun 28 2023, 11:23 PM
clang/lib/Basic/Targets/RISCV.cpp
437

Thank you for further explanation. I think getTargetFeatureFromOneExt can do this job.

std::string TargetFeature = llvm::RISCVISAInfo::getTargetFeatureFromOneExt(ExtName);
if (!TargetFeature.empty())
    Ret.Features.push_back(Ext.front() + TargetFeature);
else
    Ret.Features.push_back(Ext.str());
BeMg updated this revision to Diff 535653.Jun 29 2023, 12:17 AM

Use getTargetFeatureForExtension instead of isSupportExtension

reames added a subscriber: reames.Jul 7 2023, 10:29 AM

Can you separate the change to RISCVAsmPrinter.cpp into it's own review? This looks useful for any case where we have functions in the same model with different function attributes. The attribute((target...) syntax is one way to have that, but there are also others. LTO will see this, and so may other frontends.

This will also help with review as the set of people who can review RISCV backend changes and clang frontend changes is fairly non-overlapping.

llvm/test/CodeGen/RISCV/riscv-func-attr-target.ll
5 ↗(On Diff #535653)

This test would be a lot easier to follow if you pruned all the spurious attributes, and uses the inline attribute syntax rather than the #0 reference syntax.

FYI, this change appears to be a partial diff. Locally, I need to add RISCV to supportsMultiVersioning() to get this to work at all.

Isn't multiversioning a separate thing that builds on top of per-function target attributes?

Isn't multiversioning a separate thing that builds on top of per-function target attributes?

That's what I thought. The supportsMultiVersioning call was in an earlier version of the patch that I asked about.

BeMg updated this revision to Diff 539428.Jul 12 2023, 1:57 AM
  1. simplify riscv-func-attr-target.ll
  2. handle corner case in parseTargetAttr

Isn't multiversioning a separate thing that builds on top of per-function target attributes?

That's what I thought. The supportsMultiVersioning call was in an earlier version of the patch that I asked about.

Yeah, looks like I got confused.

I hadn't expected that target("default") would automatically be considered multi-versioning, even when there was one definition of the function. As such, my test case was accidentally testing multi-versioning even when I hadn't meant to.

BeMg updated this revision to Diff 539856.Jul 12 2023, 11:17 PM

separate the change to RISCVAsmPrinter.cpp into another patch

  • Asm tests are a no in Clang
  • You seem to have some crazy long lists that I doubt need to be that long for test coverage (nor do you need so many variations, surely)
  • CHECL is not CHECK
  • You have some very strange spacing in CHECK lines
BeMg updated this revision to Diff 539901.Jul 13 2023, 2:09 AM

Update testcase

BeMg updated this revision to Diff 539907.Jul 13 2023, 2:28 AM

Move riscv-func-attr-target.ll into D155155

BeMg updated this revision to Diff 550237.Aug 15 2023, 3:27 AM

rebase and update testcase

craig.topper added inline comments.Aug 15 2023, 7:02 PM
clang/lib/Basic/Targets/RISCV.cpp
469

Is this tested? I don't see any "no-" in the the test

BeMg updated this revision to Diff 552200.Aug 21 2023, 8:41 PM

Remove some condition because RFC doesn't support it. (Must include prefix arch|cpu|tune)

BeMg updated this revision to Diff 552265.Aug 22 2023, 1:40 AM

Also remove the - operator from target attribute

BeMg updated this revision to Diff 556544.Sep 12 2023, 3:45 AM

Update to lastest spec

  1. When it exist the duplicate target attribute, select the lastest one.
  2. arch's features will override cpu's features. TargetFeature will override commandline feature.
  3. enhence the testcase
BeMg updated this revision to Diff 557943.Oct 31 2023, 6:38 AM

Align with spec

  1. duplicate target attribute will cause compilation fail
craig.topper added inline comments.Nov 2 2023, 1:41 PM
clang/lib/Basic/Targets/RISCV.cpp
240

Can we use something like

auto I = llvm::find(FeaturesVec, "__RISCV_TargetAttrNeedOverride");
if (I == FeaturesVec.end())
  return FeaturesVec;

return std::vector(I++, FeaturesVec.end());
292–295

Does this lose features like relax and save-restore? Those aren't part of the -march so they don't appear after __RISCV_TargetAttrNeedOverride

463

You don't need an else since the body of the if ended in continue. When the if is taken control flow will never reach here.

473

Why does this clear Ret.Features, but full-arch-string doesn't?

479

No need for else here

BeMg added inline comments.Nov 2 2023, 9:31 PM
clang/lib/Basic/Targets/RISCV.cpp
473

I think full-arch-string also clear the Ret.Features in line 398 right after if (Feature.startswith("arch=")).

craig.topper added inline comments.Nov 2 2023, 9:40 PM
clang/lib/Basic/Targets/RISCV.cpp
409

Why do we need "__RISCV_TargetAttrNeedOverride"?

473

Thanks. I missed it.

BeMg updated this revision to Diff 557995.Nov 2 2023, 11:45 PM
  1. remain else if by removing continue
  2. Keep NonISAExtFeature after override
  3. Update testcase with -target-feature +save-restore
  4. Improve resolveTargetOverride function
BeMg added inline comments.Nov 3 2023, 12:12 AM
clang/lib/Basic/Targets/RISCV.cpp
409

My idea is using __RISCV_TargetAttrNeedOverride to distinguish the module-level feature and target attribute feature.

The module-level feature will merge with target attribute feature in https://github.com/llvm/llvm-project/blob/main/clang/lib/AST/ASTContext.cpp#L13481. And be used/refine inside RISCVTargetInfo::initFeatureMap.

After merge, It could find the target attribute feature start point by analyzing FeatureVec, but I prefer use the __RISCV_TargetAttrNeedOverride to do this job.

craig.topper added inline comments.Sun, Nov 19, 7:04 PM
clang/lib/Basic/Targets/RISCV.cpp
240

Do we need to call find again? We already did it in the caller, can we pass that information somehow?

241

std::vector<std::string> FeaturesNeedOverride(FeaturesVec.begin(), I);

254

llvm::copy_if(FeatureNeedOveride, std::back_inserter(NonISAExtFeatureVec), [&](const std::string &Feat) { return !llvm::is_contained(ImpliedFeatures, Feat); });

BeMg updated this revision to Diff 558134.Mon, Nov 20, 3:06 AM
  1. reuse the find result
  2. replace for loop with llvm::copy_if
  3. use explicit std::vector declaration instead of auto
This revision is now accepted and ready to land.Tue, Nov 21, 11:15 AM
This revision was automatically updated to reflect the committed changes.
reames added a comment.Fri, Dec 8, 8:37 AM

In local testing, I'm seeing some very odd behavior with target attributes. It looks like target attributes are being properly handled if clang -cc1 is directly invoked, but not if the clang driver is used. Or at least that's currently my best theory.

This works:
/home/preames/llvm-dev/build/bin/clang -cc1 -triple riscv64 ~/rivos-llvm/llvm-project/clang/test/CodeGen/RISCV/riscv-func-attr-target.c -S -emit-llvm -o - -O3

This does not:
/home/preames/llvm-dev/build/bin/clang -target riscv64-unknown-linux-gnu ~/rivos-llvm/llvm-project/clang/test/CodeGen/RISCV/riscv-func-attr-target.c -S -emit-llvm -o - -O3

reames added a comment.Fri, Dec 8, 9:02 AM

I think I figured out what is going on here.

The clang driver materializes all of the target-features at the cc1 invocation command line (including the negative ones). If I manually duplicate this at the cc1 command line, that one stops working.