Skip to content

Commit 239a41e

Browse files
committed
Re-Reland [X86] Respect code models more when determining if a global reference can fit in 32 bits (llvm#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... First reland broke large PIC builds referencing small data since it was using GOTOFF as a 32-bit constant.
1 parent e692d08 commit 239a41e

File tree

7 files changed

+203
-134
lines changed

7 files changed

+203
-134
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
@@ -649,7 +649,7 @@ getELFSectionNameForGlobal(const GlobalObject *GO, SectionKind Kind,
649649
Name = ".rodata.cst";
650650
Name += utostr(EntrySize);
651651
} else {
652-
Name = getSectionPrefixForGlobal(Kind, TM.isLargeGlobalObject(GO));
652+
Name = getSectionPrefixForGlobal(Kind, TM.isLargeGlobalValue(GO));
653653
}
654654

655655
bool HasPrefix = false;
@@ -769,7 +769,7 @@ getGlobalObjectInfo(const GlobalObject *GO, const TargetMachine &TM) {
769769
Group = C->getName();
770770
IsComdat = C->getSelectionKind() == Comdat::Any;
771771
}
772-
if (TM.isLargeGlobalObject(GO))
772+
if (TM.isLargeGlobalValue(GO))
773773
Flags |= ELF::SHF_X86_64_LARGE;
774774
return {Group, IsComdat, Flags};
775775
}

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: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2927,6 +2927,13 @@ 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+
// Cannot use 32 bit constants to reference objects in large PIC mode since
2932+
// GOTOFF is 64 bits.
2933+
if (TM.getCodeModel() == CodeModel::Kernel ||
2934+
(TM.getCodeModel() == CodeModel::Large && TM.isPositionIndependent()))
2935+
return false;
2936+
29302937
// In static codegen with small code model, we can get the address of a label
29312938
// into a register with 'movl'
29322939
if (N->getOpcode() != X86ISD::Wrapper)
@@ -2940,15 +2947,18 @@ bool X86DAGToDAGISel::selectMOV64Imm32(SDValue N, SDValue &Imm) {
29402947
return false;
29412948

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

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

2951-
return CR->getUnsignedMax().ult(1ull << 32);
2961+
return !TM.isLargeGlobalValue(GV);
29522962
}
29532963

29542964
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)