Skip to content

Commit c8ec685

Browse files
author
Jinsong Ji
committed
[llvm-exegesis][PowerPC] Add more register classes
This PR adds more register class support in PowerPC, mark OperandType for imm and memory operands. Also added more unit tests for SnippetGenerator. Reviewed By: #powerpc, steven.zhang Differential Revision: https://reviews.llvm.org/D88044
1 parent 2c66b6e commit c8ec685

File tree

6 files changed

+276
-1
lines changed

6 files changed

+276
-1
lines changed

llvm/lib/Target/PowerPC/PPCInstr64Bit.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ def s16imm64 : Operand<i64> {
1919
let EncoderMethod = "getImm16Encoding";
2020
let ParserMatchClass = PPCS16ImmAsmOperand;
2121
let DecoderMethod = "decodeSImmOperand<16>";
22+
let OperandType = "OPERAND_IMMEDIATE";
2223
}
2324
def u16imm64 : Operand<i64> {
2425
let PrintMethod = "printU16ImmOperand";
2526
let EncoderMethod = "getImm16Encoding";
2627
let ParserMatchClass = PPCU16ImmAsmOperand;
2728
let DecoderMethod = "decodeUImmOperand<16>";
29+
let OperandType = "OPERAND_IMMEDIATE";
2830
}
2931
def s17imm64 : Operand<i64> {
3032
// This operand type is used for addis/lis to allow the assembler parser
@@ -34,6 +36,7 @@ def s17imm64 : Operand<i64> {
3436
let EncoderMethod = "getImm16Encoding";
3537
let ParserMatchClass = PPCS17ImmAsmOperand;
3638
let DecoderMethod = "decodeSImmOperand<16>";
39+
let OperandType = "OPERAND_IMMEDIATE";
3740
}
3841
def tocentry : Operand<iPTR> {
3942
let MIOperandInfo = (ops i64imm:$imm);

llvm/lib/Target/PowerPC/PPCInstrInfo.td

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,7 @@ def PPCU1ImmAsmOperand : AsmOperandClass {
666666
def u1imm : Operand<i32> {
667667
let PrintMethod = "printU1ImmOperand";
668668
let ParserMatchClass = PPCU1ImmAsmOperand;
669+
let OperandType = "OPERAND_IMMEDIATE";
669670
}
670671

671672
def PPCU2ImmAsmOperand : AsmOperandClass {
@@ -675,6 +676,7 @@ def PPCU2ImmAsmOperand : AsmOperandClass {
675676
def u2imm : Operand<i32> {
676677
let PrintMethod = "printU2ImmOperand";
677678
let ParserMatchClass = PPCU2ImmAsmOperand;
679+
let OperandType = "OPERAND_IMMEDIATE";
678680
}
679681

680682
def PPCATBitsAsHintAsmOperand : AsmOperandClass {
@@ -684,6 +686,7 @@ def PPCATBitsAsHintAsmOperand : AsmOperandClass {
684686
def atimm : Operand<i32> {
685687
let PrintMethod = "printATBitsAsHint";
686688
let ParserMatchClass = PPCATBitsAsHintAsmOperand;
689+
let OperandType = "OPERAND_IMMEDIATE";
687690
}
688691

689692
def PPCU3ImmAsmOperand : AsmOperandClass {
@@ -693,6 +696,7 @@ def PPCU3ImmAsmOperand : AsmOperandClass {
693696
def u3imm : Operand<i32> {
694697
let PrintMethod = "printU3ImmOperand";
695698
let ParserMatchClass = PPCU3ImmAsmOperand;
699+
let OperandType = "OPERAND_IMMEDIATE";
696700
}
697701

698702
def PPCU4ImmAsmOperand : AsmOperandClass {
@@ -702,6 +706,7 @@ def PPCU4ImmAsmOperand : AsmOperandClass {
702706
def u4imm : Operand<i32> {
703707
let PrintMethod = "printU4ImmOperand";
704708
let ParserMatchClass = PPCU4ImmAsmOperand;
709+
let OperandType = "OPERAND_IMMEDIATE";
705710
}
706711
def PPCS5ImmAsmOperand : AsmOperandClass {
707712
let Name = "S5Imm"; let PredicateMethod = "isS5Imm";
@@ -711,6 +716,7 @@ def s5imm : Operand<i32> {
711716
let PrintMethod = "printS5ImmOperand";
712717
let ParserMatchClass = PPCS5ImmAsmOperand;
713718
let DecoderMethod = "decodeSImmOperand<5>";
719+
let OperandType = "OPERAND_IMMEDIATE";
714720
}
715721
def PPCU5ImmAsmOperand : AsmOperandClass {
716722
let Name = "U5Imm"; let PredicateMethod = "isU5Imm";
@@ -720,6 +726,7 @@ def u5imm : Operand<i32> {
720726
let PrintMethod = "printU5ImmOperand";
721727
let ParserMatchClass = PPCU5ImmAsmOperand;
722728
let DecoderMethod = "decodeUImmOperand<5>";
729+
let OperandType = "OPERAND_IMMEDIATE";
723730
}
724731
def PPCU6ImmAsmOperand : AsmOperandClass {
725732
let Name = "U6Imm"; let PredicateMethod = "isU6Imm";
@@ -729,6 +736,7 @@ def u6imm : Operand<i32> {
729736
let PrintMethod = "printU6ImmOperand";
730737
let ParserMatchClass = PPCU6ImmAsmOperand;
731738
let DecoderMethod = "decodeUImmOperand<6>";
739+
let OperandType = "OPERAND_IMMEDIATE";
732740
}
733741
def PPCU7ImmAsmOperand : AsmOperandClass {
734742
let Name = "U7Imm"; let PredicateMethod = "isU7Imm";
@@ -738,6 +746,7 @@ def u7imm : Operand<i32> {
738746
let PrintMethod = "printU7ImmOperand";
739747
let ParserMatchClass = PPCU7ImmAsmOperand;
740748
let DecoderMethod = "decodeUImmOperand<7>";
749+
let OperandType = "OPERAND_IMMEDIATE";
741750
}
742751
def PPCU8ImmAsmOperand : AsmOperandClass {
743752
let Name = "U8Imm"; let PredicateMethod = "isU8Imm";
@@ -747,6 +756,7 @@ def u8imm : Operand<i32> {
747756
let PrintMethod = "printU8ImmOperand";
748757
let ParserMatchClass = PPCU8ImmAsmOperand;
749758
let DecoderMethod = "decodeUImmOperand<8>";
759+
let OperandType = "OPERAND_IMMEDIATE";
750760
}
751761
def PPCU10ImmAsmOperand : AsmOperandClass {
752762
let Name = "U10Imm"; let PredicateMethod = "isU10Imm";
@@ -756,6 +766,7 @@ def u10imm : Operand<i32> {
756766
let PrintMethod = "printU10ImmOperand";
757767
let ParserMatchClass = PPCU10ImmAsmOperand;
758768
let DecoderMethod = "decodeUImmOperand<10>";
769+
let OperandType = "OPERAND_IMMEDIATE";
759770
}
760771
def PPCU12ImmAsmOperand : AsmOperandClass {
761772
let Name = "U12Imm"; let PredicateMethod = "isU12Imm";
@@ -765,6 +776,7 @@ def u12imm : Operand<i32> {
765776
let PrintMethod = "printU12ImmOperand";
766777
let ParserMatchClass = PPCU12ImmAsmOperand;
767778
let DecoderMethod = "decodeUImmOperand<12>";
779+
let OperandType = "OPERAND_IMMEDIATE";
768780
}
769781
def PPCS16ImmAsmOperand : AsmOperandClass {
770782
let Name = "S16Imm"; let PredicateMethod = "isS16Imm";
@@ -775,6 +787,7 @@ def s16imm : Operand<i32> {
775787
let EncoderMethod = "getImm16Encoding";
776788
let ParserMatchClass = PPCS16ImmAsmOperand;
777789
let DecoderMethod = "decodeSImmOperand<16>";
790+
let OperandType = "OPERAND_IMMEDIATE";
778791
}
779792
def PPCU16ImmAsmOperand : AsmOperandClass {
780793
let Name = "U16Imm"; let PredicateMethod = "isU16Imm";
@@ -785,6 +798,7 @@ def u16imm : Operand<i32> {
785798
let EncoderMethod = "getImm16Encoding";
786799
let ParserMatchClass = PPCU16ImmAsmOperand;
787800
let DecoderMethod = "decodeUImmOperand<16>";
801+
let OperandType = "OPERAND_IMMEDIATE";
788802
}
789803
def PPCS17ImmAsmOperand : AsmOperandClass {
790804
let Name = "S17Imm"; let PredicateMethod = "isS17Imm";
@@ -798,6 +812,7 @@ def s17imm : Operand<i32> {
798812
let EncoderMethod = "getImm16Encoding";
799813
let ParserMatchClass = PPCS17ImmAsmOperand;
800814
let DecoderMethod = "decodeSImmOperand<16>";
815+
let OperandType = "OPERAND_IMMEDIATE";
801816
}
802817
def PPCS34ImmAsmOperand : AsmOperandClass {
803818
let Name = "S34Imm";
@@ -809,12 +824,14 @@ def s34imm : Operand<i64> {
809824
let EncoderMethod = "getImm34EncodingNoPCRel";
810825
let ParserMatchClass = PPCS34ImmAsmOperand;
811826
let DecoderMethod = "decodeSImmOperand<34>";
827+
let OperandType = "OPERAND_IMMEDIATE";
812828
}
813829
def s34imm_pcrel : Operand<i64> {
814830
let PrintMethod = "printS34ImmOperand";
815831
let EncoderMethod = "getImm34EncodingPCRel";
816832
let ParserMatchClass = PPCS34ImmAsmOperand;
817833
let DecoderMethod = "decodeSImmOperand<34>";
834+
let OperandType = "OPERAND_IMMEDIATE";
818835
}
819836
def PPCImmZeroAsmOperand : AsmOperandClass {
820837
let Name = "ImmZero";
@@ -825,6 +842,7 @@ def immZero : Operand<i32> {
825842
let PrintMethod = "printImmZeroOperand";
826843
let ParserMatchClass = PPCImmZeroAsmOperand;
827844
let DecoderMethod = "decodeImmZeroOperand";
845+
let OperandType = "OPERAND_IMMEDIATE";
828846
}
829847

830848
def fpimm0 : PatLeaf<(fpimm), [{ return N->isExactlyValue(+0.0); }]>;
@@ -970,47 +988,55 @@ def memri : Operand<iPTR> {
970988
let MIOperandInfo = (ops dispRI:$imm, ptr_rc_nor0:$reg);
971989
let EncoderMethod = "getMemRIEncoding";
972990
let DecoderMethod = "decodeMemRIOperands";
991+
let OperandType = "OPERAND_MEMORY";
973992
}
974993
def memrr : Operand<iPTR> {
975994
let PrintMethod = "printMemRegReg";
976995
let MIOperandInfo = (ops ptr_rc_nor0:$ptrreg, ptr_rc_idx:$offreg);
996+
let OperandType = "OPERAND_MEMORY";
977997
}
978998
def memrix : Operand<iPTR> { // memri where the imm is 4-aligned.
979999
let PrintMethod = "printMemRegImm";
9801000
let MIOperandInfo = (ops dispRIX:$imm, ptr_rc_nor0:$reg);
9811001
let EncoderMethod = "getMemRIXEncoding";
9821002
let DecoderMethod = "decodeMemRIXOperands";
1003+
let OperandType = "OPERAND_MEMORY";
9831004
}
9841005
def memrix16 : Operand<iPTR> { // memri, imm is 16-aligned, 12-bit, Inst{16:27}
9851006
let PrintMethod = "printMemRegImm";
9861007
let MIOperandInfo = (ops dispRIX16:$imm, ptr_rc_nor0:$reg);
9871008
let EncoderMethod = "getMemRIX16Encoding";
9881009
let DecoderMethod = "decodeMemRIX16Operands";
1010+
let OperandType = "OPERAND_MEMORY";
9891011
}
9901012
def spe8dis : Operand<iPTR> { // SPE displacement where the imm is 8-aligned.
9911013
let PrintMethod = "printMemRegImm";
9921014
let MIOperandInfo = (ops dispSPE8:$imm, ptr_rc_nor0:$reg);
9931015
let EncoderMethod = "getSPE8DisEncoding";
9941016
let DecoderMethod = "decodeSPE8Operands";
1017+
let OperandType = "OPERAND_MEMORY";
9951018
}
9961019
def spe4dis : Operand<iPTR> { // SPE displacement where the imm is 4-aligned.
9971020
let PrintMethod = "printMemRegImm";
9981021
let MIOperandInfo = (ops dispSPE4:$imm, ptr_rc_nor0:$reg);
9991022
let EncoderMethod = "getSPE4DisEncoding";
10001023
let DecoderMethod = "decodeSPE4Operands";
1024+
let OperandType = "OPERAND_MEMORY";
10011025
}
10021026
def spe2dis : Operand<iPTR> { // SPE displacement where the imm is 2-aligned.
10031027
let PrintMethod = "printMemRegImm";
10041028
let MIOperandInfo = (ops dispSPE2:$imm, ptr_rc_nor0:$reg);
10051029
let EncoderMethod = "getSPE2DisEncoding";
10061030
let DecoderMethod = "decodeSPE2Operands";
1031+
let OperandType = "OPERAND_MEMORY";
10071032
}
10081033

10091034
// A single-register address. This is used with the SjLj
10101035
// pseudo-instructions which translates to LD/LWZ. These instructions requires
10111036
// G8RC_NOX0 registers.
10121037
def memr : Operand<iPTR> {
10131038
let MIOperandInfo = (ops ptr_rc_nor0:$ptrreg);
1039+
let OperandType = "OPERAND_MEMORY";
10141040
}
10151041
def PPCTLSRegOperand : AsmOperandClass {
10161042
let Name = "TLSReg"; let PredicateMethod = "isTLSReg";

llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@
1313
namespace llvm {
1414
namespace exegesis {
1515

16+
// Helper to fill a memory operand with a value.
17+
static void setMemOp(InstructionTemplate &IT, int OpIdx,
18+
const MCOperand &OpVal) {
19+
const auto Op = IT.getInstr().Operands[OpIdx];
20+
assert(Op.isExplicit() && "invalid memory pattern");
21+
IT.getValueFor(Op) = OpVal;
22+
}
23+
1624
#include "PPCGenExegesis.inc"
1725

1826
namespace {
@@ -26,6 +34,9 @@ class ExegesisPowerPCTarget : public ExegesisTarget {
2634
bool matchesArch(Triple::ArchType Arch) const override {
2735
return Arch == Triple::ppc64le;
2836
}
37+
unsigned getScratchMemoryRegister(const Triple &) const override;
38+
void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg,
39+
unsigned Offset) const override;
2940
};
3041
} // end anonymous namespace
3142

@@ -44,19 +55,75 @@ static MCInst loadImmediate(unsigned Reg, unsigned RegBitWidth,
4455
const APInt &Value) {
4556
if (Value.getBitWidth() > RegBitWidth)
4657
llvm_unreachable("Value must fit in the Register");
58+
// We don't really care the value in reg, ignore the 16 bit
59+
// restriction for now.
60+
// TODO: make sure we get the exact value in reg if needed.
4761
return MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
4862
.addReg(Reg)
4963
.addImm(Value.getZExtValue());
5064
}
5165

66+
unsigned
67+
ExegesisPowerPCTarget::getScratchMemoryRegister(const Triple &TT) const {
68+
// R13 is reserved as Thread Pointer, we won't use threading in benchmark, so
69+
// use it as scratch memory register
70+
return TT.isArch64Bit() ? PPC::X13 : PPC::R13;
71+
}
72+
73+
void ExegesisPowerPCTarget::fillMemoryOperands(InstructionTemplate &IT,
74+
unsigned Reg,
75+
unsigned Offset) const {
76+
int MemOpIdx = 0;
77+
if (IT.getInstr().hasTiedRegisters())
78+
MemOpIdx = 1;
79+
int DispOpIdx = MemOpIdx + 1;
80+
const auto DispOp = IT.getInstr().Operands[DispOpIdx];
81+
if (DispOp.isReg())
82+
// We don't really care about the real address in snippets,
83+
// So hardcode X1 for X-form Memory Operations for simplicity.
84+
// TODO: materialize the offset into a reggister
85+
setMemOp(IT, DispOpIdx, MCOperand::createReg(PPC::X1));
86+
else
87+
setMemOp(IT, DispOpIdx, MCOperand::createImm(Offset)); // Disp
88+
setMemOp(IT, MemOpIdx + 2, MCOperand::createReg(Reg)); // BaseReg
89+
}
90+
5291
std::vector<MCInst> ExegesisPowerPCTarget::setRegTo(const MCSubtargetInfo &STI,
5392
unsigned Reg,
5493
const APInt &Value) const {
94+
// X11 is optional use in function linkage, should be the least used one
95+
// Use it as scratch reg to load immediate.
96+
unsigned ScratchImmReg = PPC::X11;
97+
5598
if (PPC::GPRCRegClass.contains(Reg))
5699
return {loadImmediate(Reg, 32, Value)};
57100
if (PPC::G8RCRegClass.contains(Reg))
58101
return {loadImmediate(Reg, 64, Value)};
59-
errs() << "setRegTo is not implemented, results will be unreliable\n";
102+
if (PPC::F4RCRegClass.contains(Reg))
103+
return {loadImmediate(ScratchImmReg, 64, Value),
104+
MCInstBuilder(PPC::MTVSRD).addReg(Reg).addReg(ScratchImmReg)};
105+
// We don't care the real value in reg, so set 64 bits or duplicate 64 bits
106+
// for simplicity.
107+
// TODO: update these if we need a accurate 128 values in registers.
108+
if (PPC::VRRCRegClass.contains(Reg))
109+
return {loadImmediate(ScratchImmReg, 64, Value),
110+
MCInstBuilder(PPC::MTVRD).addReg(Reg).addReg(ScratchImmReg)};
111+
if (PPC::VSRCRegClass.contains(Reg))
112+
return {loadImmediate(ScratchImmReg, 64, Value),
113+
MCInstBuilder(PPC::MTVSRDD)
114+
.addReg(Reg)
115+
.addReg(ScratchImmReg)
116+
.addReg(ScratchImmReg)};
117+
if (PPC::VFRCRegClass.contains(Reg))
118+
return {loadImmediate(ScratchImmReg, 64, Value),
119+
MCInstBuilder(PPC::MTVSRD).addReg(Reg).addReg(ScratchImmReg)};
120+
// SPE not supported yet
121+
if (PPC::SPERCRegClass.contains(Reg)) {
122+
errs() << "Unsupported SPE Reg:" << Reg << "\n";
123+
return {};
124+
}
125+
errs() << "setRegTo is not implemented, results will be unreliable:" << Reg
126+
<< "\n";
60127
return {};
61128
}
62129

llvm/unittests/tools/llvm-exegesis/PowerPC/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ set(LLVM_LINK_COMPONENTS
1515

1616
add_llvm_target_unittest(LLVMExegesisPowerPCTests
1717
AnalysisTest.cpp
18+
SnippetGeneratorTest.cpp
1819
TargetTest.cpp
1920
)
2021
target_link_libraries(LLVMExegesisPowerPCTests PRIVATE

0 commit comments

Comments
 (0)