Skip to content

Commit 6ee2f77

Browse files
author
Chen Zheng
committed
[PowerPC][GISel] add support for fpconstant
Reviewed By: arsenm Differential Revision: https://reviews.llvm.org/D133340
1 parent 5561e17 commit 6ee2f77

File tree

15 files changed

+263
-1
lines changed

15 files changed

+263
-1
lines changed

llvm/docs/GlobalISel/GenericOpcode.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,15 @@ The address of a basic block.
6969
7070
%0:_(p0) = G_BLOCK_ADDR blockaddress(@test_blockaddress, %ir-block.block)
7171
72+
G_CONSTANT_POOL
73+
^^^^^^^^^^^^^^^
74+
75+
The address of an object in the constant pool.
76+
77+
.. code-block:: none
78+
79+
%0:_(p0) = G_CONSTANT_POOL %const.0
80+
7281
Integer Extension and Truncation
7382
--------------------------------
7483

llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ class LegalizerHelper {
359359
LegalizeResult bitcastInsertVectorElt(MachineInstr &MI, unsigned TypeIdx,
360360
LLT CastTy);
361361

362+
LegalizeResult lowerFConstant(MachineInstr &MI);
362363
LegalizeResult lowerBitcast(MachineInstr &MI);
363364
LegalizeResult lowerLoad(GAnyLoad &MI);
364365
LegalizeResult lowerStore(GStore &MI);

llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,17 @@ class MachineIRBuilder {
458458
/// \return a MachineInstrBuilder for the newly created instruction.
459459
MachineInstrBuilder buildGlobalValue(const DstOp &Res, const GlobalValue *GV);
460460

461+
/// Build and insert \p Res = G_CONSTANT_POOL \p Idx
462+
///
463+
/// G_CONSTANT_POOL materializes the address of an object in the constant
464+
/// pool.
465+
///
466+
/// \pre setBasicBlock or setMI must have been called.
467+
/// \pre \p Res must be a generic virtual register with pointer type.
468+
///
469+
/// \return a MachineInstrBuilder for the newly created instruction.
470+
MachineInstrBuilder buildConstantPool(const DstOp &Res, unsigned Idx);
471+
461472
/// Build and insert \p Res = G_PTR_ADD \p Op0, \p Op1
462473
///
463474
/// G_PTR_ADD adds \p Op1 addressible units to the pointer specified by \p Op0,

llvm/include/llvm/Support/TargetOpcodes.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,10 @@ HANDLE_TARGET_OPCODE(G_FRAME_INDEX)
290290
/// Generic reference to global value.
291291
HANDLE_TARGET_OPCODE(G_GLOBAL_VALUE)
292292

293+
/// Generic instruction to materialize the address of an object in the constant
294+
/// pool.
295+
HANDLE_TARGET_OPCODE(G_CONSTANT_POOL)
296+
293297
/// Generic instruction to extract blocks of bits from the register given
294298
/// (typically a sub-register COPY after instruction selection).
295299
HANDLE_TARGET_OPCODE(G_EXTRACT)

llvm/include/llvm/Target/GenericOpcodes.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ def G_GLOBAL_VALUE : GenericInstruction {
106106
let hasSideEffects = false;
107107
}
108108

109+
def G_CONSTANT_POOL : GenericInstruction {
110+
let OutOperandList = (outs type0:$dst);
111+
let InOperandList = (ins unknown:$src);
112+
let hasSideEffects = false;
113+
}
114+
109115
def G_INTTOPTR : GenericInstruction {
110116
let OutOperandList = (outs type0:$dst);
111117
let InOperandList = (ins type1:$src);

llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
2222
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
2323
#include "llvm/CodeGen/GlobalISel/Utils.h"
24+
#include "llvm/CodeGen/MachineConstantPool.h"
2425
#include "llvm/CodeGen/MachineFrameInfo.h"
2526
#include "llvm/CodeGen/MachineRegisterInfo.h"
2627
#include "llvm/CodeGen/TargetFrameLowering.h"
@@ -2630,6 +2631,32 @@ static void getUnmergePieces(SmallVectorImpl<Register> &Pieces,
26302631
Pieces.push_back(Unmerge.getReg(I));
26312632
}
26322633

2634+
LegalizerHelper::LegalizeResult
2635+
LegalizerHelper::lowerFConstant(MachineInstr &MI) {
2636+
Register Dst = MI.getOperand(0).getReg();
2637+
2638+
MachineFunction &MF = MIRBuilder.getMF();
2639+
const DataLayout &DL = MIRBuilder.getDataLayout();
2640+
2641+
unsigned AddrSpace = DL.getDefaultGlobalsAddressSpace();
2642+
LLT AddrPtrTy = LLT::pointer(AddrSpace, DL.getPointerSizeInBits(AddrSpace));
2643+
Align Alignment = Align(DL.getABITypeAlign(
2644+
getFloatTypeForLLT(MF.getFunction().getContext(), MRI.getType(Dst))));
2645+
2646+
auto Addr = MIRBuilder.buildConstantPool(
2647+
AddrPtrTy, MF.getConstantPool()->getConstantPoolIndex(
2648+
MI.getOperand(1).getFPImm(), Alignment));
2649+
2650+
MachineMemOperand *MMO = MF.getMachineMemOperand(
2651+
MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad,
2652+
MRI.getType(Dst), Alignment);
2653+
2654+
MIRBuilder.buildLoadInstr(TargetOpcode::G_LOAD, Dst, Addr, *MMO);
2655+
MI.eraseFromParent();
2656+
2657+
return Legalized;
2658+
}
2659+
26332660
LegalizerHelper::LegalizeResult
26342661
LegalizerHelper::lowerBitcast(MachineInstr &MI) {
26352662
Register Dst = MI.getOperand(0).getReg();
@@ -3250,6 +3277,8 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
32503277
switch(MI.getOpcode()) {
32513278
default:
32523279
return UnableToLegalize;
3280+
case TargetOpcode::G_FCONSTANT:
3281+
return lowerFConstant(MI);
32533282
case TargetOpcode::G_BITCAST:
32543283
return lowerBitcast(MI);
32553284
case TargetOpcode::G_SREM:

llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,15 @@ MachineInstrBuilder MachineIRBuilder::buildGlobalValue(const DstOp &Res,
164164
return MIB;
165165
}
166166

167+
MachineInstrBuilder MachineIRBuilder::buildConstantPool(const DstOp &Res,
168+
unsigned Idx) {
169+
assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
170+
auto MIB = buildInstr(TargetOpcode::G_CONSTANT_POOL);
171+
Res.addDefToMIB(*getMRI(), MIB);
172+
MIB.addConstantPoolIndex(Idx);
173+
return MIB;
174+
}
175+
167176
MachineInstrBuilder MachineIRBuilder::buildJumpTable(const LLT PtrTy,
168177
unsigned JTI) {
169178
return buildInstr(TargetOpcode::G_JUMP_TABLE, {PtrTy}, {})

llvm/lib/CodeGen/MachineVerifier.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,6 +1746,13 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
17461746
report("alignment immediate must be >= 1", MI);
17471747
break;
17481748
}
1749+
case TargetOpcode::G_CONSTANT_POOL: {
1750+
if (!MI->getOperand(1).isCPI())
1751+
report("Src operand 1 must be a constant pool index", MI);
1752+
if (!MRI->getType(MI->getOperand(0).getReg()).isPointer())
1753+
report("Dst operand 0 must be a pointer", MI);
1754+
break;
1755+
}
17491756
default:
17501757
break;
17511758
}

llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "PPC.h"
1414
#include "PPCInstrInfo.h"
15+
#include "PPCMachineFunctionInfo.h"
1516
#include "PPCRegisterBankInfo.h"
1617
#include "PPCSubtarget.h"
1718
#include "PPCTargetMachine.h"
@@ -54,6 +55,8 @@ class PPCInstructionSelector : public InstructionSelector {
5455

5556
bool selectZExt(MachineInstr &I, MachineBasicBlock &MBB,
5657
MachineRegisterInfo &MRI) const;
58+
bool selectConstantPool(MachineInstr &I, MachineBasicBlock &MBB,
59+
MachineRegisterInfo &MRI) const;
5760

5861
std::optional<bool> selectI64ImmDirect(MachineInstr &I,
5962
MachineBasicBlock &MBB,
@@ -62,6 +65,7 @@ class PPCInstructionSelector : public InstructionSelector {
6265
bool selectI64Imm(MachineInstr &I, MachineBasicBlock &MBB,
6366
MachineRegisterInfo &MRI) const;
6467

68+
const PPCTargetMachine &TM;
6569
const PPCSubtarget &STI;
6670
const PPCInstrInfo &TII;
6771
const PPCRegisterInfo &TRI;
@@ -85,7 +89,8 @@ class PPCInstructionSelector : public InstructionSelector {
8589
PPCInstructionSelector::PPCInstructionSelector(const PPCTargetMachine &TM,
8690
const PPCSubtarget &STI,
8791
const PPCRegisterBankInfo &RBI)
88-
: STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), RBI(RBI),
92+
: TM(TM), STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()),
93+
RBI(RBI),
8994
#define GET_GLOBALISEL_PREDICATES_INIT
9095
#include "PPCGenGlobalISel.inc"
9196
#undef GET_GLOBALISEL_PREDICATES_INIT
@@ -636,6 +641,66 @@ bool PPCInstructionSelector::selectI64Imm(MachineInstr &I,
636641
return true;
637642
}
638643

644+
bool PPCInstructionSelector::selectConstantPool(
645+
MachineInstr &I, MachineBasicBlock &MBB, MachineRegisterInfo &MRI) const {
646+
const DebugLoc &DbgLoc = I.getDebugLoc();
647+
MachineFunction *MF = MBB.getParent();
648+
649+
// TODO: handle 32-bit.
650+
// TODO: Enabling floating point constant pool selection on AIX requires
651+
// global isel on big endian target enabled first.
652+
// See CallLowering::enableBigEndian().
653+
if (!STI.isPPC64() || !STI.isLittleEndian())
654+
return false;
655+
656+
MF->getInfo<PPCFunctionInfo>()->setUsesTOCBasePtr();
657+
658+
const Register DstReg = I.getOperand(0).getReg();
659+
unsigned CPI = I.getOperand(1).getIndex();
660+
661+
// Address stored in the TOC entry. This is related to code model and the ABI
662+
// we are currently using. For now we only handle 64-bit Linux LE. PowerPC
663+
// only supports small, medium and large code model.
664+
const CodeModel::Model CModel = TM.getCodeModel();
665+
assert(!(CModel == CodeModel::Tiny || CModel == CodeModel::Kernel) &&
666+
"PowerPC doesn't support tiny or kernel code models.");
667+
668+
const MCRegister TOCReg = STI.getTOCPointerRegister();
669+
MachineMemOperand *MMO = MF->getMachineMemOperand(
670+
MachinePointerInfo::getGOT(*MF), MachineMemOperand::MOLoad,
671+
MRI.getType(DstReg), MF->getDataLayout().getPointerABIAlignment(0));
672+
673+
MachineInstr *MI = nullptr;
674+
// For now we only handle 64-bit Linux.
675+
if (CModel == CodeModel::Small) {
676+
// For small code model, generate LDtocCPT(CPI, X2).
677+
MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::LDtocCPT), DstReg)
678+
.addConstantPoolIndex(CPI)
679+
.addReg(TOCReg)
680+
.addMemOperand(MMO);
681+
} else {
682+
Register HaAddrReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
683+
BuildMI(MBB, I, DbgLoc, TII.get(PPC::ADDIStocHA8), HaAddrReg)
684+
.addReg(TOCReg)
685+
.addConstantPoolIndex(CPI);
686+
687+
if (CModel == CodeModel::Large)
688+
// For large code model, generate LDtocL(CPI, ADDIStocHA8(X2, CPI))
689+
MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::LDtocL), DstReg)
690+
.addConstantPoolIndex(CPI)
691+
.addReg(HaAddrReg)
692+
.addMemOperand(MMO);
693+
else
694+
// For medium code model, generate ADDItocL(CPI, ADDIStocHA8(X2, CPI))
695+
MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::ADDItocL), DstReg)
696+
.addReg(HaAddrReg)
697+
.addConstantPoolIndex(CPI);
698+
}
699+
700+
I.eraseFromParent();
701+
return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
702+
}
703+
639704
bool PPCInstructionSelector::select(MachineInstr &I) {
640705
auto &MBB = *I.getParent();
641706
auto &MF = *MBB.getParent();
@@ -704,6 +769,8 @@ bool PPCInstructionSelector::select(MachineInstr &I) {
704769
return selectZExt(I, MBB, MRI);
705770
case TargetOpcode::G_CONSTANT:
706771
return selectI64Imm(I, MBB, MRI);
772+
case TargetOpcode::G_CONSTANT_POOL:
773+
return selectConstantPool(I, MBB, MRI);
707774
}
708775
return false;
709776
}

llvm/lib/Target/PowerPC/GISel/PPCLegalizerInfo.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,8 @@ PPCLegalizerInfo::PPCLegalizerInfo(const PPCSubtarget &ST) {
5454
getActionDefinitionsBuilder({G_LOAD, G_STORE})
5555
.legalForTypesWithMemDesc({{S64, P0, S64, 8}, {S32, P0, S32, 4}});
5656

57+
getActionDefinitionsBuilder(G_FCONSTANT).lowerFor({S32, S64});
58+
getActionDefinitionsBuilder(G_CONSTANT_POOL).legalFor({P0});
59+
5760
getLegacyLegalizerInfo().computeTables();
5861
}

llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ PPCRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
118118
case TargetOpcode::G_CONSTANT:
119119
OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});
120120
break;
121+
case TargetOpcode::G_CONSTANT_POOL:
122+
OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});
123+
break;
121124
case TargetOpcode::G_FPTOUI:
122125
case TargetOpcode::G_FPTOSI: {
123126
Register SrcReg = MI.getOperand(1).getReg();

llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@
8686
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
8787
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
8888
#
89+
# DEBUG-NEXT: G_CONSTANT_POOL (opcode {{[0-9]+}}): 1 type index, 0 imm indices
90+
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
91+
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
92+
#
8993
# DEBUG-NEXT: G_EXTRACT (opcode {{[0-9]+}}): 2 type indices, 1 imm index
9094
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
9195
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
; RUN: not --crash llc -global-isel -mtriple=powerpc-unknown-linux-gnu \
2+
; RUN: -o - < %s 2>&1 | FileCheck %s --check-prefix=BE
3+
; RUN: not --crash llc -global-isel -mtriple=powerpcle-unknown-linux-gnu \
4+
; RUN: -o - < %s 2>&1 | FileCheck %s --check-prefix=BIT32
5+
6+
; BE: LLVM ERROR: unable to translate in big endian mode
7+
8+
; BIT32: LLVM ERROR: unable to legalize instruction: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD{{.*}}load (s64) from constant-pool
9+
10+
define double @foo() {
11+
entry:
12+
ret double 1.000000e+00
13+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
3+
; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -global-isel -code-model=small \
4+
; RUN: -verify-machineinstrs -o - < %s | FileCheck %s --check-prefix=SMALL
5+
; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -global-isel -code-model=medium \
6+
; RUN: -verify-machineinstrs -o - < %s | FileCheck %s --check-prefix=MEDIUM
7+
; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -global-isel -code-model=large \
8+
; RUN: -verify-machineinstrs -o - < %s | FileCheck %s --check-prefix=LARGE
9+
10+
define float @foo_float() {
11+
; SMALL-LABEL: foo_float:
12+
; SMALL: # %bb.0: # %entry
13+
; SMALL-NEXT: ld 3, .LC0@toc(2)
14+
; SMALL-NEXT: lfs 1, 0(3)
15+
; SMALL-NEXT: blr
16+
;
17+
; MEDIUM-LABEL: foo_float:
18+
; MEDIUM: # %bb.0: # %entry
19+
; MEDIUM-NEXT: addis 3, 2, .LCPI0_0@toc@ha
20+
; MEDIUM-NEXT: addi 3, 3, .LCPI0_0@toc@l
21+
; MEDIUM-NEXT: lfs 1, 0(3)
22+
; MEDIUM-NEXT: blr
23+
;
24+
; LARGE-LABEL: foo_float:
25+
; LARGE: # %bb.0: # %entry
26+
; LARGE-NEXT: addis 3, 2, .LC0@toc@ha
27+
; LARGE-NEXT: ld 3, .LC0@toc@l(3)
28+
; LARGE-NEXT: lfs 1, 0(3)
29+
; LARGE-NEXT: blr
30+
entry:
31+
ret float 1.000000e+00
32+
}
33+
34+
define double @foo_double() {
35+
; SMALL-LABEL: foo_double:
36+
; SMALL: # %bb.0: # %entry
37+
; SMALL-NEXT: ld 3, .LC1@toc(2)
38+
; SMALL-NEXT: lfd 1, 0(3)
39+
; SMALL-NEXT: blr
40+
;
41+
; MEDIUM-LABEL: foo_double:
42+
; MEDIUM: # %bb.0: # %entry
43+
; MEDIUM-NEXT: addis 3, 2, .LCPI1_0@toc@ha
44+
; MEDIUM-NEXT: addi 3, 3, .LCPI1_0@toc@l
45+
; MEDIUM-NEXT: lfd 1, 0(3)
46+
; MEDIUM-NEXT: blr
47+
;
48+
; LARGE-LABEL: foo_double:
49+
; LARGE: # %bb.0: # %entry
50+
; LARGE-NEXT: addis 3, 2, .LC1@toc@ha
51+
; LARGE-NEXT: ld 3, .LC1@toc@l(3)
52+
; LARGE-NEXT: lfd 1, 0(3)
53+
; LARGE-NEXT: blr
54+
entry:
55+
ret double 1.000000e+00
56+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# RUN: not --crash llc -o - -march=arm64 -global-isel -run-pass=none \
2+
# RUN: -verify-machineinstrs %s 2>&1 | FileCheck %s
3+
# REQUIRES: aarch64-registered-target
4+
5+
---
6+
name: test_constant_pool
7+
constants:
8+
- id: 0
9+
value: 'double 3.250000e+00'
10+
stack:
11+
- { id: 0, size: 64, alignment: 8 }
12+
legalized: true
13+
regBankSelected: false
14+
selected: false
15+
tracksRegLiveness: true
16+
liveins:
17+
body: |
18+
bb.0:
19+
20+
; CHECK: Bad machine code: Too few operands
21+
%0:_(p0) = G_CONSTANT_POOL
22+
23+
; CHECK: Bad machine code: Src operand 1 must be a constant pool index
24+
%1:_(p0) = G_CONSTANT_POOL 1
25+
26+
; CHECK: Bad machine code: Src operand 1 must be a constant pool index
27+
%2:_(p0) = G_CONSTANT_POOL i32 1
28+
29+
; CHECK: Bad machine code: Src operand 1 must be a constant pool index
30+
%3:_(p0) = G_CONSTANT_POOL %stack.0
31+
32+
; CHECK: Dst operand 0 must be a pointer
33+
%4:_(s32) = G_CONSTANT_POOL %const.0
34+
35+
; CHECK: Dst operand 0 must be a pointer
36+
%5:_(s64) = G_CONSTANT_POOL %const.0
37+
38+
; CHECK-NOT: %6
39+
%6:_(p0) = G_CONSTANT_POOL %const.0
40+
...

0 commit comments

Comments
 (0)