mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-22 10:29:35 +00:00
Codegen vector predicate compares.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27151 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ffea91e522
commit
6d92caddc4
@ -1060,6 +1060,20 @@ void PPCDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) {
|
||||
getI32Imm(0)), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
case PPCISD::MFCR: {
|
||||
SDOperand InFlag;
|
||||
Select(InFlag, N->getOperand(1));
|
||||
// Use MFOCRF if supported.
|
||||
if (TLI.getTargetMachine().getSubtarget<PPCSubtarget>().isGigaProcessor())
|
||||
Result = SDOperand(CurDAG->getTargetNode(PPC::MFOCRF, MVT::i32,
|
||||
N->getOperand(0), InFlag), 0);
|
||||
else
|
||||
Result = SDOperand(CurDAG->getTargetNode(PPC::MFCR, MVT::i32, InFlag), 0);
|
||||
CodeGenMap[Op] = Result;
|
||||
return;
|
||||
}
|
||||
|
||||
case ISD::SDIV: {
|
||||
// FIXME: since this depends on the setting of the carry flag from the srawi
|
||||
// we should really be making notes about that for the scheduler.
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "llvm/CodeGen/SSARegMap.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/Intrinsics.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
using namespace llvm;
|
||||
@ -136,6 +137,9 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM)
|
||||
setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
|
||||
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
|
||||
|
||||
// We want to custom lower some of our intrinsics.
|
||||
setOperationAction(ISD::INTRINSIC , MVT::Other, Custom);
|
||||
|
||||
if (TM.getSubtarget<PPCSubtarget>().is64Bit()) {
|
||||
// They also have instructions for converting between i64 and fp.
|
||||
setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
|
||||
@ -230,6 +234,8 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case PPCISD::STD_32: return "PPCISD::STD_32";
|
||||
case PPCISD::CALL: return "PPCISD::CALL";
|
||||
case PPCISD::RET_FLAG: return "PPCISD::RET_FLAG";
|
||||
case PPCISD::MFCR: return "PPCISD::MFCR";
|
||||
case PPCISD::VCMPo: return "PPCISD::VCMPo";
|
||||
}
|
||||
}
|
||||
|
||||
@ -746,6 +752,80 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
SDOperand VPermMask =DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8, ResultMask);
|
||||
return DAG.getNode(PPCISD::VPERM, V1.getValueType(), V1, V2, VPermMask);
|
||||
}
|
||||
case ISD::INTRINSIC: {
|
||||
bool HasChain = Op.getOperand(0).getValueType() == MVT::Other;
|
||||
unsigned IntNo=cast<ConstantSDNode>(Op.getOperand(HasChain))->getValue();
|
||||
|
||||
// If this is a lowered altivec predicate compare, CompareOpc is set to the
|
||||
// opcode number of the comparison.
|
||||
int CompareOpc = -1;
|
||||
switch (IntNo) {
|
||||
default: return SDOperand(); // Don't custom lower most intrinsics.
|
||||
case Intrinsic::ppc_altivec_vcmpbfp_p: CompareOpc = 966; break;
|
||||
case Intrinsic::ppc_altivec_vcmpeqfp_p: CompareOpc = 198; break;
|
||||
case Intrinsic::ppc_altivec_vcmpequb_p: CompareOpc = 6; break;
|
||||
case Intrinsic::ppc_altivec_vcmpequh_p: CompareOpc = 70; break;
|
||||
case Intrinsic::ppc_altivec_vcmpequw_p: CompareOpc = 134; break;
|
||||
case Intrinsic::ppc_altivec_vcmpgefp_p: CompareOpc = 454; break;
|
||||
case Intrinsic::ppc_altivec_vcmpgtfp_p: CompareOpc = 710; break;
|
||||
case Intrinsic::ppc_altivec_vcmpgtsb_p: CompareOpc = 774; break;
|
||||
case Intrinsic::ppc_altivec_vcmpgtsh_p: CompareOpc = 838; break;
|
||||
case Intrinsic::ppc_altivec_vcmpgtsw_p: CompareOpc = 902; break;
|
||||
case Intrinsic::ppc_altivec_vcmpgtub_p: CompareOpc = 518; break;
|
||||
case Intrinsic::ppc_altivec_vcmpgtuh_p: CompareOpc = 582; break;
|
||||
case Intrinsic::ppc_altivec_vcmpgtuw_p: CompareOpc = 646; break;
|
||||
}
|
||||
|
||||
assert(CompareOpc>0 && "We only lower altivec predicate compares so far!");
|
||||
|
||||
// Create the PPCISD altivec 'dot' comparison node.
|
||||
std::vector<SDOperand> Ops;
|
||||
std::vector<MVT::ValueType> VTs;
|
||||
Ops.push_back(Op.getOperand(2)); // LHS
|
||||
Ops.push_back(Op.getOperand(3)); // RHS
|
||||
Ops.push_back(DAG.getConstant(CompareOpc, MVT::i32));
|
||||
VTs.push_back(Op.getOperand(2).getValueType());
|
||||
VTs.push_back(MVT::Flag);
|
||||
SDOperand CompNode = DAG.getNode(PPCISD::VCMPo, VTs, Ops);
|
||||
|
||||
// Now that we have the comparison, emit a copy from the CR to a GPR.
|
||||
// This is flagged to the above dot comparison.
|
||||
SDOperand Flags = DAG.getNode(PPCISD::MFCR, MVT::i32,
|
||||
DAG.getRegister(PPC::CR6, MVT::i32),
|
||||
CompNode.getValue(1));
|
||||
|
||||
// Unpack the result based on how the target uses it.
|
||||
unsigned BitNo; // Bit # of CR6.
|
||||
bool InvertBit; // Invert result?
|
||||
switch (cast<ConstantSDNode>(Op.getOperand(1))->getValue()) {
|
||||
default: // Can't happen, don't crash on invalid number though.
|
||||
case 0: // Return the value of the EQ bit of CR6.
|
||||
BitNo = 0; InvertBit = false;
|
||||
break;
|
||||
case 1: // Return the inverted value of the EQ bit of CR6.
|
||||
BitNo = 0; InvertBit = true;
|
||||
break;
|
||||
case 2: // Return the value of the LT bit of CR6.
|
||||
BitNo = 2; InvertBit = false;
|
||||
break;
|
||||
case 3: // Return the inverted value of the LT bit of CR6.
|
||||
BitNo = 2; InvertBit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Shift the bit into the low position.
|
||||
Flags = DAG.getNode(ISD::SRL, MVT::i32, Flags,
|
||||
DAG.getConstant(8-(3-BitNo), MVT::i32));
|
||||
// Isolate the bit.
|
||||
Flags = DAG.getNode(ISD::AND, MVT::i32, Flags,
|
||||
DAG.getConstant(1, MVT::i32));
|
||||
|
||||
// If we are supposed to, toggle the bit.
|
||||
if (InvertBit)
|
||||
Flags = DAG.getNode(ISD::XOR, MVT::i32, Flags,
|
||||
DAG.getConstant(1, MVT::i32));
|
||||
return Flags;
|
||||
}
|
||||
}
|
||||
return SDOperand();
|
||||
}
|
||||
|
@ -88,6 +88,17 @@ namespace llvm {
|
||||
|
||||
/// Return with a flag operand, matched by 'blr'
|
||||
RET_FLAG,
|
||||
|
||||
/// R32 = MFCR(CRREG, INFLAG) - Represents the MFCR/MFOCRF instructions.
|
||||
/// This copies the bits corresponding to the specified CRREG into the
|
||||
/// resultant GPR. Bits corresponding to other CR regs are undefined.
|
||||
MFCR,
|
||||
|
||||
/// RESVEC, OUTFLAG = VCMPo(LHS, RHS, OPC) - Represents one of the
|
||||
/// altivec VCMP*o instructions. For lack of better number, we use the
|
||||
/// opcode number encoding for the OPC field to identify the compare. For
|
||||
/// example, 838 is VCMPGTSH.
|
||||
VCMPo
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -306,28 +306,32 @@ def VCMPBFP : VXRForm_1<966, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
(int_ppc_altivec_vcmpbfp VRRC:$vA, VRRC:$vB))]>;
|
||||
def VCMPBFPo : VXRForm_1<966, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpbfp. $vD, $vA, $vB", VecFPCompare,
|
||||
[]>, isVDOT;
|
||||
[(set VRRC:$vD, (v4f32
|
||||
(PPCvcmp_o VRRC:$vA, VRRC:$vB, 966)))]>, isVDOT;
|
||||
def VCMPEQFP : VXRForm_1<198, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpeqfp $vD, $vA, $vB", VecFPCompare,
|
||||
[(set VRRC:$vD,
|
||||
(int_ppc_altivec_vcmpeqfp VRRC:$vA, VRRC:$vB))]>;
|
||||
def VCMPEQFPo : VXRForm_1<198, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpeqfp. $vD, $vA, $vB", VecFPCompare,
|
||||
[]>, isVDOT;
|
||||
[(set VRRC:$vD, (v4f32
|
||||
(PPCvcmp_o VRRC:$vA, VRRC:$vB, 198)))]>, isVDOT;
|
||||
def VCMPGEFP : VXRForm_1<454, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpgefp $vD, $vA, $vB", VecFPCompare,
|
||||
[(set VRRC:$vD,
|
||||
(int_ppc_altivec_vcmpgefp VRRC:$vA, VRRC:$vB))]>;
|
||||
def VCMPGEFPo : VXRForm_1<454, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpgefp. $vD, $vA, $vB", VecFPCompare,
|
||||
[]>, isVDOT;
|
||||
[(set VRRC:$vD, (v4f32
|
||||
(PPCvcmp_o VRRC:$vA, VRRC:$vB, 454)))]>, isVDOT;
|
||||
def VCMPGTFP : VXRForm_1<710, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpgtfp $vD, $vA, $vB", VecFPCompare,
|
||||
[(set VRRC:$vD,
|
||||
(int_ppc_altivec_vcmpgtfp VRRC:$vA, VRRC:$vB))]>;
|
||||
def VCMPGTFPo : VXRForm_1<710, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpgtfp. $vD, $vA, $vB", VecFPCompare,
|
||||
[]>, isVDOT;
|
||||
[(set VRRC:$vD, (v4f32
|
||||
(PPCvcmp_o VRRC:$vA, VRRC:$vB, 710)))]>, isVDOT;
|
||||
|
||||
// i8 element comparisons.
|
||||
def VCMPEQUB : VXRForm_1<6, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
@ -336,21 +340,24 @@ def VCMPEQUB : VXRForm_1<6, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
(int_ppc_altivec_vcmpequb VRRC:$vA, VRRC:$vB))]>;
|
||||
def VCMPEQUBo : VXRForm_1<6, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpequb. $vD, $vA, $vB", VecFPCompare,
|
||||
[]>, isVDOT;
|
||||
[(set VRRC:$vD, (v16i8
|
||||
(PPCvcmp_o VRRC:$vA, VRRC:$vB, 6)))]>, isVDOT;
|
||||
def VCMPGTSB : VXRForm_1<774, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpgtsb $vD, $vA, $vB", VecFPCompare,
|
||||
[(set VRRC:$vD,
|
||||
(int_ppc_altivec_vcmpgtsb VRRC:$vA, VRRC:$vB))]>;
|
||||
def VCMPGTSBo : VXRForm_1<774, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpgtsb. $vD, $vA, $vB", VecFPCompare,
|
||||
[]>, isVDOT;
|
||||
[(set VRRC:$vD, (v16i8
|
||||
(PPCvcmp_o VRRC:$vA, VRRC:$vB, 774)))]>, isVDOT;
|
||||
def VCMPGTUB : VXRForm_1<518, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpgtub $vD, $vA, $vB", VecFPCompare,
|
||||
[(set VRRC:$vD,
|
||||
(int_ppc_altivec_vcmpgtub VRRC:$vA, VRRC:$vB))]>;
|
||||
def VCMPGTUBo : VXRForm_1<518, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpgtub. $vD, $vA, $vB", VecFPCompare,
|
||||
[]>, isVDOT;
|
||||
[(set VRRC:$vD, (v16i8
|
||||
(PPCvcmp_o VRRC:$vA, VRRC:$vB, 518)))]>, isVDOT;
|
||||
|
||||
// i16 element comparisons.
|
||||
def VCMPEQUH : VXRForm_1<70, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
@ -359,21 +366,24 @@ def VCMPEQUH : VXRForm_1<70, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
(int_ppc_altivec_vcmpequh VRRC:$vA, VRRC:$vB))]>;
|
||||
def VCMPEQUHo : VXRForm_1<70, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpequh. $vD, $vA, $vB", VecFPCompare,
|
||||
[]>, isVDOT;
|
||||
[(set VRRC:$vD, (v8i16
|
||||
(PPCvcmp_o VRRC:$vA, VRRC:$vB, 70)))]>, isVDOT;
|
||||
def VCMPGTSH : VXRForm_1<838, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpgtsh $vD, $vA, $vB", VecFPCompare,
|
||||
[(set VRRC:$vD,
|
||||
(int_ppc_altivec_vcmpgtsh VRRC:$vA, VRRC:$vB))]>;
|
||||
def VCMPGTSHo : VXRForm_1<838, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpgtsh. $vD, $vA, $vB", VecFPCompare,
|
||||
[]>, isVDOT;
|
||||
[(set VRRC:$vD, (v8i16
|
||||
(PPCvcmp_o VRRC:$vA, VRRC:$vB, 838)))]>, isVDOT;
|
||||
def VCMPGTUH : VXRForm_1<582, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpgtuh $vD, $vA, $vB", VecFPCompare,
|
||||
[(set VRRC:$vD,
|
||||
(int_ppc_altivec_vcmpgtuh VRRC:$vA, VRRC:$vB))]>;
|
||||
def VCMPGTUHo : VXRForm_1<582, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpgtuh. $vD, $vA, $vB", VecFPCompare,
|
||||
[]>, isVDOT;
|
||||
[(set VRRC:$vD, (v8i16
|
||||
(PPCvcmp_o VRRC:$vA, VRRC:$vB, 582)))]>, isVDOT;
|
||||
|
||||
// i32 element comparisons.
|
||||
def VCMPEQUW : VXRForm_1<134, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
@ -382,21 +392,24 @@ def VCMPEQUW : VXRForm_1<134, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
(int_ppc_altivec_vcmpequw VRRC:$vA, VRRC:$vB))]>;
|
||||
def VCMPEQUWo : VXRForm_1<134, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpequw. $vD, $vA, $vB", VecFPCompare,
|
||||
[]>, isVDOT;
|
||||
[(set VRRC:$vD, (v4i32
|
||||
(PPCvcmp_o VRRC:$vA, VRRC:$vB, 134)))]>, isVDOT;
|
||||
def VCMPGTSW : VXRForm_1<902, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpgtsw $vD, $vA, $vB", VecFPCompare,
|
||||
[(set VRRC:$vD,
|
||||
(int_ppc_altivec_vcmpgtsw VRRC:$vA, VRRC:$vB))]>;
|
||||
def VCMPGTSWo : VXRForm_1<902, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpgtsw. $vD, $vA, $vB", VecFPCompare,
|
||||
[]>, isVDOT;
|
||||
[(set VRRC:$vD, (v4i32
|
||||
(PPCvcmp_o VRRC:$vA, VRRC:$vB, 902)))]>, isVDOT;
|
||||
def VCMPGTUW : VXRForm_1<646, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpgtuw $vD, $vA, $vB", VecFPCompare,
|
||||
[(set VRRC:$vD,
|
||||
(int_ppc_altivec_vcmpgtuw VRRC:$vA, VRRC:$vB))]>;
|
||||
def VCMPGTUWo : VXRForm_1<646, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
"vcmpgtuw. $vD, $vA, $vB", VecFPCompare,
|
||||
[]>, isVDOT;
|
||||
[(set VRRC:$vD, (v4i32
|
||||
(PPCvcmp_o VRRC:$vA, VRRC:$vB, 646)))]>, isVDOT;
|
||||
|
||||
def V_SET0 : VXForm_setzero<1220, (ops VRRC:$vD),
|
||||
"vxor $vD, $vD, $vD", VecFP,
|
||||
|
@ -30,6 +30,10 @@ def SDT_PPCvperm : SDTypeProfile<1, 3, [
|
||||
SDTCisVT<3, v16i8>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>
|
||||
]>;
|
||||
|
||||
def SDT_PPCvcmp_o : SDTypeProfile<1, 3, [
|
||||
SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>, SDTCisVT<3, i32>
|
||||
]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PowerPC specific DAG Nodes.
|
||||
//
|
||||
@ -68,6 +72,8 @@ def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_PPCCallSeq,[SDNPHasChain]>;
|
||||
def retflag : SDNode<"PPCISD::RET_FLAG", SDT_PPCRetFlag,
|
||||
[SDNPHasChain, SDNPOptInFlag]>;
|
||||
|
||||
def PPCvcmp_o : SDNode<"PPCISD::VCMPo", SDT_PPCvcmp_o, [SDNPOutFlag]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PowerPC specific transformation functions and pattern fragments.
|
||||
//
|
||||
@ -701,11 +707,11 @@ def MFVRSAVE : XFXForm_1_ext<31, 339, 256, (ops GPRC:$rT),
|
||||
"mfspr $rT, 256", IntGeneral>,
|
||||
PPC970_DGroup_First, PPC970_Unit_FXU;
|
||||
|
||||
def MFCR : XFXForm_3<31, 19, (ops GPRC:$rT), "mfcr $rT", SprMFCR>,
|
||||
PPC970_MicroCode, PPC970_Unit_CRU;
|
||||
def MTCRF : XFXForm_5<31, 144, (ops crbitm:$FXM, GPRC:$rS),
|
||||
"mtcrf $FXM, $rS", BrMCRX>,
|
||||
PPC970_MicroCode, PPC970_Unit_CRU;
|
||||
def MFCR : XFXForm_3<31, 19, (ops GPRC:$rT), "mfcr $rT", SprMFCR>,
|
||||
PPC970_MicroCode, PPC970_Unit_CRU;
|
||||
def MFOCRF: XFXForm_5a<31, 19, (ops GPRC:$rT, crbitm:$FXM),
|
||||
"mfcr $rT, $FXM", SprMFCR>,
|
||||
PPC970_DGroup_First, PPC970_Unit_CRU;
|
||||
|
Loading…
Reference in New Issue
Block a user