Skip to content

Commit 27774d9

Browse files
author
Hal Finkel
committedMar 13, 2014
[PowerPC] Initial support for the VSX instruction set
VSX is an ISA extension supported on the POWER7 and later cores that enhances floating-point vector and scalar capabilities. Among other things, this adds <2 x double> support and generally helps to reduce register pressure. The interesting part of this ISA feature is the register configuration: there are 64 new 128-bit vector registers, the 32 of which are super-registers of the existing 32 scalar floating-point registers, and the second 32 of which overlap with the 32 Altivec vector registers. This makes things like vector insertion and extraction tricky: this can be free but only if we force a restriction to the right register subclass when needed. A new "minipass" PPCVSXCopy takes care of this (although it could do a more-optimal job of it; see the comment about unnecessary copies below). Please note that, currently, VSX is not enabled by default when targeting anything because it is not yet ready for that. The assembler and disassembler are fully implemented and tested. However: - CodeGen support causes miscompiles; test-suite runtime failures: MultiSource/Benchmarks/FreeBench/distray/distray MultiSource/Benchmarks/McCat/08-main/main MultiSource/Benchmarks/Olden/voronoi/voronoi MultiSource/Benchmarks/mafft/pairlocalalign MultiSource/Benchmarks/tramp3d-v4/tramp3d-v4 SingleSource/Benchmarks/CoyoteBench/almabench SingleSource/Benchmarks/Misc/matmul_f64_4x4 - The lowering currently falls back to using Altivec instructions far more than it should. Worse, there are some things that are scalarized through the stack that shouldn't be. - A lot of unnecessary copies make it past the optimizers, and this needs to be fixed. - Many more regression tests are needed. Normally, I'd fix these things prior to committing, but there are some students and other contributors who would like to work this, and so it makes sense to move this development process upstream where it can be subject to the regular code-review procedures. llvm-svn: 203768
1 parent 5457bd0 commit 27774d9

22 files changed

+2071
-23
lines changed
 

‎llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,25 @@ static unsigned VRegs[32] = {
9595
PPC::V24, PPC::V25, PPC::V26, PPC::V27,
9696
PPC::V28, PPC::V29, PPC::V30, PPC::V31
9797
};
98+
static unsigned VSRegs[64] = {
99+
PPC::VSL0, PPC::VSL1, PPC::VSL2, PPC::VSL3,
100+
PPC::VSL4, PPC::VSL5, PPC::VSL6, PPC::VSL7,
101+
PPC::VSL8, PPC::VSL9, PPC::VSL10, PPC::VSL11,
102+
PPC::VSL12, PPC::VSL13, PPC::VSL14, PPC::VSL15,
103+
PPC::VSL16, PPC::VSL17, PPC::VSL18, PPC::VSL19,
104+
PPC::VSL20, PPC::VSL21, PPC::VSL22, PPC::VSL23,
105+
PPC::VSL24, PPC::VSL25, PPC::VSL26, PPC::VSL27,
106+
PPC::VSL28, PPC::VSL29, PPC::VSL30, PPC::VSL31,
107+
108+
PPC::VSH0, PPC::VSH1, PPC::VSH2, PPC::VSH3,
109+
PPC::VSH4, PPC::VSH5, PPC::VSH6, PPC::VSH7,
110+
PPC::VSH8, PPC::VSH9, PPC::VSH10, PPC::VSH11,
111+
PPC::VSH12, PPC::VSH13, PPC::VSH14, PPC::VSH15,
112+
PPC::VSH16, PPC::VSH17, PPC::VSH18, PPC::VSH19,
113+
PPC::VSH20, PPC::VSH21, PPC::VSH22, PPC::VSH23,
114+
PPC::VSH24, PPC::VSH25, PPC::VSH26, PPC::VSH27,
115+
PPC::VSH28, PPC::VSH29, PPC::VSH30, PPC::VSH31
116+
};
98117
static unsigned CRBITRegs[32] = {
99118
PPC::CR0LT, PPC::CR0GT, PPC::CR0EQ, PPC::CR0UN,
100119
PPC::CR1LT, PPC::CR1GT, PPC::CR1EQ, PPC::CR1UN,
@@ -345,6 +364,11 @@ struct PPCOperand : public MCParsedAsmOperand {
345364
return (unsigned) Imm.Val;
346365
}
347366

367+
unsigned getVSReg() const {
368+
assert(isVSRegNumber() && "Invalid access!");
369+
return (unsigned) Imm.Val;
370+
}
371+
348372
unsigned getCCReg() const {
349373
assert(isCCRegNumber() && "Invalid access!");
350374
return (unsigned) (Kind == Immediate ? Imm.Val : Expr.CRVal);
@@ -362,6 +386,7 @@ struct PPCOperand : public MCParsedAsmOperand {
362386

363387
bool isToken() const { return Kind == Token; }
364388
bool isImm() const { return Kind == Immediate || Kind == Expression; }
389+
bool isU2Imm() const { return Kind == Immediate && isUInt<2>(getImm()); }
365390
bool isU5Imm() const { return Kind == Immediate && isUInt<5>(getImm()); }
366391
bool isS5Imm() const { return Kind == Immediate && isInt<5>(getImm()); }
367392
bool isU6Imm() const { return Kind == Immediate && isUInt<6>(getImm()); }
@@ -382,6 +407,7 @@ struct PPCOperand : public MCParsedAsmOperand {
382407
(Kind == Immediate && isInt<16>(getImm()) &&
383408
(getImm() & 3) == 0); }
384409
bool isRegNumber() const { return Kind == Immediate && isUInt<5>(getImm()); }
410+
bool isVSRegNumber() const { return Kind == Immediate && isUInt<6>(getImm()); }
385411
bool isCCRegNumber() const { return (Kind == Expression
386412
&& isUInt<3>(getExprCRVal())) ||
387413
(Kind == Immediate
@@ -448,6 +474,11 @@ struct PPCOperand : public MCParsedAsmOperand {
448474
Inst.addOperand(MCOperand::CreateReg(VRegs[getReg()]));
449475
}
450476

477+
void addRegVSRCOperands(MCInst &Inst, unsigned N) const {
478+
assert(N == 1 && "Invalid number of operands!");
479+
Inst.addOperand(MCOperand::CreateReg(VSRegs[getVSReg()]));
480+
}
481+
451482
void addRegCRBITRCOperands(MCInst &Inst, unsigned N) const {
452483
assert(N == 1 && "Invalid number of operands!");
453484
Inst.addOperand(MCOperand::CreateReg(CRBITRegs[getCRBit()]));

‎llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,26 @@ static const unsigned VRegs[] = {
9292
PPC::V28, PPC::V29, PPC::V30, PPC::V31
9393
};
9494

95+
static const unsigned VSRegs[] = {
96+
PPC::VSL0, PPC::VSL1, PPC::VSL2, PPC::VSL3,
97+
PPC::VSL4, PPC::VSL5, PPC::VSL6, PPC::VSL7,
98+
PPC::VSL8, PPC::VSL9, PPC::VSL10, PPC::VSL11,
99+
PPC::VSL12, PPC::VSL13, PPC::VSL14, PPC::VSL15,
100+
PPC::VSL16, PPC::VSL17, PPC::VSL18, PPC::VSL19,
101+
PPC::VSL20, PPC::VSL21, PPC::VSL22, PPC::VSL23,
102+
PPC::VSL24, PPC::VSL25, PPC::VSL26, PPC::VSL27,
103+
PPC::VSL28, PPC::VSL29, PPC::VSL30, PPC::VSL31,
104+
105+
PPC::VSH0, PPC::VSH1, PPC::VSH2, PPC::VSH3,
106+
PPC::VSH4, PPC::VSH5, PPC::VSH6, PPC::VSH7,
107+
PPC::VSH8, PPC::VSH9, PPC::VSH10, PPC::VSH11,
108+
PPC::VSH12, PPC::VSH13, PPC::VSH14, PPC::VSH15,
109+
PPC::VSH16, PPC::VSH17, PPC::VSH18, PPC::VSH19,
110+
PPC::VSH20, PPC::VSH21, PPC::VSH22, PPC::VSH23,
111+
PPC::VSH24, PPC::VSH25, PPC::VSH26, PPC::VSH27,
112+
PPC::VSH28, PPC::VSH29, PPC::VSH30, PPC::VSH31
113+
};
114+
95115
static const unsigned GPRegs[] = {
96116
PPC::R0, PPC::R1, PPC::R2, PPC::R3,
97117
PPC::R4, PPC::R5, PPC::R6, PPC::R7,
@@ -163,6 +183,12 @@ static DecodeStatus DecodeVRRCRegisterClass(MCInst &Inst, uint64_t RegNo,
163183
return decodeRegisterClass(Inst, RegNo, VRegs);
164184
}
165185

186+
static DecodeStatus DecodeVSRCRegisterClass(MCInst &Inst, uint64_t RegNo,
187+
uint64_t Address,
188+
const void *Decoder) {
189+
return decodeRegisterClass(Inst, RegNo, VSRegs);
190+
}
191+
166192
static DecodeStatus DecodeGPRCRegisterClass(MCInst &Inst, uint64_t RegNo,
167193
uint64_t Address,
168194
const void *Decoder) {

‎llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,13 @@ void PPCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNo,
199199
printOperand(MI, OpNo+1, O);
200200
}
201201

202+
void PPCInstPrinter::printU2ImmOperand(const MCInst *MI, unsigned OpNo,
203+
raw_ostream &O) {
204+
unsigned int Value = MI->getOperand(OpNo).getImm();
205+
assert(Value <= 3 && "Invalid u2imm argument!");
206+
O << (unsigned int)Value;
207+
}
208+
202209
void PPCInstPrinter::printS5ImmOperand(const MCInst *MI, unsigned OpNo,
203210
raw_ostream &O) {
204211
int Value = MI->getOperand(OpNo).getImm();
@@ -316,7 +323,10 @@ static const char *stripRegisterPrefix(const char *RegName) {
316323
switch (RegName[0]) {
317324
case 'r':
318325
case 'f':
319-
case 'v': return RegName + 1;
326+
case 'v':
327+
if (RegName[1] == 's')
328+
return RegName + 2;
329+
return RegName + 1;
320330
case 'c': if (RegName[1] == 'r') return RegName + 2;
321331
}
322332

‎llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class PPCInstPrinter : public MCInstPrinter {
4343
void printPredicateOperand(const MCInst *MI, unsigned OpNo,
4444
raw_ostream &O, const char *Modifier = 0);
4545

46-
46+
void printU2ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
4747
void printS5ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
4848
void printU5ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
4949
void printU6ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);

‎llvm/lib/Target/PowerPC/PPC.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ namespace llvm {
3535
FunctionPass *createPPCCTRLoopsVerify();
3636
#endif
3737
FunctionPass *createPPCEarlyReturnPass();
38+
FunctionPass *createPPCVSXCopyPass();
3839
FunctionPass *createPPCBranchSelectionPass();
3940
FunctionPass *createPPCISelDag(PPCTargetMachine &TM);
4041
FunctionPass *createPPCJITCodeEmitterPass(PPCTargetMachine &TM,

‎llvm/lib/Target/PowerPC/PPC.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ def FeatureBookE : SubtargetFeature<"booke", "IsBookE", "true",
9090
def FeatureQPX : SubtargetFeature<"qpx","HasQPX", "true",
9191
"Enable QPX instructions">;
9292
def FeatureVSX : SubtargetFeature<"vsx","HasVSX", "true",
93-
"Enable VSX instructions">;
93+
"Enable VSX instructions",
94+
[FeatureAltivec]>;
9495

9596
def DeprecatedMFTB : SubtargetFeature<"", "DeprecatedMFTB", "true",
9697
"Treat mftb as deprecated">;

‎llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,10 @@ static const char *stripRegisterPrefix(const char *RegName) {
129129
switch (RegName[0]) {
130130
case 'r':
131131
case 'f':
132-
case 'v': return RegName + 1;
132+
case 'v':
133+
if (RegName[1] == 's')
134+
return RegName + 2;
135+
return RegName + 1;
133136
case 'c': if (RegName[1] == 'r') return RegName + 2;
134137
}
135138

‎llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ SDValue PPCDAGToDAGISel::SelectCC(SDValue LHS, SDValue RHS,
572572
Opc = PPC::FCMPUS;
573573
} else {
574574
assert(LHS.getValueType() == MVT::f64 && "Unknown vt!");
575-
Opc = PPC::FCMPUD;
575+
Opc = PPCSubTarget.hasVSX() ? PPC::XSCMPUDP : PPC::FCMPUD;
576576
}
577577
return SDValue(CurDAG->getMachineNode(Opc, dl, MVT::i32, LHS, RHS), 0);
578578
}
@@ -640,7 +640,8 @@ static unsigned getCRIdxForSetCC(ISD::CondCode CC, bool &Invert) {
640640
// getVCmpInst: return the vector compare instruction for the specified
641641
// vector type and condition code. Since this is for altivec specific code,
642642
// only support the altivec types (v16i8, v8i16, v4i32, and v4f32).
643-
static unsigned int getVCmpInst(MVT::SimpleValueType VecVT, ISD::CondCode CC) {
643+
static unsigned int getVCmpInst(MVT::SimpleValueType VecVT, ISD::CondCode CC,
644+
bool HasVSX) {
644645
switch (CC) {
645646
case ISD::SETEQ:
646647
case ISD::SETUEQ:
@@ -654,7 +655,9 @@ static unsigned int getVCmpInst(MVT::SimpleValueType VecVT, ISD::CondCode CC) {
654655
return PPC::VCMPEQUW;
655656
// v4f32 != v4f32 could be translate to unordered not equal
656657
else if (VecVT == MVT::v4f32)
657-
return PPC::VCMPEQFP;
658+
return HasVSX ? PPC::XVCMPEQSP : PPC::VCMPEQFP;
659+
else if (VecVT == MVT::v2f64)
660+
return PPC::XVCMPEQDP;
658661
break;
659662
case ISD::SETLT:
660663
case ISD::SETGT:
@@ -667,7 +670,9 @@ static unsigned int getVCmpInst(MVT::SimpleValueType VecVT, ISD::CondCode CC) {
667670
else if (VecVT == MVT::v4i32)
668671
return PPC::VCMPGTSW;
669672
else if (VecVT == MVT::v4f32)
670-
return PPC::VCMPGTFP;
673+
return HasVSX ? PPC::XVCMPGTSP : PPC::VCMPGTFP;
674+
else if (VecVT == MVT::v2f64)
675+
return PPC::XVCMPGTDP;
671676
break;
672677
case ISD::SETULT:
673678
case ISD::SETUGT:
@@ -682,17 +687,23 @@ static unsigned int getVCmpInst(MVT::SimpleValueType VecVT, ISD::CondCode CC) {
682687
break;
683688
case ISD::SETOEQ:
684689
if (VecVT == MVT::v4f32)
685-
return PPC::VCMPEQFP;
690+
return HasVSX ? PPC::XVCMPEQSP : PPC::VCMPEQFP;
691+
else if (VecVT == MVT::v2f64)
692+
return PPC::XVCMPEQDP;
686693
break;
687694
case ISD::SETOLT:
688695
case ISD::SETOGT:
689696
case ISD::SETOLE:
690697
if (VecVT == MVT::v4f32)
691-
return PPC::VCMPGTFP;
698+
return HasVSX ? PPC::XVCMPGTSP : PPC::VCMPGTFP;
699+
else if (VecVT == MVT::v2f64)
700+
return PPC::XVCMPGTDP;
692701
break;
693702
case ISD::SETOGE:
694703
if (VecVT == MVT::v4f32)
695-
return PPC::VCMPGEFP;
704+
return HasVSX ? PPC::XVCMPGESP : PPC::VCMPGEFP;
705+
else if (VecVT == MVT::v2f64)
706+
return PPC::XVCMPGEDP;
696707
break;
697708
default:
698709
break;
@@ -703,7 +714,7 @@ static unsigned int getVCmpInst(MVT::SimpleValueType VecVT, ISD::CondCode CC) {
703714
// getVCmpEQInst: return the equal compare instruction for the specified vector
704715
// type. Since this is for altivec specific code, only support the altivec
705716
// types (v16i8, v8i16, v4i32, and v4f32).
706-
static unsigned int getVCmpEQInst(MVT::SimpleValueType VecVT) {
717+
static unsigned int getVCmpEQInst(MVT::SimpleValueType VecVT, bool HasVSX) {
707718
switch (VecVT) {
708719
case MVT::v16i8:
709720
return PPC::VCMPEQUB;
@@ -712,13 +723,14 @@ static unsigned int getVCmpEQInst(MVT::SimpleValueType VecVT) {
712723
case MVT::v4i32:
713724
return PPC::VCMPEQUW;
714725
case MVT::v4f32:
715-
return PPC::VCMPEQFP;
726+
return HasVSX ? PPC::XVCMPEQSP : PPC::VCMPEQFP;
727+
case MVT::v2f64:
728+
return PPC::XVCMPEQDP;
716729
default:
717730
llvm_unreachable("Invalid integer vector compare condition");
718731
}
719732
}
720733

721-
722734
SDNode *PPCDAGToDAGISel::SelectSETCC(SDNode *N) {
723735
SDLoc dl(N);
724736
unsigned Imm;
@@ -808,7 +820,7 @@ SDNode *PPCDAGToDAGISel::SelectSETCC(SDNode *N) {
808820
if (LHS.getValueType().isVector()) {
809821
EVT VecVT = LHS.getValueType();
810822
MVT::SimpleValueType VT = VecVT.getSimpleVT().SimpleTy;
811-
unsigned int VCmpInst = getVCmpInst(VT, CC);
823+
unsigned int VCmpInst = getVCmpInst(VT, CC, PPCSubTarget.hasVSX());
812824

813825
switch (CC) {
814826
case ISD::SETEQ:
@@ -839,7 +851,7 @@ SDNode *PPCDAGToDAGISel::SelectSETCC(SDNode *N) {
839851
return CurDAG->SelectNodeTo(N, VCmpInst, VecVT, LHS, RHS);
840852
} else {
841853
SDValue VCmpGT(CurDAG->getMachineNode(VCmpInst, dl, VecVT, LHS, RHS), 0);
842-
unsigned int VCmpEQInst = getVCmpEQInst(VT);
854+
unsigned int VCmpEQInst = getVCmpEQInst(VT, PPCSubTarget.hasVSX());
843855
SDValue VCmpEQ(CurDAG->getMachineNode(VCmpEQInst, dl, VecVT, LHS, RHS), 0);
844856
return CurDAG->SelectNodeTo(N, PPC::VOR, VecVT, VCmpGT, VCmpEQ);
845857
}
@@ -848,7 +860,7 @@ SDNode *PPCDAGToDAGISel::SelectSETCC(SDNode *N) {
848860
case ISD::SETOLE:
849861
case ISD::SETULE: {
850862
SDValue VCmpLE(CurDAG->getMachineNode(VCmpInst, dl, VecVT, RHS, LHS), 0);
851-
unsigned int VCmpEQInst = getVCmpEQInst(VT);
863+
unsigned int VCmpEQInst = getVCmpEQInst(VT, PPCSubTarget.hasVSX());
852864
SDValue VCmpEQ(CurDAG->getMachineNode(VCmpEQInst, dl, VecVT, LHS, RHS), 0);
853865
return CurDAG->SelectNodeTo(N, PPC::VOR, VecVT, VCmpLE, VCmpEQ);
854866
}

0 commit comments

Comments
 (0)
Please sign in to comment.