Skip to content

Commit ec92d74

Browse files
committed
Reland [X86] Respect code models more when determining if a global reference can fit in 32 bits (#75386)
For non-GlobalValue references, the small and medium code models can use 32 bit constants. For GlobalValue references, use TargetMachine::isLargeGlobalObject(). Look through aliases for determining if a GlobalValue is small or large. Even the large code model can reference small objects with 32 bit constants as long as we're in no-pic mode, or if the reference is offset from the GOT. Original commit broke the build...
1 parent f976719 commit ec92d74

File tree

7 files changed

+209
-143
lines changed

7 files changed

+209
-143
lines changed

llvm/include/llvm/Target/TargetMachine.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ class TargetMachine {
239239
void setCodeModel(CodeModel::Model CM) { CMModel = CM; }
240240

241241
void setLargeDataThreshold(uint64_t LDT) { LargeDataThreshold = LDT; }
242-
bool isLargeGlobalObject(const GlobalObject *GO) const;
242+
bool isLargeGlobalValue(const GlobalValue *GV) const;
243243

244244
bool isPositionIndependent() const;
245245

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ getELFSectionNameForGlobal(const GlobalObject *GO, SectionKind Kind,
645645
Name = ".rodata.cst";
646646
Name += utostr(EntrySize);
647647
} else {
648-
Name = getSectionPrefixForGlobal(Kind, TM.isLargeGlobalObject(GO));
648+
Name = getSectionPrefixForGlobal(Kind, TM.isLargeGlobalValue(GO));
649649
}
650650

651651
bool HasPrefix = false;
@@ -765,7 +765,7 @@ getGlobalObjectInfo(const GlobalObject *GO, const TargetMachine &TM) {
765765
Group = C->getName();
766766
IsComdat = C->getSelectionKind() == Comdat::Any;
767767
}
768-
if (TM.isLargeGlobalObject(GO))
768+
if (TM.isLargeGlobalValue(GO))
769769
Flags |= ELF::SHF_X86_64_LARGE;
770770
return {Group, IsComdat, Flags};
771771
}

llvm/lib/Target/TargetMachine.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,16 @@ TargetMachine::TargetMachine(const Target &T, StringRef DataLayoutString,
3939

4040
TargetMachine::~TargetMachine() = default;
4141

42-
bool TargetMachine::isLargeGlobalObject(const GlobalObject *GO) const {
42+
bool TargetMachine::isLargeGlobalValue(const GlobalValue *GVal) const {
4343
if (getTargetTriple().getArch() != Triple::x86_64)
4444
return false;
4545

46+
auto *GO = GVal->getAliaseeObject();
47+
48+
// Be conservative if we can't find an underlying GlobalObject.
49+
if (!GO)
50+
return true;
51+
4652
auto *GV = dyn_cast<GlobalVariable>(GO);
4753

4854
// Functions/GlobalIFuncs are only large under the large code model.

llvm/lib/Target/X86/X86FastISel.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -716,10 +716,8 @@ bool X86FastISel::handleConstantAddresses(const Value *V, X86AddressMode &AM) {
716716
return false;
717717

718718
// Can't handle large objects yet.
719-
if (auto *GO = dyn_cast<GlobalObject>(GV)) {
720-
if (TM.isLargeGlobalObject(GO))
721-
return false;
722-
}
719+
if (TM.isLargeGlobalValue(GV))
720+
return false;
723721

724722
// Can't handle TLS yet.
725723
if (GV->isThreadLocal())
@@ -3849,7 +3847,7 @@ unsigned X86FastISel::X86MaterializeGV(const GlobalValue *GV, MVT VT) {
38493847
if (TM.getCodeModel() != CodeModel::Small &&
38503848
TM.getCodeModel() != CodeModel::Medium)
38513849
return 0;
3852-
if (!isa<GlobalObject>(GV) || TM.isLargeGlobalObject(cast<GlobalObject>(GV)))
3850+
if (TM.isLargeGlobalValue(GV))
38533851
return 0;
38543852

38553853
// Materialize addresses with LEA/MOV instructions.

llvm/lib/Target/X86/X86ISelDAGToDAG.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2927,6 +2927,10 @@ bool X86DAGToDAGISel::selectAddr(SDNode *Parent, SDValue N, SDValue &Base,
29272927
}
29282928

29292929
bool X86DAGToDAGISel::selectMOV64Imm32(SDValue N, SDValue &Imm) {
2930+
// Cannot use 32 bit constants to reference objects in kernel code model.
2931+
if (TM.getCodeModel() == CodeModel::Kernel)
2932+
return false;
2933+
29302934
// In static codegen with small code model, we can get the address of a label
29312935
// into a register with 'movl'
29322936
if (N->getOpcode() != X86ISD::Wrapper)
@@ -2940,15 +2944,18 @@ bool X86DAGToDAGISel::selectMOV64Imm32(SDValue N, SDValue &Imm) {
29402944
return false;
29412945

29422946
Imm = N;
2943-
if (N->getOpcode() != ISD::TargetGlobalAddress)
2944-
return TM.getCodeModel() == CodeModel::Small;
2947+
// Small/medium code model can reference non-TargetGlobalAddress objects with
2948+
// 32 bit constants.
2949+
if (N->getOpcode() != ISD::TargetGlobalAddress) {
2950+
return TM.getCodeModel() == CodeModel::Small ||
2951+
TM.getCodeModel() == CodeModel::Medium;
2952+
}
29452953

2946-
std::optional<ConstantRange> CR =
2947-
cast<GlobalAddressSDNode>(N)->getGlobal()->getAbsoluteSymbolRange();
2948-
if (!CR)
2949-
return TM.getCodeModel() == CodeModel::Small;
2954+
const GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
2955+
if (std::optional<ConstantRange> CR = GV->getAbsoluteSymbolRange())
2956+
return CR->getUnsignedMax().ult(1ull << 32);
29502957

2951-
return CR->getUnsignedMax().ult(1ull << 32);
2958+
return !TM.isLargeGlobalValue(GV);
29522959
}
29532960

29542961
bool X86DAGToDAGISel::selectLEA64_32Addr(SDValue N, SDValue &Base,

llvm/lib/Target/X86/X86Subtarget.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,16 @@ X86Subtarget::classifyLocalReference(const GlobalValue *GV) const {
8686
CodeModel::Model CM = TM.getCodeModel();
8787
assert(CM != CodeModel::Tiny &&
8888
"Tiny codesize model not supported on X86");
89-
// In the large code model, even referencing a global under the large data
90-
// threshold which is considered "small", we need to use GOTOFF.
89+
// In the large code model, all text is far from any global data, so we
90+
// use GOTOFF.
9191
if (CM == CodeModel::Large)
9292
return X86II::MO_GOTOFF;
93-
// Large objects use GOTOFF, otherwise use RIP-rel access.
94-
if (auto *GO = dyn_cast_or_null<GlobalObject>(GV))
95-
return TM.isLargeGlobalObject(GO) ? X86II::MO_GOTOFF
96-
: X86II::MO_NO_FLAG;
97-
// For non-GlobalObjects, the small and medium code models treat them as
98-
// accessible with a RIP-rel access.
93+
// Large GlobalValues use GOTOFF, otherwise use RIP-rel access.
94+
if (GV)
95+
return TM.isLargeGlobalValue(GV) ? X86II::MO_GOTOFF : X86II::MO_NO_FLAG;
96+
// GV == nullptr is for all other non-GlobalValue global data like the
97+
// constant pool, jump tables, labels, etc. The small and medium code
98+
// models treat these as accessible with a RIP-rel access.
9999
return X86II::MO_NO_FLAG;
100100
}
101101

0 commit comments

Comments
 (0)