Skip to content
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

[AIX] Support per global code model. #79202

Merged
merged 9 commits into from
Mar 15, 2024

Conversation

mandlebug
Copy link
Contributor

Exploit the per global code model attribute on AIX. On AIX we need to update both the code sequence used to access the global (either 1 or 2 instructions for small and large code model respectively) and the storage mapping class that we emit the toc entry.

return ModuleModel;

std::optional<CodeModel::Model> MaybeCodeModel =
dyn_cast<GlobalVariable>(GV)->getCodeModel();
Copy link
Contributor

Choose a reason for hiding this comment

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

dyn_cast maybe return a nullptr, do we need to check dyn_cast(GV) not nullptr here ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have an early return on !isa<GlobalVariable>(GV)) so we know dyn_cast must not fail - and because of that I should be using cast<> instead. I'll update it.

llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp Show resolved Hide resolved
llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp Show resolved Hide resolved
return;

const GlobalVariable *GVar = cast<GlobalVariable>(GV);
std::optional<CodeModel::Model> MaybeCM = GVar->getCodeModel();
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: do not need to introduce a new variable GVar, since it only be used once

case MachineOperand::MO_GlobalAddress: {
const GlobalValue *GV = MO.getGlobal();
MCSymbol *Sym = AP.getSymbol(GV);
checkPerGlobalCodeModel(GV, Sym);
Copy link
Contributor

@diggerlin diggerlin Jan 29, 2024

Choose a reason for hiding this comment

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

I am not sure whether it is a good place to checkPerGlobalCodeModel in the getMCSymbolForTOCPseudoMO , This means that an MCSymbolXCOFF may end up setting PerSymbolCodeModel several times, depending on how many times the GV is used as an operand

how about to do it in

 bool PPCAIXAsmPrinter::doInitiation() {
 .....
  for (const auto &G : M.globals()) {
     ..
      MCSymbol *Sym = getSymbol(&G);
      checkPerGlobalCodeModel(%G, Sym)
    }

return;

static std::optional<CodeModel::Model>
hasPerGlobalCodeModel(const GlobalValue *GV) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit , the functionality looks like to get the CodeModel::Model , change the function name to getPerGlobalCodeModel

; CHECK-SMALL32: lwz [[SCRATCH:[0-9]+]], L..C[[TL_F:[0-9]+]](2)
; CHECK-LARGE64: ld [[SCRATCH:[0-9]+]], L..C[[TL_F]]@l([[HI]])
; CHECK-SMALL64: ld [[SCRATCH:[0-9]+]], L..C[[TL_F:[0-9]+]](2)
; CHECK: lwz 3, 0([[SCRATCH]])
Copy link
Contributor

@diggerlin diggerlin Feb 21, 2024

Choose a reason for hiding this comment

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

since the only different of 32bit and 64 bit is lwz and ld
for example:
CHECK-LARGE32: lwz [[SCRATCH:[0-9]+]], L..C[[TL_F]]@l([[HI]])
CHECK-LARGE64: ld [[SCRATCH:[0-9]+]], L..C[[TL_F]]@l([[HI]])

I will change like as following to make the test case simple.

RUN: %s | FileCheck --check-prefixes=CHECK,CHECK32,CHECK-LARGE,CHECK-LARGE32

to

RUN: %s | FileCheck -DINSTR=lwz --check-prefixes=CHECK,CHECK32,CHECK-LARGE

CHECK-LARGE: [[INSTR]] [[SCRATCH:[0-9]+]], L..C[[TL_F]]@l([[HI]]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I like the suggestion in that it simplifies the number of check prefixes we have, but then it also buries some of the details behind the macro. I was looking at the difference in the toc peephole patch (since the testing there seems to have gone from using the macro to now using it) and personally prefer having the extra check but easier to read output - mainly because we are already impacting the readability by having to have match variables for the labels in the TOC. If you feel really strongly let me know and I will change it over to your suggestion.

}
; CHECK: addis [[HI:[0-9]+]], L..C[[TL_D]]@u(2)
; CHECK32: lwz 3, L..C[[TL_D]]@l([[HI]])
; CHECK64: ld 3, L..C[[TL_D]]@l([[HI]])
Copy link
Contributor

@diggerlin diggerlin Feb 21, 2024

Choose a reason for hiding this comment

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

ditto, we can use -DINSTR=lwz or -DINSTR=ld

; CHECK-LARGE32: lwz [[SCRATCH:[0-9]+]], L..C[[TL_E]]@l([[HI]])
; CHECK-SMALL32: lwz [[SCRATCH:[0-9]+]], L..C[[TL_E:[0-9]+]](2)
; CHECK-LARGE64: ld [[SCRATCH:[0-9]+]], L..C[[TL_E]]@l([[HI]])
; CHECK-SMALL64: ld [[SCRATCH:[0-9]+]], L..C[[TL_E:[0-9]+]](2)
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto as below comment.

const TargetMachine &TM) {
const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(Sym);
// Use large code model toc entries for ehinfo symbols as they are
// never refrenced directly. The runtime loads their TOC entries
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: refrenced -> referenced

const TargetMachine &TM) {
const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(Sym);
// Use large code model toc entries for ehinfo symbols as they are
// never refrenced directly. The runtime loads their TOC entries
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: their TOC entries address -> their TOC entry addresses

const TargetMachine &TM,
const MachineOperand &MO) {
CodeModel::Model ModuleModel = TM.getCodeModel();
// Per global code model is only support on AIX.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: only support -> only supported

@@ -176,6 +176,15 @@ bool PPCSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const {
// Large code model always uses the TOC even for local symbols.
if (TM.getCodeModel() == CodeModel::Large)
Copy link
Contributor

Choose a reason for hiding this comment

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

What happens if the TM.getCodeModel is large, but the specific GV is set to small?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was a really good question. I think originally I added this because it was triggering an assertion in the PPCAsmPrinter when we would emit the large code model nodes when the module code model was small. In reality both small and large code model use an indirect. That is true for both XCOFF and ELF - ELF has medium code model where we accessing things toc-relative instead of got indirect. I changed the AIX code to check for the toc-data attribute, since that is the only time a symbol would not be indirected on AIX.

The existing code is slightly wrong in that we should be returning true for both small and large code model, but because of where (and how) this function is used that change will be untestable. We can update it in a separate NFC patch to make it correct at least, and when we add support for per global code model for ELF then it would be come testable.

@mandlebug mandlebug force-pushed the sfertile/AIXCodeModelAttribute branch from 3dbf6c9 to 9e5eb9a Compare March 4, 2024 20:58
@mandlebug
Copy link
Contributor Author

rebased and force pushed as there were conflicting changes that had landed since this PR was first posted.

Copy link

github-actions bot commented Mar 4, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

llvm/include/llvm/MC/MCSymbolXCOFF.h Outdated Show resolved Hide resolved
llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp Outdated Show resolved Hide resolved
@@ -186,9 +186,18 @@ bool PPCSubtarget::enableSubRegLiveness() const {
}

bool PPCSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const {
if (isAIXABI() && isa<GlobalVariable>(GV)) {
// On AIX the only symbols that aren't indirect are toc-data.
if (cast<GlobalVariable>(GV)->hasAttribute("toc-data"))
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: According to https://llvm.org/docs/ProgrammersManual.html#the-isa-cast-and-dyn-cast-templates, we should try not to use isa<> followed by <cast>?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated to use dyn_cast

llvm/lib/Target/PowerPC/PPCSubtarget.cpp Show resolved Hide resolved
Copy link
Collaborator

@chenzheng1030 chenzheng1030 left a comment

Choose a reason for hiding this comment

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

At first glance, the code diff is larger than what I thought. I original thought we just need a small change to fix the code generation for per global code model in ISEL-DAG phase.

But seems to keep the optimization of keeping large code model symbols with TE SMC, most of the code changes are for recording code model for a XCOFF symbol because there is no direct mapping between MCSymbolXCOFF and GlobalVariable. I cannot find a better way to avoid these codes either...

case MachineOperand::MO_GlobalAddress:
return AP.getSymbol(MO.getGlobal());
case MachineOperand::MO_GlobalAddress: {
const GlobalValue *GV = MO.getGlobal();
Copy link
Collaborator

Choose a reason for hiding this comment

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

This seems unnecessary?

llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp Show resolved Hide resolved
Copy link
Contributor

@diggerlin diggerlin left a comment

Choose a reason for hiding this comment

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

I put other two small comment. I do not have further comment on the patch, please address zhengchen's comment and wait for zhengchen happy with the PR.

llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp Show resolved Hide resolved
return CM;
}

return ModuleModel;
Copy link
Contributor

@diggerlin diggerlin Mar 11, 2024

Choose a reason for hiding this comment

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

nit : we can change the code from line 574 ~591 to (I do not have strong suggestion on the change, feel free to keep your code if you want)

if (auto *GValue = dyn_cast<GlobalAddressSDNode>(Node->getOperand(0)){
  if(auto *GVar = dyn_cast<GlobalVariable>(GV)){
      std::optional<CodeModel::Model> MaybeCodeModel =GV->getCodeModel();
  if (MaybeCodeModel) {
    CodeModel::Model CM = *MaybeCodeModel;
    assert((CM == CodeModel::Small || CM == CodeModel::Large) &&
           "invalid code model for AIX");
    return CM;
    } 
 }
 }
return ModuleModel;

Copy link
Collaborator

@chenzheng1030 chenzheng1030 left a comment

Choose a reason for hiding this comment

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

LGTM too. Thanks for making the improvement.

@mandlebug mandlebug force-pushed the sfertile/AIXCodeModelAttribute branch from 3fd3217 to 701e485 Compare March 14, 2024 16:22
mandlebug and others added 6 commits March 15, 2024 10:19
Exploit the per global code model attribute on AIX. On AIX we need to
update both the code sequence used to access the global (either 1 or
2 instructions for small and large code model respectively) and the
storage mapping class that we emit the toc entry.
- convert assert to early return.
- change dyn_cast<> following an isa<> to a cast<>
- remove a null check after a cast<>
- Change setting per global code model on MCSymbol to the ASMPrinters
  initialization so it happens once.
- Add some globals without explicit code models to the lit test.
- Fixed some spelling mistakes in comments.
- renamed function that retreives the per global code model.
- updated the AIX specific code in isGVIndirectSymbol.
Co-authored-by: Amy Kwan <akwan0907@gmail.com>
mandlebug and others added 3 commits March 15, 2024 10:19
Co-authored-by: Amy Kwan <akwan0907@gmail.com>
- use dyn_cast instad of isa + cast
- remove erroneously added newline in otherwise untouched code.
- Added support for looking through aliases to the aliasees objects code
  model, along with lit testing.
- Split the shared code of 'getCodeModel' into PPCSubtarget and have
  PPCISelDAGToDAG and PPCAsmPrinter use that.
- Undo unintended change to 'getMCSymbolForTOCPsudoMO' that was left when
  addressing earlier comments.
@mandlebug mandlebug force-pushed the sfertile/AIXCodeModelAttribute branch from 701e485 to a77ce54 Compare March 15, 2024 15:15
@lei137 lei137 merged commit 2d80505 into llvm:main Mar 15, 2024
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants